1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.objects;
27
28import static jdk.nashorn.internal.lookup.Lookup.MH;
29import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
30import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
31import static jdk.nashorn.internal.runtime.JSType.isString;
32import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
33
34import java.io.IOException;
35import java.io.PrintWriter;
36import java.lang.invoke.MethodHandle;
37import java.lang.invoke.MethodHandles;
38import java.lang.invoke.MethodType;
39import java.lang.invoke.SwitchPoint;
40import java.lang.reflect.Field;
41import java.util.ArrayList;
42import java.util.Arrays;
43import java.util.List;
44import java.util.Map;
45import java.util.Objects;
46import java.util.concurrent.Callable;
47import java.util.concurrent.ConcurrentHashMap;
48import javax.script.ScriptContext;
49import javax.script.ScriptEngine;
50import jdk.dynalink.CallSiteDescriptor;
51import jdk.dynalink.linker.GuardedInvocation;
52import jdk.dynalink.linker.LinkRequest;
53import jdk.nashorn.api.scripting.ClassFilter;
54import jdk.nashorn.api.scripting.ScriptObjectMirror;
55import jdk.nashorn.internal.lookup.Lookup;
56import jdk.nashorn.internal.objects.annotations.Attribute;
57import jdk.nashorn.internal.objects.annotations.Getter;
58import jdk.nashorn.internal.objects.annotations.Property;
59import jdk.nashorn.internal.objects.annotations.ScriptClass;
60import jdk.nashorn.internal.objects.annotations.Setter;
61import jdk.nashorn.internal.runtime.Context;
62import jdk.nashorn.internal.runtime.ECMAErrors;
63import jdk.nashorn.internal.runtime.FindProperty;
64import jdk.nashorn.internal.runtime.GlobalConstants;
65import jdk.nashorn.internal.runtime.GlobalFunctions;
66import jdk.nashorn.internal.runtime.JSType;
67import jdk.nashorn.internal.runtime.NativeJavaPackage;
68import jdk.nashorn.internal.runtime.PropertyDescriptor;
69import jdk.nashorn.internal.runtime.PropertyMap;
70import jdk.nashorn.internal.runtime.Scope;
71import jdk.nashorn.internal.runtime.ScriptEnvironment;
72import jdk.nashorn.internal.runtime.ScriptFunction;
73import jdk.nashorn.internal.runtime.ScriptObject;
74import jdk.nashorn.internal.runtime.ScriptRuntime;
75import jdk.nashorn.internal.runtime.ScriptingFunctions;
76import jdk.nashorn.internal.runtime.Specialization;
77import jdk.nashorn.internal.runtime.Symbol;
78import jdk.nashorn.internal.runtime.arrays.ArrayData;
79import jdk.nashorn.internal.runtime.linker.Bootstrap;
80import jdk.nashorn.internal.runtime.linker.InvokeByName;
81import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
82import jdk.nashorn.internal.runtime.regexp.RegExpResult;
83import jdk.nashorn.internal.scripts.JD;
84import jdk.nashorn.internal.scripts.JO;
85import jdk.nashorn.tools.ShellFunctions;
86
87/**
88 * Representation of global scope.
89 */
90@ScriptClass("Global")
91public final class Global extends Scope {
92    // This special value is used to flag a lazily initialized global property.
93    private static final Object LAZY_SENTINEL = new Object();
94    // This serves as placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
95    private static final Object LOCATION_PLACEHOLDER = new Object();
96
97    private static final String PACKAGE_PREFIX = "jdk.nashorn.internal.objects.";
98
99    private InvokeByName TO_STRING;
100    private InvokeByName VALUE_OF;
101
102    /**
103     * Optimistic builtin names that require switchpoint invalidation
104     * upon assignment. Overly conservative, but works for now, to avoid
105     * any complicated scope checks and especially heavy weight guards
106     * like
107     *
108     * <pre>
109     *     public boolean setterGuard(final Object receiver) {
110     *         final Global          global = Global.instance();
111     *         final ScriptObject    sobj   = global.getFunctionPrototype();
112     *         final Object          apply  = sobj.get("apply");
113     *         return apply == receiver;
114     *     }
115     * </pre>
116     *
117     * Naturally, checking for builtin classes like NativeFunction is cheaper,
118     * it's when you start adding property checks for said builtins you have
119     * problems with guard speed.
120     */
121
122    /** Nashorn extension: arguments array */
123    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
124    public Object arguments;
125
126    /** ECMA 15.1.2.2 parseInt (string , radix) */
127    @Property(attributes = Attribute.NOT_ENUMERABLE)
128    public Object parseInt;
129
130    /** ECMA 15.1.2.3 parseFloat (string) */
131    @Property(attributes = Attribute.NOT_ENUMERABLE)
132    public Object parseFloat;
133
134    /** ECMA 15.1.2.4 isNaN (number) */
135    @Property(attributes = Attribute.NOT_ENUMERABLE)
136    public Object isNaN;
137
138    /** ECMA 15.1.2.5 isFinite (number) */
139    @Property(attributes = Attribute.NOT_ENUMERABLE)
140    public Object isFinite;
141
142    /** ECMA 15.1.3.3 encodeURI */
143    @Property(attributes = Attribute.NOT_ENUMERABLE)
144    public Object encodeURI;
145
146    /** ECMA 15.1.3.4 encodeURIComponent */
147    @Property(attributes = Attribute.NOT_ENUMERABLE)
148    public Object encodeURIComponent;
149
150    /** ECMA 15.1.3.1 decodeURI */
151    @Property(attributes = Attribute.NOT_ENUMERABLE)
152    public Object decodeURI;
153
154    /** ECMA 15.1.3.2 decodeURIComponent */
155    @Property(attributes = Attribute.NOT_ENUMERABLE)
156    public Object decodeURIComponent;
157
158    /** ECMA B.2.1 escape (string) */
159    @Property(attributes = Attribute.NOT_ENUMERABLE)
160    public Object escape;
161
162    /** ECMA B.2.2 unescape (string) */
163    @Property(attributes = Attribute.NOT_ENUMERABLE)
164    public Object unescape;
165
166    /** Nashorn extension: global.print */
167    @Property(attributes = Attribute.NOT_ENUMERABLE)
168    public Object print;
169
170    /** Nashorn extension: global.load */
171    @Property(attributes = Attribute.NOT_ENUMERABLE)
172    public Object load;
173
174    /** Nashorn extension: global.loadWithNewGlobal */
175    @Property(attributes = Attribute.NOT_ENUMERABLE)
176    public Object loadWithNewGlobal;
177
178    /** Nashorn extension: global.exit */
179    @Property(attributes = Attribute.NOT_ENUMERABLE)
180    public Object exit;
181
182    /** Nashorn extension: global.quit */
183    @Property(attributes = Attribute.NOT_ENUMERABLE)
184    public Object quit;
185
186    /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
187    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
188    public static final double NaN = Double.NaN;
189
190    /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
191    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
192    public static final double Infinity = Double.POSITIVE_INFINITY;
193
194    /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
195    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
196    public static final Object undefined = UNDEFINED;
197
198    /** ECMA 15.1.2.1 eval(x) */
199    @Property(attributes = Attribute.NOT_ENUMERABLE)
200    public Object eval;
201
202    /** ECMA 15.1.4.1 Object constructor. */
203    @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
204    public volatile Object object;
205
206    /** ECMA 15.1.4.2 Function constructor. */
207    @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
208    public volatile Object function;
209
210    /** ECMA 15.1.4.3 Array constructor. */
211    @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
212    public volatile Object array;
213
214    /** ECMA 15.1.4.4 String constructor */
215    @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
216    public volatile Object string;
217
218    /** ECMA 15.1.4.5 Boolean constructor */
219    @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
220    public volatile Object _boolean;
221
222    /** ECMA 15.1.4.6 - Number constructor */
223    @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
224    public volatile Object number;
225
226
227    /**
228     * Getter for ECMA 15.1.4.7 Date property
229     *
230     * @param self self reference
231     * @return Date property value
232     */
233    @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
234    public static Object getDate(final Object self) {
235        final Global global = Global.instanceFrom(self);
236        if (global.date == LAZY_SENTINEL) {
237            global.date = global.getBuiltinDate();
238        }
239        return global.date;
240    }
241
242    /**
243     * Setter for ECMA 15.1.4.7 Date property
244     *
245     * @param self self reference
246     * @param value value for the Date property
247     */
248    @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
249    public static void setDate(final Object self, final Object value) {
250        final Global global = Global.instanceFrom(self);
251        global.date = value;
252    }
253
254    private volatile Object date = LAZY_SENTINEL;
255
256    /**
257     * Getter for ECMA 15.1.4.8 RegExp property
258     *
259     * @param self self reference
260     * @return RegExp property value
261     */
262    @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
263    public static Object getRegExp(final Object self) {
264        final Global global = Global.instanceFrom(self);
265        if (global.regexp == LAZY_SENTINEL) {
266            global.regexp = global.getBuiltinRegExp();
267        }
268        return global.regexp;
269    }
270
271    /**
272     * Setter for ECMA 15.1.4.8 RegExp property
273     *
274     * @param self self reference
275     * @param value value for the RegExp property
276     */
277    @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
278    public static void setRegExp(final Object self, final Object value) {
279        final Global global = Global.instanceFrom(self);
280        global.regexp = value;
281    }
282
283    private volatile Object regexp = LAZY_SENTINEL;
284
285    /**
286     * Getter for ECMA 15.12 - The JSON property
287     * @param self self reference
288     * @return the value of JSON property
289     */
290    @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
291    public static Object getJSON(final Object self) {
292        final Global global = Global.instanceFrom(self);
293        if (global.json == LAZY_SENTINEL) {
294            global.json = global.getBuiltinJSON();
295        }
296        return global.json;
297    }
298
299    /**
300     * Setter for ECMA 15.12 - The JSON property
301     * @param self self reference
302     * @param value value for the JSON property
303     */
304    @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
305    public static void setJSON(final Object self, final Object value) {
306        final Global global = Global.instanceFrom(self);
307        global.json = value;
308    }
309
310    private volatile Object json = LAZY_SENTINEL;
311
312    /**
313     * Getter for Nashorn extension: global.JSAdapter
314     * @param self self reference
315     * @return value of the JSAdapter property
316     */
317    @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
318    public static Object getJSAdapter(final Object self) {
319        final Global global = Global.instanceFrom(self);
320        if (global.jsadapter == LAZY_SENTINEL) {
321            global.jsadapter = global.getBuiltinJSAdapter();
322        }
323        return global.jsadapter;
324    }
325
326    /**
327     * Setter for Nashorn extension: global.JSAdapter
328     * @param self self reference
329     * @param value value for the JSAdapter property
330     */
331    @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
332    public static void setJSAdapter(final Object self, final Object value) {
333        final Global global = Global.instanceFrom(self);
334        global.jsadapter = value;
335    }
336
337    private volatile Object jsadapter = LAZY_SENTINEL;
338
339    /** ECMA 15.8 - The Math object */
340    @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
341    public volatile Object math;
342
343    /** Error object */
344    @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
345    public volatile Object error;
346
347    /**
348     * Getter for the EvalError property
349     * @param self self reference
350     * @return the value of EvalError property
351     */
352    @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
353    public static Object getEvalError(final Object self) {
354        final Global global = Global.instanceFrom(self);
355        if (global.evalError == LAZY_SENTINEL) {
356            global.evalError = global.getBuiltinEvalError();
357        }
358        return global.evalError;
359    }
360
361    /**
362     * Setter for the EvalError property
363     * @param self self reference
364     * @param value value of the EvalError property
365     */
366    @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
367    public static void setEvalError(final Object self, final Object value) {
368        final Global global = Global.instanceFrom(self);
369        global.evalError = value;
370    }
371
372    private volatile Object evalError = LAZY_SENTINEL;
373
374    /**
375     * Getter for the RangeError property.
376     * @param self self reference
377     * @return the value of RangeError property
378     */
379    @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
380    public static Object getRangeError(final Object self) {
381        final Global global = Global.instanceFrom(self);
382        if (global.rangeError == LAZY_SENTINEL) {
383            global.rangeError = global.getBuiltinRangeError();
384        }
385        return global.rangeError;
386    }
387
388
389    /**
390     * Setter for the RangeError property.
391     * @param self self reference
392     * @param value value for the RangeError property
393     */
394    @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
395    public static void setRangeError(final Object self, final Object value) {
396        final Global global = Global.instanceFrom(self);
397        global.rangeError = value;
398    }
399
400    private volatile Object rangeError = LAZY_SENTINEL;
401
402    /** ReferenceError object */
403    @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
404    public volatile Object referenceError;
405
406    /** SyntaxError object */
407    @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
408    public volatile Object syntaxError;
409
410    /** TypeError object */
411    @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
412    public volatile Object typeError;
413
414    /**
415     * Getter for the URIError property.
416     * @param self self reference
417     * @return the value of URIError property
418     */
419    @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
420    public static Object getURIError(final Object self) {
421        final Global global = Global.instanceFrom(self);
422        if (global.uriError == LAZY_SENTINEL) {
423            global.uriError = global.getBuiltinURIError();
424        }
425        return global.uriError;
426    }
427
428    /**
429     * Setter for the URIError property.
430     * @param self self reference
431     * @param value value for the URIError property
432     */
433    @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
434    public static void setURIError(final Object self, final Object value) {
435        final Global global = Global.instanceFrom(self);
436        global.uriError = value;
437    }
438
439    private volatile Object uriError = LAZY_SENTINEL;
440
441    /**
442     * Getter for the ArrayBuffer property.
443     * @param self self reference
444     * @return the value of the ArrayBuffer property
445     */
446    @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
447    public static Object getArrayBuffer(final Object self) {
448        final Global global = Global.instanceFrom(self);
449        if (global.arrayBuffer == LAZY_SENTINEL) {
450            global.arrayBuffer = global.getBuiltinArrayBuffer();
451        }
452        return global.arrayBuffer;
453    }
454
455    /**
456     * Setter for the ArrayBuffer property.
457     * @param self self reference
458     * @param value value of the ArrayBuffer property
459     */
460    @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
461    public static void setArrayBuffer(final Object self, final Object value) {
462        final Global global = Global.instanceFrom(self);
463        global.arrayBuffer = value;
464    }
465
466    private volatile Object arrayBuffer;
467
468    /**
469     * Getter for the DataView property.
470     * @param self self reference
471     * @return the value of the DataView property
472     */
473    @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
474    public static Object getDataView(final Object self) {
475        final Global global = Global.instanceFrom(self);
476        if (global.dataView == LAZY_SENTINEL) {
477            global.dataView = global.getBuiltinDataView();
478        }
479        return global.dataView;
480    }
481
482
483    /**
484     * Setter for the DataView property.
485     * @param self self reference
486     * @param value value of the DataView property
487     */
488    @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
489    public static void setDataView(final Object self, final Object value) {
490        final Global global = Global.instanceFrom(self);
491        global.dataView = value;
492    }
493
494    private volatile Object dataView;
495
496    /**
497     * Getter for the Int8Array property.
498     * @param self self reference
499     * @return the value of the Int8Array property.
500     */
501    @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
502    public static Object getInt8Array(final Object self) {
503        final Global global = Global.instanceFrom(self);
504        if (global.int8Array == LAZY_SENTINEL) {
505            global.int8Array = global.getBuiltinInt8Array();
506        }
507        return global.int8Array;
508    }
509
510    /**
511     * Setter for the Int8Array property.
512     * @param self self reference
513     * @param value value of the Int8Array property
514     */
515    @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
516    public static void setInt8Array(final Object self, final Object value) {
517        final Global global = Global.instanceFrom(self);
518        global.int8Array = value;
519    }
520
521    private volatile Object int8Array;
522
523    /**
524     * Getter for the Uin8Array property.
525     * @param self self reference
526     * @return the value of the Uint8Array property
527     */
528    @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
529    public static Object getUint8Array(final Object self) {
530        final Global global = Global.instanceFrom(self);
531        if (global.uint8Array == LAZY_SENTINEL) {
532            global.uint8Array = global.getBuiltinUint8Array();
533        }
534        return global.uint8Array;
535    }
536
537    /**
538     * Setter for the Uin8Array property.
539     * @param self self reference
540     * @param value value of the Uin8Array property
541     */
542    @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
543    public static void setUint8Array(final Object self, final Object value) {
544        final Global global = Global.instanceFrom(self);
545        global.uint8Array = value;
546    }
547
548    private volatile Object uint8Array;
549
550    /**
551     * Getter for the Uint8ClampedArray property.
552     * @param self self reference
553     * @return the value of the Uint8ClampedArray property
554     */
555    @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
556    public static Object getUint8ClampedArray(final Object self) {
557        final Global global = Global.instanceFrom(self);
558        if (global.uint8ClampedArray == LAZY_SENTINEL) {
559            global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
560        }
561        return global.uint8ClampedArray;
562    }
563
564    /**
565     * Setter for the Uint8ClampedArray property.
566     * @param self self reference
567     * @param value value of the Uint8ClampedArray property
568     */
569    @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
570    public static void setUint8ClampedArray(final Object self, final Object value) {
571        final Global global = Global.instanceFrom(self);
572        global.uint8ClampedArray = value;
573    }
574
575    private volatile Object uint8ClampedArray;
576
577    /**
578     * Getter for the Int16Array property.
579     * @param self self reference
580     * @return the value of the Int16Array property
581     */
582    @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
583    public static Object getInt16Array(final Object self) {
584        final Global global = Global.instanceFrom(self);
585        if (global.int16Array == LAZY_SENTINEL) {
586            global.int16Array = global.getBuiltinInt16Array();
587        }
588        return global.int16Array;
589    }
590
591    /**
592     * Setter for the Int16Array property.
593     * @param self self reference
594     * @param value value of the Int16Array property
595     */
596    @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
597    public static void setInt16Array(final Object self, final Object value) {
598        final Global global = Global.instanceFrom(self);
599        global.int16Array = value;
600    }
601
602    private volatile Object int16Array;
603
604    /**
605     * Getter for the Uint16Array property.
606     * @param self self reference
607     * @return the value of the Uint16Array property
608     */
609    @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
610    public static Object getUint16Array(final Object self) {
611        final Global global = Global.instanceFrom(self);
612        if (global.uint16Array == LAZY_SENTINEL) {
613            global.uint16Array = global.getBuiltinUint16Array();
614        }
615        return global.uint16Array;
616    }
617
618    /**
619     * Setter for the Uint16Array property.
620     * @param self self reference
621     * @param value value of the Uint16Array property
622     */
623    @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
624    public static void setUint16Array(final Object self, final Object value) {
625        final Global global = Global.instanceFrom(self);
626        global.uint16Array = value;
627    }
628
629    private volatile Object uint16Array;
630
631    /**
632     * Getter for the Int32Array property.
633     *
634     * @param self self reference
635     * @return the value of the Int32Array property
636     */
637    @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
638    public static Object getInt32Array(final Object self) {
639        final Global global = Global.instanceFrom(self);
640        if (global.int32Array == LAZY_SENTINEL) {
641            global.int32Array = global.getBuiltinInt32Array();
642        }
643        return global.int32Array;
644    }
645
646
647    /**
648     * Setter for the Int32Array property.
649     *
650     * @param self self reference
651     * @param value value of the Int32Array property
652     */
653    @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
654    public static void setInt32Array(final Object self, final Object value) {
655        final Global global = Global.instanceFrom(self);
656        global.int32Array = value;
657    }
658
659    private volatile Object int32Array;
660
661    /**
662     * Getter of the Uint32Array property.
663     *
664     * @param self self reference
665     * @return the value of the Uint32Array property
666     */
667    @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
668    public static Object getUint32Array(final Object self) {
669        final Global global = Global.instanceFrom(self);
670        if (global.uint32Array == LAZY_SENTINEL) {
671            global.uint32Array = global.getBuiltinUint32Array();
672        }
673        return global.uint32Array;
674    }
675
676
677    /**
678     * Setter of the Uint32Array property.
679     *
680     * @param self self reference
681     * @param value value of the Uint32Array property
682     */
683    @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
684    public static void setUint32Array(final Object self, final Object value) {
685        final Global global = Global.instanceFrom(self);
686        global.uint32Array = value;
687    }
688
689    private volatile Object uint32Array;
690
691    /**
692     * Getter for the Float32Array property.
693     *
694     * @param self self reference
695     * @return the value of the Float32Array property
696     */
697    @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
698    public static Object getFloat32Array(final Object self) {
699        final Global global = Global.instanceFrom(self);
700        if (global.float32Array == LAZY_SENTINEL) {
701            global.float32Array = global.getBuiltinFloat32Array();
702        }
703        return global.float32Array;
704    }
705
706    /**
707     * Setter for the Float32Array property.
708     *
709     * @param self self reference
710     * @param value value of the Float32Array property
711     */
712    @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
713    public static void setFloat32Array(final Object self, final Object value) {
714        final Global global = Global.instanceFrom(self);
715        global.float32Array = value;
716    }
717
718    private volatile Object float32Array;
719
720    /**
721     * Getter for the Float64Array property.
722     *
723     * @param self self reference
724     * @return the value of the Float64Array property
725     */
726    @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
727    public static Object getFloat64Array(final Object self) {
728        final Global global = Global.instanceFrom(self);
729        if (global.float64Array == LAZY_SENTINEL) {
730            global.float64Array = global.getBuiltinFloat64Array();
731        }
732        return global.float64Array;
733    }
734
735    /**
736     * Setter for the Float64Array property.
737     *
738     * @param self self reference
739     * @param value value of the Float64Array property
740     */
741    @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
742    public static void setFloat64Array(final Object self, final Object value) {
743        final Global global = Global.instanceFrom(self);
744        global.float64Array = value;
745    }
746
747    private volatile Object float64Array;
748
749
750    /**
751     * Getter for the Symbol property.
752     *
753     * @param self self reference
754     * @return  the value of the Symbol property
755     */
756    @Getter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE)
757    public static Object getSymbol(final Object self) {
758        final Global global = Global.instanceFrom(self);
759        if (global.symbol == LAZY_SENTINEL) {
760            global.symbol = global.getBuiltinSymbol();
761        }
762        return global.symbol;
763    }
764
765    /**
766     * Setter for the Symbol property.
767     *
768     * @param self self reference
769     * @param value value of the Symbol property
770     */
771    @Setter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE)
772    public static void setSymbol(final Object self, final Object value) {
773        Global.instanceFrom(self).symbol = value;
774    }
775
776    private volatile Object symbol;
777
778    /**
779     * Getter for the Map property.
780     *
781     * @param self self reference
782     * @return  the value of the Map property
783     */
784    @Getter(name = "Map", attributes = Attribute.NOT_ENUMERABLE)
785    public static Object getMap(final Object self) {
786        final Global global = Global.instanceFrom(self);
787        if (global.map == LAZY_SENTINEL) {
788            global.map = global.getBuiltinMap();
789        }
790        return global.map;
791    }
792
793    /**
794     * Setter for the Map property.
795     *
796     * @param self self reference
797     * @param value value of the Map property
798     */
799    @Setter(name = "Map", attributes = Attribute.NOT_ENUMERABLE)
800    public static void setMap(final Object self, final Object value) {
801        Global.instanceFrom(self).map = value;
802    }
803
804    private volatile Object map;
805
806    /**
807     * Getter for the WeakMap property.
808     *
809     * @param self self reference
810     * @return  the value of the WeakMap property
811     */
812    @Getter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE)
813    public static Object getWeakMap(final Object self) {
814        final Global global = Global.instanceFrom(self);
815        if (global.weakMap == LAZY_SENTINEL) {
816            global.weakMap = global.getBuiltinWeakMap();
817        }
818        return global.weakMap;
819    }
820
821    /**
822     * Setter for the WeakMap property.
823     *
824     * @param self self reference
825     * @param value value of the WeakMap property
826     */
827    @Setter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE)
828    public static void setWeakMap(final Object self, final Object value) {
829        Global.instanceFrom(self).weakMap = value;
830    }
831
832    private volatile Object weakMap;
833
834    /**
835     * Getter for the Set property.
836     *
837     * @param self self reference
838     * @return  the value of the Set property
839     */
840    @Getter(name = "Set", attributes = Attribute.NOT_ENUMERABLE)
841    public static Object getSet(final Object self) {
842        final Global global = Global.instanceFrom(self);
843        if (global.set == LAZY_SENTINEL) {
844            global.set = global.getBuiltinSet();
845        }
846        return global.set;
847    }
848
849    /**
850     * Setter for the Set property.
851     *
852     * @param self self reference
853     * @param value value of the Set property
854     */
855    @Setter(name = "Set", attributes = Attribute.NOT_ENUMERABLE)
856    public static void setSet(final Object self, final Object value) {
857        Global.instanceFrom(self).set = value;
858    }
859
860    private volatile Object set;
861
862    /**
863     * Getter for the WeakSet property.
864     *
865     * @param self self reference
866     * @return  the value of the WeakSet property
867     */
868    @Getter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE)
869    public static Object getWeakSet(final Object self) {
870        final Global global = Global.instanceFrom(self);
871        if (global.weakSet == LAZY_SENTINEL) {
872            global.weakSet = global.getBuiltinWeakSet();
873        }
874        return global.weakSet;
875    }
876
877    /**
878     * Setter for the WeakSet property.
879     *
880     * @param self self reference
881     * @param value value of the WeakSet property
882     */
883    @Setter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE)
884    public static void setWeakSet(final Object self, final Object value) {
885        Global.instanceFrom(self).weakSet = value;
886    }
887
888    private volatile Object weakSet;
889
890    /** Nashorn extension: Java access - global.Packages */
891    @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
892    public volatile Object packages;
893
894    /** Nashorn extension: Java access - global.com */
895    @Property(attributes = Attribute.NOT_ENUMERABLE)
896    public volatile Object com;
897
898    /** Nashorn extension: Java access - global.edu */
899    @Property(attributes = Attribute.NOT_ENUMERABLE)
900    public volatile Object edu;
901
902    /** Nashorn extension: Java access - global.java */
903    @Property(attributes = Attribute.NOT_ENUMERABLE)
904    public volatile Object java;
905
906    /** Nashorn extension: Java access - global.javafx */
907    @Property(attributes = Attribute.NOT_ENUMERABLE)
908    public volatile Object javafx;
909
910    /** Nashorn extension: Java access - global.javax */
911    @Property(attributes = Attribute.NOT_ENUMERABLE)
912    public volatile Object javax;
913
914    /** Nashorn extension: Java access - global.org */
915    @Property(attributes = Attribute.NOT_ENUMERABLE)
916    public volatile Object org;
917
918    /**
919     * Getter for the Nashorn extension: Java access - global.JavaImporter.
920     *
921     * @param self self reference
922     * @return the value of the JavaImporter property
923     */
924    @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
925    public static Object getJavaImporter(final Object self) {
926        final Global global = Global.instanceFrom(self);
927        if (global.javaImporter == LAZY_SENTINEL) {
928            global.javaImporter = global.getBuiltinJavaImporter();
929        }
930        return global.javaImporter;
931    }
932
933    /**
934     * Setter for the Nashorn extension: Java access - global.JavaImporter.
935     *
936     * @param self self reference
937     * @param value value of the JavaImporter property
938     */
939    @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
940    public static void setJavaImporter(final Object self, final Object value) {
941        final Global global = Global.instanceFrom(self);
942        global.javaImporter = value;
943    }
944
945    private volatile Object javaImporter;
946
947    /**
948     * Getter for the Nashorn extension: global.Java property.
949     *
950     * @param self self reference
951     * @return the value of the Java property
952     */
953    @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
954    public static Object getJavaApi(final Object self) {
955        final Global global = Global.instanceFrom(self);
956        if (global.javaApi == LAZY_SENTINEL) {
957            global.javaApi = global.getBuiltinJavaApi();
958        }
959        return global.javaApi;
960    }
961
962    /**
963     * Setter for the Nashorn extension: global.Java property.
964     *
965     * @param self self reference
966     * @param value value of the Java property
967     */
968    @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
969    public static void setJavaApi(final Object self, final Object value) {
970        final Global global = Global.instanceFrom(self);
971        global.javaApi = value;
972    }
973
974    private volatile Object javaApi;
975
976    /** Nashorn extension: current script's file name */
977    @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
978    public static final Object __FILE__ = LOCATION_PLACEHOLDER;
979
980    /** Nashorn extension: current script's directory */
981    @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
982    public static final Object __DIR__ = LOCATION_PLACEHOLDER;
983
984    /** Nashorn extension: current source line number being executed */
985    @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
986    public static final Object __LINE__ = LOCATION_PLACEHOLDER;
987
988    private volatile NativeDate DEFAULT_DATE;
989
990    /** Used as Date.prototype's default value */
991    NativeDate getDefaultDate() {
992        return DEFAULT_DATE;
993    }
994
995    private volatile NativeRegExp DEFAULT_REGEXP;
996
997    /** Used as RegExp.prototype's default value */
998    NativeRegExp getDefaultRegExp() {
999        return DEFAULT_REGEXP;
1000    }
1001
1002    /*
1003     * Built-in constructor objects: Even if user changes dynamic values of
1004     * "Object", "Array" etc., we still want to keep original values of these
1005     * constructors here. For example, we need to be able to create array,
1006     * regexp literals even after user overwrites global "Array" or "RegExp"
1007     * constructor - see also ECMA 262 spec. Annex D.
1008     */
1009    private ScriptFunction builtinFunction;
1010    private ScriptFunction builtinObject;
1011    private ScriptFunction builtinArray;
1012    private ScriptFunction builtinBoolean;
1013    private ScriptFunction builtinDate;
1014    private ScriptObject   builtinJSON;
1015    private ScriptFunction builtinJSAdapter;
1016    private ScriptObject   builtinMath;
1017    private ScriptFunction builtinNumber;
1018    private ScriptFunction builtinRegExp;
1019    private ScriptFunction builtinString;
1020    private ScriptFunction builtinError;
1021    private ScriptFunction builtinEval;
1022    private ScriptFunction builtinEvalError;
1023    private ScriptFunction builtinRangeError;
1024    private ScriptFunction builtinReferenceError;
1025    private ScriptFunction builtinSyntaxError;
1026    private ScriptFunction builtinTypeError;
1027    private ScriptFunction builtinURIError;
1028    private ScriptObject   builtinPackages;
1029    private ScriptObject   builtinCom;
1030    private ScriptObject   builtinEdu;
1031    private ScriptObject   builtinJava;
1032    private ScriptObject   builtinJavafx;
1033    private ScriptObject   builtinJavax;
1034    private ScriptObject   builtinOrg;
1035    private ScriptFunction builtinJavaImporter;
1036    private ScriptObject   builtinJavaApi;
1037    private ScriptFunction builtinArrayBuffer;
1038    private ScriptFunction builtinDataView;
1039    private ScriptFunction builtinInt8Array;
1040    private ScriptFunction builtinUint8Array;
1041    private ScriptFunction builtinUint8ClampedArray;
1042    private ScriptFunction builtinInt16Array;
1043    private ScriptFunction builtinUint16Array;
1044    private ScriptFunction builtinInt32Array;
1045    private ScriptFunction builtinUint32Array;
1046    private ScriptFunction builtinFloat32Array;
1047    private ScriptFunction builtinFloat64Array;
1048    private ScriptFunction builtinSymbol;
1049    private ScriptFunction builtinMap;
1050    private ScriptFunction builtinWeakMap;
1051    private ScriptFunction builtinSet;
1052    private ScriptFunction builtinWeakSet;
1053    private ScriptObject   builtinIteratorPrototype;
1054    private ScriptObject   builtinMapIteratorPrototype;
1055    private ScriptObject   builtinSetIteratorPrototype;
1056    private ScriptObject   builtinArrayIteratorPrototype;
1057    private ScriptObject   builtinStringIteratorPrototype;
1058
1059    private ScriptFunction builtInJavaExtend;
1060    private ScriptFunction builtInJavaTo;
1061
1062    /*
1063     * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
1064     */
1065    private ScriptFunction typeErrorThrower;
1066
1067    // Used to store the last RegExp result to support deprecated RegExp constructor properties
1068    private RegExpResult lastRegExpResult;
1069
1070    private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
1071    private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
1072    private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
1073    private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
1074    private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
1075    private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
1076    private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
1077    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
1078
1079    // initialized by nasgen
1080    private static PropertyMap $nasgenmap$;
1081
1082    // context to which this global belongs to
1083    private final Context context;
1084
1085    // current ScriptContext to use - can be null.
1086    private ThreadLocal<ScriptContext> scontext;
1087    // current ScriptEngine associated - can be null.
1088    private ScriptEngine engine;
1089    // initial ScriptContext - usually null and only used for special case
1090    private volatile ScriptContext initscontext;
1091
1092    // ES6 global lexical scope.
1093    private final LexicalScope lexicalScope;
1094
1095    // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
1096    private SwitchPoint lexicalScopeSwitchPoint;
1097
1098    /**
1099     * Set the current script context
1100     * @param ctxt script context
1101     */
1102    public void setScriptContext(final ScriptContext ctxt) {
1103        assert scontext != null;
1104        scontext.set(ctxt);
1105    }
1106
1107    /**
1108     * Get the current script context
1109     * @return current script context
1110     */
1111    public ScriptContext getScriptContext() {
1112        assert scontext != null;
1113        return scontext.get();
1114    }
1115
1116    /**
1117     * Set the initial script context
1118     * @param ctxt initial script context
1119     */
1120    public void setInitScriptContext(final ScriptContext ctxt) {
1121        this.initscontext = ctxt;
1122    }
1123
1124    private ScriptContext currentContext() {
1125        final ScriptContext sc = scontext != null? scontext.get() : null;
1126        if (sc != null) {
1127            return sc;
1128        } else if (initscontext != null) {
1129            return initscontext;
1130        }
1131        return engine != null? engine.getContext() : null;
1132    }
1133
1134    @Override
1135    protected Context getContext() {
1136        return context;
1137    }
1138
1139    @Override
1140    protected boolean useDualFields() {
1141        return context.useDualFields();
1142    }
1143
1144    // performs initialization checks for Global constructor and returns the
1145    // PropertyMap, if everything is fine.
1146    private static PropertyMap checkAndGetMap(final Context context) {
1147        // security check first
1148        final SecurityManager sm = System.getSecurityManager();
1149        if (sm != null) {
1150            sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
1151        }
1152
1153        Objects.requireNonNull(context);
1154
1155        return $nasgenmap$;
1156    }
1157
1158    /**
1159     * Constructor
1160     *
1161     * @param context the context
1162     */
1163    public Global(final Context context) {
1164        super(checkAndGetMap(context));
1165        this.context = context;
1166        this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
1167    }
1168
1169    /**
1170     * Script access to "current" Global instance
1171     *
1172     * @return the global singleton
1173     */
1174    public static Global instance() {
1175        return Objects.requireNonNull(Context.getGlobal());
1176    }
1177
1178    private static Global instanceFrom(final Object self) {
1179        return self instanceof Global? (Global)self : instance();
1180    }
1181
1182    /**
1183     * Check if we have a Global instance
1184     * @return true if one exists
1185     */
1186    public static boolean hasInstance() {
1187        return Context.getGlobal() != null;
1188    }
1189
1190    /**
1191     * Script access to {@link ScriptEnvironment}
1192     *
1193     * @return the script environment
1194     */
1195    static ScriptEnvironment getEnv() {
1196        return instance().getContext().getEnv();
1197    }
1198
1199    /**
1200     * Script access to {@link Context}
1201     *
1202     * @return the context
1203     */
1204    static Context getThisContext() {
1205        return instance().getContext();
1206    }
1207
1208    // Runtime interface to Global
1209
1210    /**
1211     * Is there a class filter in the current Context?
1212     * @return class filter
1213     */
1214    public ClassFilter getClassFilter() {
1215        return context.getClassFilter();
1216    }
1217
1218    /**
1219     * Is this global of the given Context?
1220     * @param ctxt the context
1221     * @return true if this global belongs to the given Context
1222     */
1223    public boolean isOfContext(final Context ctxt) {
1224        return this.context == ctxt;
1225    }
1226
1227    /**
1228     * Does this global belong to a strict Context?
1229     * @return true if this global belongs to a strict Context
1230     */
1231    public boolean isStrictContext() {
1232        return context.getEnv()._strict;
1233    }
1234
1235    /**
1236     * Initialize standard builtin objects like "Object", "Array", "Function" etc.
1237     * as well as our extension builtin objects like "Java", "JSAdapter" as properties
1238     * of the global scope object.
1239     *
1240     * @param eng ScriptEngine to initialize
1241     */
1242    public void initBuiltinObjects(final ScriptEngine eng) {
1243        if (this.builtinObject != null) {
1244            // already initialized, just return
1245            return;
1246        }
1247
1248        TO_STRING = new InvokeByName("toString", ScriptObject.class);
1249        VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
1250
1251        this.engine = eng;
1252        if (this.engine != null) {
1253            this.scontext = new ThreadLocal<>();
1254        }
1255        init(eng);
1256    }
1257
1258    /**
1259     * Wrap a Java object as corresponding script object
1260     *
1261     * @param obj object to wrap
1262     * @return    wrapped object
1263     */
1264    public Object wrapAsObject(final Object obj) {
1265        if (obj instanceof Boolean) {
1266            return new NativeBoolean((Boolean)obj, this);
1267        } else if (obj instanceof Number) {
1268            return new NativeNumber(((Number)obj).doubleValue(), this);
1269        } else if (isString(obj)) {
1270            return new NativeString((CharSequence)obj, this);
1271        } else if (obj instanceof Object[]) { // extension
1272            return new NativeArray(ArrayData.allocate((Object[])obj), this);
1273        } else if (obj instanceof double[]) { // extension
1274            return new NativeArray(ArrayData.allocate((double[])obj), this);
1275        } else if (obj instanceof int[]) {
1276            return new NativeArray(ArrayData.allocate((int[]) obj), this);
1277        } else if (obj instanceof ArrayData) {
1278            return new NativeArray((ArrayData) obj, this);
1279        } else if (obj instanceof Symbol) {
1280            return new NativeSymbol((Symbol) obj, this);
1281        } else {
1282            // FIXME: more special cases? Map? List?
1283            return obj;
1284        }
1285    }
1286
1287    /**
1288     * Lookup helper for JS primitive types
1289     *
1290     * @param request the link request for the dynamic call site.
1291     * @param self     self reference
1292     *
1293     * @return guarded invocation
1294     */
1295    public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
1296        if (isString(self)) {
1297            return NativeString.lookupPrimitive(request, self);
1298        } else if (self instanceof Number) {
1299            return NativeNumber.lookupPrimitive(request, self);
1300        } else if (self instanceof Boolean) {
1301            return NativeBoolean.lookupPrimitive(request, self);
1302        } else if (self instanceof Symbol) {
1303            return NativeSymbol.lookupPrimitive(request, self);
1304        }
1305        throw new IllegalArgumentException("Unsupported primitive: " + self);
1306    }
1307
1308    /**
1309     * Returns a method handle that creates a wrapper object for a JS primitive value.
1310     *
1311     * @param self receiver object
1312     * @return method handle to create wrapper objects for primitive receiver
1313     */
1314    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
1315        if (isString(self)) {
1316            return NativeString.WRAPFILTER;
1317        } else if (self instanceof Number) {
1318            return NativeNumber.WRAPFILTER;
1319        } else if (self instanceof Boolean) {
1320            return NativeBoolean.WRAPFILTER;
1321        }
1322        throw new IllegalArgumentException("Unsupported primitive: " + self);
1323    }
1324
1325
1326    /**
1327     * Create a new empty script object
1328     *
1329     * @return the new ScriptObject
1330     */
1331    public ScriptObject newObject() {
1332        return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
1333    }
1334
1335    /**
1336     * Default value of given type
1337     *
1338     * @param sobj     script object
1339     * @param typeHint type hint
1340     *
1341     * @return default value
1342     */
1343    public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
1344        // When the [[DefaultValue]] internal method of O is called with no hint,
1345        // then it behaves as if the hint were Number, unless O is a Date object
1346        // in which case it behaves as if the hint were String.
1347        Class<?> hint = typeHint;
1348        if (hint == null) {
1349            hint = Number.class;
1350        }
1351
1352        try {
1353            if (hint == String.class) {
1354
1355                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1356
1357                if (Bootstrap.isCallable(toString)) {
1358                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1359                    if (JSType.isPrimitive(value)) {
1360                        return value;
1361                    }
1362                }
1363
1364                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1365                if (Bootstrap.isCallable(valueOf)) {
1366                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1367                    if (JSType.isPrimitive(value)) {
1368                        return value;
1369                    }
1370                }
1371                throw typeError(this, "cannot.get.default.string");
1372            }
1373
1374            if (hint == Number.class) {
1375                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1376                if (Bootstrap.isCallable(valueOf)) {
1377                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1378                    if (JSType.isPrimitive(value)) {
1379                        return value;
1380                    }
1381                }
1382
1383                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1384                if (Bootstrap.isCallable(toString)) {
1385                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1386                    if (JSType.isPrimitive(value)) {
1387                        return value;
1388                    }
1389                }
1390
1391                throw typeError(this, "cannot.get.default.number");
1392            }
1393        } catch (final RuntimeException | Error e) {
1394            throw e;
1395        } catch (final Throwable t) {
1396            throw new RuntimeException(t);
1397        }
1398
1399        return UNDEFINED;
1400    }
1401
1402    /**
1403     * Is the given ScriptObject an ECMAScript Error object?
1404     *
1405     * @param sobj the object being checked
1406     * @return true if sobj is an Error object
1407     */
1408    public boolean isError(final ScriptObject sobj) {
1409        final ScriptObject errorProto = getErrorPrototype();
1410        ScriptObject proto = sobj.getProto();
1411        while (proto != null) {
1412            if (proto == errorProto) {
1413                return true;
1414            }
1415            proto = proto.getProto();
1416        }
1417        return false;
1418    }
1419
1420    /**
1421     * Create a new ECMAScript Error object.
1422     *
1423     * @param msg error message
1424     * @return newly created Error object
1425     */
1426    public ScriptObject newError(final String msg) {
1427        return new NativeError(msg, this);
1428    }
1429
1430    /**
1431     * Create a new ECMAScript EvalError object.
1432     *
1433     * @param msg error message
1434     * @return newly created EvalError object
1435     */
1436    public ScriptObject newEvalError(final String msg) {
1437        return new NativeEvalError(msg, this);
1438    }
1439
1440    /**
1441     * Create a new ECMAScript RangeError object.
1442     *
1443     * @param msg error message
1444     * @return newly created RangeError object
1445     */
1446    public ScriptObject newRangeError(final String msg) {
1447        return new NativeRangeError(msg, this);
1448    }
1449
1450    /**
1451     * Create a new ECMAScript ReferenceError object.
1452     *
1453     * @param msg error message
1454     * @return newly created ReferenceError object
1455     */
1456    public ScriptObject newReferenceError(final String msg) {
1457        return new NativeReferenceError(msg, this);
1458    }
1459
1460    /**
1461     * Create a new ECMAScript SyntaxError object.
1462     *
1463     * @param msg error message
1464     * @return newly created SyntaxError object
1465     */
1466    public ScriptObject newSyntaxError(final String msg) {
1467        return new NativeSyntaxError(msg, this);
1468    }
1469
1470    /**
1471     * Create a new ECMAScript TypeError object.
1472     *
1473     * @param msg error message
1474     * @return newly created TypeError object
1475     */
1476    public ScriptObject newTypeError(final String msg) {
1477        return new NativeTypeError(msg, this);
1478    }
1479
1480    /**
1481     * Create a new ECMAScript URIError object.
1482     *
1483     * @param msg error message
1484     * @return newly created URIError object
1485     */
1486    public ScriptObject newURIError(final String msg) {
1487        return new NativeURIError(msg, this);
1488    }
1489
1490    /**
1491     * Create a new ECMAScript GenericDescriptor object.
1492     *
1493     * @param configurable is the property configurable?
1494     * @param enumerable is the property enumerable?
1495     * @return newly created GenericDescriptor object
1496     */
1497    public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1498        return new GenericPropertyDescriptor(configurable, enumerable, this);
1499    }
1500
1501    /**
1502     * Create a new ECMAScript DatePropertyDescriptor object.
1503     *
1504     * @param value of the data property
1505     * @param configurable is the property configurable?
1506     * @param enumerable is the property enumerable?
1507     * @param writable is the property writable?
1508     * @return newly created DataPropertyDescriptor object
1509     */
1510    public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1511        return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1512    }
1513
1514    /**
1515     * Create a new ECMAScript AccessorPropertyDescriptor object.
1516     *
1517     * @param get getter function of the user accessor property
1518     * @param set setter function of the user accessor property
1519     * @param configurable is the property configurable?
1520     * @param enumerable is the property enumerable?
1521     * @return newly created AccessorPropertyDescriptor object
1522     */
1523    public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1524        final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1525
1526        if (get == null) {
1527            desc.delete(PropertyDescriptor.GET, false);
1528        }
1529
1530        if (set == null) {
1531            desc.delete(PropertyDescriptor.SET, false);
1532        }
1533
1534        return desc;
1535    }
1536
1537    private <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1538        final T obj = map.get(key);
1539        if (obj != null) {
1540            return obj;
1541        }
1542
1543        final Global oldGlobal = Context.getGlobal();
1544        final boolean differentGlobal = oldGlobal != this;
1545        try {
1546            if (differentGlobal) {
1547                Context.setGlobal(this);
1548            }
1549            final T newObj = creator.call();
1550            final T existingObj = map.putIfAbsent(key, newObj);
1551            return existingObj != null ? existingObj : newObj;
1552        } catch (final Exception exp) {
1553            throw new RuntimeException(exp);
1554        } finally {
1555            if (differentGlobal) {
1556                Context.setGlobal(oldGlobal);
1557            }
1558        }
1559    }
1560
1561    private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1562
1563
1564    /**
1565     * Get cached InvokeByName object for the given key
1566     * @param key key to be associated with InvokeByName object
1567     * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1568     * @return InvokeByName object associated with the key.
1569     */
1570    public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1571        return getLazilyCreatedValue(key, creator, namedInvokers);
1572    }
1573
1574    private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1575
1576    /**
1577     * Get cached dynamic method handle for the given key
1578     * @param key key to be associated with dynamic method handle
1579     * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1580     * @return dynamic method handle associated with the key.
1581     */
1582    public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1583        return getLazilyCreatedValue(key, creator, dynamicInvokers);
1584    }
1585
1586    /**
1587     * Hook to search missing variables in ScriptContext if available
1588     * @param self used to detect if scope call or not (this function is 'strict')
1589     * @param name name of the variable missing
1590     * @return value of the missing variable or undefined (or TypeError for scope search)
1591     */
1592    public static Object __noSuchProperty__(final Object self, final Object name) {
1593        final Global global = Global.instance();
1594        final ScriptContext sctxt = global.currentContext();
1595        final String nameStr = name.toString();
1596
1597        if (sctxt != null) {
1598            final int scope = sctxt.getAttributesScope(nameStr);
1599            if (scope != -1) {
1600                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1601            }
1602        }
1603
1604        switch (nameStr) {
1605        case "context":
1606            return sctxt;
1607        case "engine":
1608            return global.engine;
1609        default:
1610            break;
1611        }
1612
1613        if (self == UNDEFINED) {
1614            // scope access and so throw ReferenceError
1615            throw referenceError(global, "not.defined", nameStr);
1616        }
1617
1618        return UNDEFINED;
1619    }
1620
1621    /**
1622     * This is the eval used when 'indirect' eval call is made.
1623     *
1624     * var global = this;
1625     * global.eval("print('hello')");
1626     *
1627     * @param self  eval scope
1628     * @param str   eval string
1629     *
1630     * @return the result of eval
1631     */
1632    public static Object eval(final Object self, final Object str) {
1633        return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false);
1634    }
1635
1636    /**
1637     * Direct eval
1638     *
1639     * @param self     The scope of eval passed as 'self'
1640     * @param str      Evaluated code
1641     * @param callThis "this" to be passed to the evaluated code
1642     * @param location location of the eval call
1643     * @param strict   is eval called from a strict mode code?
1644     *
1645     * @return the return value of the eval
1646     *
1647     * This is directly invoked from generated when eval(code) is called in user code
1648     */
1649    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1650        if (!isString(str)) {
1651            return str;
1652        }
1653        final Global global = Global.instanceFrom(self);
1654        final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1655
1656        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1657    }
1658
1659    /**
1660     * Global print implementation - Nashorn extension
1661     *
1662     * @param self    scope
1663     * @param objects arguments to print
1664     *
1665     * @return result of print (undefined)
1666     */
1667    public static Object print(final Object self, final Object... objects) {
1668        return Global.instanceFrom(self).printImpl(false, objects);
1669    }
1670
1671    /**
1672     * Global println implementation - Nashorn extension
1673     *
1674     * @param self    scope
1675     * @param objects arguments to print
1676     *
1677     * @return result of println (undefined)
1678     */
1679    public static Object println(final Object self, final Object... objects) {
1680        return Global.instanceFrom(self).printImpl(true, objects);
1681    }
1682
1683    /**
1684     * Global load implementation - Nashorn extension.
1685     *
1686     * <p>
1687     * load builtin loads the given script. Script source can be a URL or a File
1688     * or a script object with name and script properties. Evaluated code gets
1689     * global object "this" and uses global object as scope for evaluation.
1690     * </p>
1691     * <p>
1692     * If self is undefined or null or global, then global object is used
1693     * as scope as well as "this" for the evaluated code. If self is any other
1694     * object, then it is indirect load call. With indirect load call, the
1695     * properties of scope are available to evaluated script as variables. Also,
1696     * global scope properties are accessible. Any var, function definition in
1697     * evaluated script goes into an object that is not accessible to user scripts.
1698     * </p>
1699     * Thus the indirect load call is equivalent to the following:
1700     * <pre>
1701     * <code>
1702     * (function (scope, source) {
1703     *    with(scope) {
1704     *        eval(&lt;script_from_source&gt;);
1705     *    }
1706     * })(self, source);
1707     * </code>
1708     * </pre>
1709     *
1710     * @param self    scope to use for the script evaluation
1711     * @param source  script source
1712     *
1713     * @return result of load (may be undefined)
1714     *
1715     * @throws IOException if source could not be read
1716     */
1717    public static Object load(final Object self, final Object source) throws IOException {
1718        final Global global = Global.instanceFrom(self);
1719        return global.getContext().load(self, source);
1720    }
1721
1722    /**
1723     * Global loadWithNewGlobal implementation - Nashorn extension.
1724     *
1725     * loadWithNewGlobal builtin loads the given script from a URL or a File
1726     * or a script object with name and script properties. Evaluated code gets
1727     * new global object "this" and uses that new global object as scope for evaluation.
1728     *
1729     * @param self self This value is ignored by this function
1730     * @param args optional arguments to be passed to the loaded script
1731     *
1732     * @return result of load (may be undefined)
1733     *
1734     * @throws IOException if source could not be read
1735     */
1736    public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1737        final Global global = Global.instanceFrom(self);
1738        final int length = args.length;
1739        final boolean hasArgs = 0 < length;
1740        final Object from = hasArgs ? args[0] : UNDEFINED;
1741        final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1742
1743        return global.getContext().loadWithNewGlobal(from, arguments);
1744    }
1745
1746    /**
1747     * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1748     *
1749     * @param self  self reference
1750     * @param code  exit code
1751     *
1752     * @return undefined (will never be reached)
1753     */
1754    public static Object exit(final Object self, final Object code) {
1755        System.exit(JSType.toInt32(code));
1756        return UNDEFINED;
1757    }
1758
1759    // builtin prototype accessors
1760
1761    /**
1762     * Get the builtin Object prototype.
1763     * @return the Object prototype.
1764     */
1765    public ScriptObject getObjectPrototype() {
1766        return ScriptFunction.getPrototype(builtinObject);
1767    }
1768
1769    /**
1770     * Get the builtin Function prototype.
1771     * @return the Function prototype.
1772     */
1773    public ScriptObject getFunctionPrototype() {
1774        return ScriptFunction.getPrototype(builtinFunction);
1775    }
1776
1777    /**
1778     * Get the builtin Array prototype.
1779     * @return the Array prototype
1780     */
1781    public ScriptObject getArrayPrototype() {
1782        return ScriptFunction.getPrototype(builtinArray);
1783    }
1784
1785    ScriptObject getBooleanPrototype() {
1786        return ScriptFunction.getPrototype(builtinBoolean);
1787    }
1788
1789    ScriptObject getNumberPrototype() {
1790        return ScriptFunction.getPrototype(builtinNumber);
1791    }
1792
1793    ScriptObject getDatePrototype() {
1794        return ScriptFunction.getPrototype(getBuiltinDate());
1795    }
1796
1797    ScriptObject getRegExpPrototype() {
1798        return ScriptFunction.getPrototype(getBuiltinRegExp());
1799    }
1800
1801    ScriptObject getStringPrototype() {
1802        return ScriptFunction.getPrototype(builtinString);
1803    }
1804
1805    ScriptObject getErrorPrototype() {
1806        return ScriptFunction.getPrototype(builtinError);
1807    }
1808
1809    ScriptObject getEvalErrorPrototype() {
1810        return ScriptFunction.getPrototype(getBuiltinEvalError());
1811    }
1812
1813    ScriptObject getRangeErrorPrototype() {
1814        return ScriptFunction.getPrototype(getBuiltinRangeError());
1815    }
1816
1817    ScriptObject getReferenceErrorPrototype() {
1818        return ScriptFunction.getPrototype(builtinReferenceError);
1819    }
1820
1821    ScriptObject getSyntaxErrorPrototype() {
1822        return ScriptFunction.getPrototype(builtinSyntaxError);
1823    }
1824
1825    ScriptObject getTypeErrorPrototype() {
1826        return ScriptFunction.getPrototype(builtinTypeError);
1827    }
1828
1829    ScriptObject getURIErrorPrototype() {
1830        return ScriptFunction.getPrototype(getBuiltinURIError());
1831    }
1832
1833    ScriptObject getJavaImporterPrototype() {
1834        return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1835    }
1836
1837    ScriptObject getJSAdapterPrototype() {
1838        return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1839    }
1840
1841    ScriptObject getSymbolPrototype() {
1842        return ScriptFunction.getPrototype(getBuiltinSymbol());
1843    }
1844
1845    ScriptObject getMapPrototype() {
1846        return ScriptFunction.getPrototype(getBuiltinMap());
1847    }
1848
1849    ScriptObject getWeakMapPrototype() {
1850        return ScriptFunction.getPrototype(getBuiltinWeakMap());
1851    }
1852
1853    ScriptObject getSetPrototype() {
1854        return ScriptFunction.getPrototype(getBuiltinSet());
1855    }
1856
1857    ScriptObject getWeakSetPrototype() {
1858        return ScriptFunction.getPrototype(getBuiltinWeakSet());
1859    }
1860
1861    ScriptObject getIteratorPrototype() {
1862        if (builtinIteratorPrototype == null) {
1863            builtinIteratorPrototype = initPrototype("AbstractIterator", getObjectPrototype());
1864        }
1865        return builtinIteratorPrototype;
1866    }
1867
1868    ScriptObject getMapIteratorPrototype() {
1869        if (builtinMapIteratorPrototype == null) {
1870            builtinMapIteratorPrototype = initPrototype("MapIterator", getIteratorPrototype());
1871        }
1872        return builtinMapIteratorPrototype;
1873    }
1874
1875    ScriptObject getSetIteratorPrototype() {
1876        if (builtinSetIteratorPrototype == null) {
1877            builtinSetIteratorPrototype = initPrototype("SetIterator", getIteratorPrototype());
1878        }
1879        return builtinSetIteratorPrototype;
1880    }
1881
1882    ScriptObject getArrayIteratorPrototype() {
1883        if (builtinArrayIteratorPrototype == null) {
1884            builtinArrayIteratorPrototype = initPrototype("ArrayIterator", getIteratorPrototype());
1885        }
1886        return builtinArrayIteratorPrototype;
1887    }
1888
1889    ScriptObject getStringIteratorPrototype() {
1890        if (builtinStringIteratorPrototype == null) {
1891            builtinStringIteratorPrototype = initPrototype("StringIterator", getIteratorPrototype());
1892        }
1893        return builtinStringIteratorPrototype;
1894    }
1895
1896    private synchronized ScriptFunction getBuiltinArrayBuffer() {
1897        if (this.builtinArrayBuffer == null) {
1898            this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1899        }
1900        return this.builtinArrayBuffer;
1901    }
1902
1903    ScriptObject getArrayBufferPrototype() {
1904        return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1905    }
1906
1907    private synchronized ScriptFunction getBuiltinDataView() {
1908        if (this.builtinDataView == null) {
1909            this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1910        }
1911        return this.builtinDataView;
1912    }
1913
1914    ScriptObject getDataViewPrototype() {
1915        return ScriptFunction.getPrototype(getBuiltinDataView());
1916    }
1917
1918    private synchronized ScriptFunction getBuiltinInt8Array() {
1919        if (this.builtinInt8Array == null) {
1920            this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1921        }
1922        return this.builtinInt8Array;
1923    }
1924
1925    ScriptObject getInt8ArrayPrototype() {
1926        return ScriptFunction.getPrototype(getBuiltinInt8Array());
1927    }
1928
1929    private synchronized ScriptFunction getBuiltinUint8Array() {
1930        if (this.builtinUint8Array == null) {
1931            this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1932        }
1933        return this.builtinUint8Array;
1934    }
1935
1936    ScriptObject getUint8ArrayPrototype() {
1937        return ScriptFunction.getPrototype(getBuiltinUint8Array());
1938    }
1939
1940    private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1941        if (this.builtinUint8ClampedArray == null) {
1942            this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1943        }
1944        return this.builtinUint8ClampedArray;
1945    }
1946
1947    ScriptObject getUint8ClampedArrayPrototype() {
1948        return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1949    }
1950
1951    private synchronized ScriptFunction getBuiltinInt16Array() {
1952        if (this.builtinInt16Array == null) {
1953            this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1954        }
1955        return this.builtinInt16Array;
1956    }
1957
1958    ScriptObject getInt16ArrayPrototype() {
1959        return ScriptFunction.getPrototype(getBuiltinInt16Array());
1960    }
1961
1962    private synchronized ScriptFunction getBuiltinUint16Array() {
1963        if (this.builtinUint16Array == null) {
1964            this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1965        }
1966        return this.builtinUint16Array;
1967    }
1968
1969    ScriptObject getUint16ArrayPrototype() {
1970        return ScriptFunction.getPrototype(getBuiltinUint16Array());
1971    }
1972
1973    private synchronized ScriptFunction getBuiltinInt32Array() {
1974        if (this.builtinInt32Array == null) {
1975            this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1976        }
1977        return this.builtinInt32Array;
1978    }
1979
1980    ScriptObject getInt32ArrayPrototype() {
1981        return ScriptFunction.getPrototype(getBuiltinInt32Array());
1982    }
1983
1984    private synchronized ScriptFunction getBuiltinUint32Array() {
1985        if (this.builtinUint32Array == null) {
1986            this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1987        }
1988        return this.builtinUint32Array;
1989    }
1990
1991    ScriptObject getUint32ArrayPrototype() {
1992        return ScriptFunction.getPrototype(getBuiltinUint32Array());
1993    }
1994
1995    private synchronized ScriptFunction getBuiltinFloat32Array() {
1996        if (this.builtinFloat32Array == null) {
1997            this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1998        }
1999        return this.builtinFloat32Array;
2000    }
2001
2002    ScriptObject getFloat32ArrayPrototype() {
2003        return ScriptFunction.getPrototype(getBuiltinFloat32Array());
2004    }
2005
2006    private synchronized ScriptFunction getBuiltinFloat64Array() {
2007        if (this.builtinFloat64Array == null) {
2008            this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
2009        }
2010        return this.builtinFloat64Array;
2011    }
2012
2013    ScriptObject getFloat64ArrayPrototype() {
2014        return ScriptFunction.getPrototype(getBuiltinFloat64Array());
2015    }
2016
2017    /**
2018     * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties.
2019     *
2020     * @return the TypeError throwing function
2021     */
2022    public ScriptFunction getTypeErrorThrower() {
2023        return typeErrorThrower;
2024    }
2025
2026    private synchronized ScriptFunction getBuiltinDate() {
2027        if (this.builtinDate == null) {
2028            this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
2029            final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
2030            // initialize default date
2031            this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
2032        }
2033        return this.builtinDate;
2034    }
2035
2036    private synchronized ScriptFunction getBuiltinEvalError() {
2037        if (this.builtinEvalError == null) {
2038            this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
2039        }
2040        return this.builtinEvalError;
2041    }
2042
2043    private ScriptFunction getBuiltinFunction() {
2044        return builtinFunction;
2045    }
2046
2047    /**
2048     * Get the switchpoint used to check property changes for Function.prototype.apply
2049     * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
2050     */
2051    public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
2052        return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
2053    }
2054
2055    private static boolean isBuiltinFunctionProperty(final String name) {
2056        final Global instance = Global.instance();
2057        final ScriptFunction builtinFunction = instance.getBuiltinFunction();
2058        if (builtinFunction == null) {
2059            return false; //conservative for compile-only mode
2060        }
2061        final boolean isBuiltinFunction = instance.function == builtinFunction;
2062        return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
2063    }
2064
2065    /**
2066     * Check if the Function.prototype.apply has not been replaced
2067     * @return true if Function.prototype.apply has been replaced
2068     */
2069    public static boolean isBuiltinFunctionPrototypeApply() {
2070        return isBuiltinFunctionProperty("apply");
2071    }
2072
2073    /**
2074     * Check if the Function.prototype.apply has not been replaced
2075     * @return true if Function.prototype.call has been replaced
2076     */
2077    public static boolean isBuiltinFunctionPrototypeCall() {
2078        return isBuiltinFunctionProperty("call");
2079    }
2080
2081    private synchronized ScriptFunction getBuiltinJSAdapter() {
2082        if (this.builtinJSAdapter == null) {
2083            this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
2084        }
2085        return builtinJSAdapter;
2086    }
2087
2088    private synchronized ScriptObject getBuiltinJSON() {
2089        if (this.builtinJSON == null) {
2090            this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
2091        }
2092        return this.builtinJSON;
2093    }
2094
2095    private synchronized ScriptFunction getBuiltinJavaImporter() {
2096        if (getContext().getEnv()._no_java) {
2097            throw new IllegalStateException();
2098        }
2099        if (this.builtinJavaImporter == null) {
2100            this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
2101        }
2102        return this.builtinJavaImporter;
2103    }
2104
2105    private synchronized ScriptObject getBuiltinJavaApi() {
2106        if (getContext().getEnv()._no_java) {
2107            throw new IllegalStateException();
2108        }
2109        if (this.builtinJavaApi == null) {
2110            this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
2111            this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend");
2112            this.builtInJavaTo = (ScriptFunction)builtinJavaApi.get("to");
2113        }
2114        return this.builtinJavaApi;
2115    }
2116
2117    /**
2118     * Returns true if the passed function is the built-in "Java.extend".
2119     * @param fn the function in question
2120     * @return true if the function is built-in "Java.extend"
2121     */
2122    public static boolean isBuiltInJavaExtend(final ScriptFunction fn) {
2123        if(!"extend".equals(fn.getName())) {
2124            // Avoid hitting the thread local if the name doesn't match.
2125            return false;
2126        }
2127        return fn == Context.getGlobal().builtInJavaExtend;
2128    }
2129
2130    /**
2131     * Returns true if the passed function is the built-in "Java.to".
2132     * @param fn the function in question
2133     * @return true if the function is built-in "Java.to"
2134     */
2135    public static boolean isBuiltInJavaTo(final ScriptFunction fn) {
2136        if(!"to".equals(fn.getName())) {
2137            // Avoid hitting the thread local if the name doesn't match.
2138            return false;
2139        }
2140        return fn == Context.getGlobal().builtInJavaTo;
2141    }
2142
2143
2144    private synchronized ScriptFunction getBuiltinRangeError() {
2145        if (this.builtinRangeError == null) {
2146            this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2147        }
2148        return builtinRangeError;
2149    }
2150
2151    private synchronized ScriptFunction getBuiltinRegExp() {
2152        if (this.builtinRegExp == null) {
2153            this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2154            final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2155            // initialize default regexp object
2156            this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2157            // RegExp.prototype should behave like a RegExp object. So copy the
2158            // properties.
2159            regExpProto.addBoundProperties(DEFAULT_REGEXP);
2160        }
2161        return builtinRegExp;
2162    }
2163
2164    private synchronized ScriptFunction getBuiltinURIError() {
2165        if (this.builtinURIError == null) {
2166            this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2167        }
2168        return this.builtinURIError;
2169    }
2170
2171    private synchronized ScriptFunction getBuiltinSymbol() {
2172        if (this.builtinSymbol == null) {
2173            this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class);
2174        }
2175        return this.builtinSymbol;
2176    }
2177
2178    private synchronized ScriptFunction getBuiltinMap() {
2179        if (this.builtinMap == null) {
2180            this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class);
2181        }
2182        return this.builtinMap;
2183    }
2184
2185    private synchronized ScriptFunction getBuiltinWeakMap() {
2186        if (this.builtinWeakMap == null) {
2187            this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class);
2188        }
2189        return this.builtinWeakMap;
2190    }
2191
2192    private synchronized ScriptFunction getBuiltinSet() {
2193        if (this.builtinSet == null) {
2194            this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class);
2195        }
2196        return this.builtinSet;
2197    }
2198
2199    private synchronized ScriptFunction getBuiltinWeakSet() {
2200        if (this.builtinWeakSet == null) {
2201            this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class);
2202        }
2203        return this.builtinWeakSet;
2204    }
2205
2206    @Override
2207    public String getClassName() {
2208        return "global";
2209    }
2210
2211    /**
2212     * Copy function used to clone NativeRegExp objects.
2213     *
2214     * @param regexp a NativeRegExp to clone
2215     *
2216     * @return copy of the given regexp object
2217     */
2218    public static Object regExpCopy(final Object regexp) {
2219        return new NativeRegExp((NativeRegExp)regexp);
2220    }
2221
2222    /**
2223     * Convert given object to NativeRegExp type.
2224     *
2225     * @param obj object to be converted
2226     * @return NativeRegExp instance
2227     */
2228    public static NativeRegExp toRegExp(final Object obj) {
2229        if (obj instanceof NativeRegExp) {
2230            return (NativeRegExp)obj;
2231        }
2232        return new NativeRegExp(JSType.toString(obj));
2233    }
2234
2235    /**
2236     * ECMA 9.9 ToObject implementation
2237     *
2238     * @param obj  an item for which to run ToObject
2239     * @return ToObject version of given item
2240     */
2241    public static Object toObject(final Object obj) {
2242        if (obj == null || obj == UNDEFINED) {
2243            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2244        }
2245
2246        if (obj instanceof ScriptObject) {
2247            return obj;
2248        }
2249
2250        return instance().wrapAsObject(obj);
2251    }
2252
2253    /**
2254     * Allocate a new object array.
2255     *
2256     * @param initial object values.
2257     * @return the new array
2258     */
2259    public static NativeArray allocate(final Object[] initial) {
2260        ArrayData arrayData = ArrayData.allocate(initial);
2261
2262        for (int index = 0; index < initial.length; index++) {
2263            final Object value = initial[index];
2264
2265            if (value == ScriptRuntime.EMPTY) {
2266                arrayData = arrayData.delete(index);
2267            }
2268        }
2269
2270        return new NativeArray(arrayData);
2271    }
2272
2273    /**
2274     * Allocate a new number array.
2275     *
2276     * @param initial number values.
2277     * @return the new array
2278     */
2279    public static NativeArray allocate(final double[] initial) {
2280        return new NativeArray(ArrayData.allocate(initial));
2281    }
2282
2283    /**
2284     * Allocate a new integer array.
2285     *
2286     * @param initial number values.
2287     * @return the new array
2288     */
2289    public static NativeArray allocate(final int[] initial) {
2290        return new NativeArray(ArrayData.allocate(initial));
2291    }
2292
2293    /**
2294     * Allocate a new object array for arguments.
2295     *
2296     * @param arguments initial arguments passed.
2297     * @param callee reference to the function that uses arguments object
2298     * @param numParams actual number of declared parameters
2299     *
2300     * @return the new array
2301     */
2302    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2303        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2304    }
2305
2306    /**
2307     * Called from generated to check if given function is the builtin 'eval'. If
2308     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2309     *
2310     * @param  fn function object that is checked
2311     * @return true if fn is the builtin eval
2312     */
2313    public static boolean isEval(final Object fn) {
2314        return fn == Global.instance().builtinEval;
2315    }
2316
2317    /**
2318     * Called from generated to replace a location property placeholder with the actual location property value.
2319     *
2320     * @param  placeholder the value tested for being a placeholder for a location property
2321     * @param  locationProperty the actual value for the location property
2322     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2323     */
2324    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2325        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2326    }
2327
2328    /**
2329     * Called from runtime internals to check if the passed value is a location property placeholder.
2330     * @param  placeholder the value tested for being a placeholder for a location property
2331     * @return true if the value is a placeholder, false otherwise.
2332     */
2333    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2334        return placeholder == LOCATION_PLACEHOLDER;
2335    }
2336
2337    /**
2338     * Create a new RegExp object.
2339     *
2340     * @param expression Regular expression.
2341     * @param options    Search options.
2342     *
2343     * @return New RegExp object.
2344     */
2345    public static Object newRegExp(final String expression, final String options) {
2346        if (options == null) {
2347            return new NativeRegExp(expression);
2348        }
2349        return new NativeRegExp(expression, options);
2350    }
2351
2352    /**
2353     * Get the object prototype
2354     *
2355     * @return the object prototype
2356     */
2357    public static ScriptObject objectPrototype() {
2358        return Global.instance().getObjectPrototype();
2359    }
2360
2361    /**
2362     * Create a new empty object instance.
2363     *
2364     * @return New empty object.
2365     */
2366    public static ScriptObject newEmptyInstance() {
2367        return Global.instance().newObject();
2368    }
2369
2370    /**
2371     * Check if a given object is a ScriptObject, raises an exception if this is
2372     * not the case
2373     *
2374     * @param obj and object to check
2375     * @return the script object
2376     */
2377    public static ScriptObject checkObject(final Object obj) {
2378        if (!(obj instanceof ScriptObject)) {
2379            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2380        }
2381        return (ScriptObject)obj;
2382    }
2383
2384    /**
2385     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2386     * if this object is null or undefined.
2387     *
2388     * @param obj an object to check
2389     */
2390    public static void checkObjectCoercible(final Object obj) {
2391        if (obj == null || obj == UNDEFINED) {
2392            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2393        }
2394    }
2395
2396    /**
2397     * Return the ES6 global scope for lexically declared bindings.
2398     * @return the ES6 lexical global scope.
2399     */
2400    public final ScriptObject getLexicalScope() {
2401        assert context.getEnv()._es6;
2402        return lexicalScope;
2403    }
2404
2405    @Override
2406    public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2407        PropertyMap ownMap = getMap();
2408        LexicalScope lexScope = null;
2409        PropertyMap lexicalMap = null;
2410        boolean hasLexicalDefinitions = false;
2411
2412        if (context.getEnv()._es6) {
2413            lexScope = (LexicalScope) getLexicalScope();
2414            lexicalMap = lexScope.getMap();
2415
2416            for (final jdk.nashorn.internal.runtime.Property property : properties) {
2417                if (property.isLexicalBinding()) {
2418                    hasLexicalDefinitions = true;
2419                }
2420                // ES6 15.1.8 steps 6. and 7.
2421                final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2422                if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2423                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2424                }
2425                final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2426                if (lexicalProperty != null && !property.isConfigurable()) {
2427                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2428                }
2429            }
2430        }
2431
2432        final boolean extensible = isExtensible();
2433        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2434            if (property.isLexicalBinding()) {
2435                assert lexScope != null;
2436                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
2437
2438                if (ownMap.findProperty(property.getKey()) != null) {
2439                    // If property exists in the global object invalidate any global constant call sites.
2440                    invalidateGlobalConstant(property.getKey());
2441                }
2442            } else {
2443                ownMap = addBoundProperty(ownMap, source, property, extensible);
2444            }
2445        }
2446
2447        setMap(ownMap);
2448
2449        if (hasLexicalDefinitions) {
2450            assert lexScope != null;
2451            lexScope.setMap(lexicalMap);
2452            invalidateLexicalSwitchPoint();
2453        }
2454    }
2455
2456    @Override
2457    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2458        final String name = NashornCallSiteDescriptor.getOperand(desc);
2459        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2460
2461        if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2462            if (lexicalScope.hasOwnProperty(name)) {
2463                return lexicalScope.findGetMethod(desc, request);
2464            }
2465        }
2466
2467        final GuardedInvocation invocation =  super.findGetMethod(desc, request);
2468
2469        // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2470        // because those are invalidated per-key in the addBoundProperties method above.
2471        // We therefore check if the invocation does already have a switchpoint and the property is non-inherited,
2472        // assuming this only applies to global constants. If other non-inherited properties will
2473        // start using switchpoints some time in the future we'll have to revisit this.
2474        if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2475            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2476        }
2477
2478        return invocation;
2479    }
2480
2481    @Override
2482    protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) {
2483        if (lexicalScope != null && isScope) {
2484            final FindProperty find = lexicalScope.findProperty(key, false);
2485            if (find != null) {
2486                return find;
2487            }
2488        }
2489        return super.findProperty(key, deep, isScope, start);
2490    }
2491
2492    @Override
2493    public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2494        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2495
2496        if (lexicalScope != null && isScope) {
2497            final String name = NashornCallSiteDescriptor.getOperand(desc);
2498            if (lexicalScope.hasOwnProperty(name)) {
2499                return lexicalScope.findSetMethod(desc, request);
2500            }
2501        }
2502
2503        final GuardedInvocation invocation = super.findSetMethod(desc, request);
2504
2505        if (isScope && context.getEnv()._es6) {
2506            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2507        }
2508
2509        return invocation;
2510    }
2511
2512    /**
2513     * Adds jjs shell interactive mode builtin functions to global scope.
2514     */
2515    public void addShellBuiltins() {
2516        Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT);
2517        addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2518
2519        value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT);
2520        addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2521    }
2522
2523    private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2524        SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2525        if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2526            switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2527        }
2528        return switchPoint;
2529    }
2530
2531    private synchronized void invalidateLexicalSwitchPoint() {
2532        if (lexicalScopeSwitchPoint != null) {
2533            context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2534            SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2535        }
2536    }
2537
2538
2539    @SuppressWarnings("unused")
2540    private static Object lexicalScopeFilter(final Object self) {
2541        if (self instanceof Global) {
2542            return ((Global) self).getLexicalScope();
2543        }
2544        return self;
2545    }
2546
2547    private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2548        final T func = initConstructor(name, clazz);
2549        tagBuiltinProperties(name, func);
2550        return func;
2551    }
2552
2553    private void init(final ScriptEngine eng) {
2554        assert Context.getGlobal() == this : "this global is not set as current";
2555
2556        final ScriptEnvironment env = getContext().getEnv();
2557
2558        // initialize Function and Object constructor
2559        initFunctionAndObject();
2560
2561        // Now fix Global's own proto.
2562        this.setInitialProto(getObjectPrototype());
2563
2564        // initialize global function properties
2565        this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL);
2566
2567        this.parseInt = ScriptFunction.createBuiltin("parseInt",   GlobalFunctions.PARSEINT,
2568                    new Specialization[] {
2569                    new Specialization(GlobalFunctions.PARSEINT_Z),
2570                    new Specialization(GlobalFunctions.PARSEINT_I),
2571                    new Specialization(GlobalFunctions.PARSEINT_OI),
2572                    new Specialization(GlobalFunctions.PARSEINT_O) });
2573        this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2574        this.isNaN = ScriptFunction.createBuiltin("isNaN",   GlobalFunctions.IS_NAN,
2575                   new Specialization[] {
2576                        new Specialization(GlobalFunctions.IS_NAN_I),
2577                        new Specialization(GlobalFunctions.IS_NAN_J),
2578                        new Specialization(GlobalFunctions.IS_NAN_D) });
2579        this.parseFloat         = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2580        this.isNaN              = ScriptFunction.createBuiltin("isNaN",      GlobalFunctions.IS_NAN);
2581        this.isFinite           = ScriptFunction.createBuiltin("isFinite",   GlobalFunctions.IS_FINITE);
2582        this.encodeURI          = ScriptFunction.createBuiltin("encodeURI",  GlobalFunctions.ENCODE_URI);
2583        this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2584        this.decodeURI          = ScriptFunction.createBuiltin("decodeURI",  GlobalFunctions.DECODE_URI);
2585        this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2586        this.escape             = ScriptFunction.createBuiltin("escape",     GlobalFunctions.ESCAPE);
2587        this.unescape           = ScriptFunction.createBuiltin("unescape",   GlobalFunctions.UNESCAPE);
2588        this.print              = ScriptFunction.createBuiltin("print",      env._print_no_newline ? PRINT : PRINTLN);
2589        this.load               = ScriptFunction.createBuiltin("load",       LOAD);
2590        this.loadWithNewGlobal  = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2591        this.exit               = ScriptFunction.createBuiltin("exit",       EXIT);
2592        this.quit               = ScriptFunction.createBuiltin("quit",       EXIT);
2593
2594        // built-in constructors
2595        this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2596        this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2597        this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2598        this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2599        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2600
2601        // initialize String.prototype.length to 0
2602        // add String.prototype.length
2603        final ScriptObject stringPrototype = getStringPrototype();
2604        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2605
2606        // set isArray flag on Array.prototype
2607        final ScriptObject arrayPrototype = getArrayPrototype();
2608        arrayPrototype.setIsArray();
2609
2610        if (env._es6) {
2611            this.symbol   = LAZY_SENTINEL;
2612            this.map      = LAZY_SENTINEL;
2613            this.weakMap  = LAZY_SENTINEL;
2614            this.set      = LAZY_SENTINEL;
2615            this.weakSet  = LAZY_SENTINEL;
2616        } else {
2617            // We need to manually delete nasgen-generated properties we don't want
2618            this.delete("Symbol", false);
2619            this.delete("Map", false);
2620            this.delete("WeakMap", false);
2621            this.delete("Set", false);
2622            this.delete("WeakSet", false);
2623            builtinObject.delete("getOwnPropertySymbols", false);
2624            arrayPrototype.delete("entries", false);
2625            arrayPrototype.delete("keys", false);
2626            arrayPrototype.delete("values", false);
2627        }
2628
2629        // Error stuff
2630        initErrorObjects();
2631
2632        // java access
2633        if (! env._no_java) {
2634            this.javaApi = LAZY_SENTINEL;
2635            this.javaImporter = LAZY_SENTINEL;
2636            initJavaAccess();
2637        } else {
2638            // delete nasgen-created global properties related to java access
2639            this.delete("Java", false);
2640            this.delete("JavaImporter", false);
2641            this.delete("Packages", false);
2642            this.delete("com", false);
2643            this.delete("edu", false);
2644            this.delete("java", false);
2645            this.delete("javafx", false);
2646            this.delete("javax", false);
2647            this.delete("org", false);
2648        }
2649
2650        if (! env._no_typed_arrays) {
2651            this.arrayBuffer       = LAZY_SENTINEL;
2652            this.dataView          = LAZY_SENTINEL;
2653            this.int8Array         = LAZY_SENTINEL;
2654            this.uint8Array        = LAZY_SENTINEL;
2655            this.uint8ClampedArray = LAZY_SENTINEL;
2656            this.int16Array        = LAZY_SENTINEL;
2657            this.uint16Array       = LAZY_SENTINEL;
2658            this.int32Array        = LAZY_SENTINEL;
2659            this.uint32Array       = LAZY_SENTINEL;
2660            this.float32Array      = LAZY_SENTINEL;
2661            this.float64Array      = LAZY_SENTINEL;
2662        }
2663
2664        if (env._scripting) {
2665            initScripting(env);
2666        }
2667
2668        if (Context.DEBUG) {
2669            boolean debugOkay;
2670            final SecurityManager sm = System.getSecurityManager();
2671            if (sm != null) {
2672                try {
2673                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2674                    debugOkay = true;
2675                } catch (final SecurityException ignored) {
2676                    // if no permission, don't initialize Debug object
2677                    debugOkay = false;
2678                }
2679
2680            } else {
2681                debugOkay = true;
2682            }
2683
2684            if (debugOkay) {
2685                initDebug();
2686            }
2687        }
2688
2689        copyBuiltins();
2690
2691        // expose script (command line) arguments as "arguments" property of global
2692        arguments = wrapAsObject(env.getArguments().toArray());
2693        if (env._scripting) {
2694            // synonym for "arguments" in scripting mode
2695            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2696        }
2697
2698        if (eng != null) {
2699            // default file name
2700            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2701            // __noSuchProperty__ hook for ScriptContext search of missing variables
2702            final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2703            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2704        }
2705    }
2706
2707    private void initErrorObjects() {
2708        // Error objects
2709        this.builtinError = initConstructor("Error", ScriptFunction.class);
2710        final ScriptObject errorProto = getErrorPrototype();
2711
2712        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2713        final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK);
2714        final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK);
2715        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2716        final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER);
2717        final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER);
2718        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2719        final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2720        final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2721        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2722        final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME);
2723        final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME);
2724        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2725
2726        // ECMA 15.11.4.2 Error.prototype.name
2727        // Error.prototype.name = "Error";
2728        errorProto.set(NativeError.NAME, "Error", 0);
2729        // ECMA 15.11.4.3 Error.prototype.message
2730        // Error.prototype.message = "";
2731        errorProto.set(NativeError.MESSAGE, "", 0);
2732
2733        tagBuiltinProperties("Error", builtinError);
2734
2735        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2736        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2737        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2738    }
2739
2740    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2741        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2742        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2743        prototype.set(NativeError.NAME, name, 0);
2744        prototype.set(NativeError.MESSAGE, "", 0);
2745        prototype.setInitialProto(errorProto);
2746        tagBuiltinProperties(name, cons);
2747        return cons;
2748    }
2749
2750    private void initJavaAccess() {
2751        final ScriptObject objectProto = getObjectPrototype();
2752        this.builtinPackages = new NativeJavaPackage("", objectProto);
2753        this.builtinCom = new NativeJavaPackage("com", objectProto);
2754        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2755        this.builtinJava = new NativeJavaPackage("java", objectProto);
2756        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2757        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2758        this.builtinOrg = new NativeJavaPackage("org", objectProto);
2759    }
2760
2761    private void initScripting(final ScriptEnvironment scriptEnv) {
2762        ScriptObject value;
2763        value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE);
2764        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2765
2766        value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY);
2767        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2768
2769        final String execName = ScriptingFunctions.EXEC_NAME;
2770        value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC);
2771        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2772
2773        // Nashorn extension: global.echo (scripting-mode-only)
2774        // alias for "print"
2775        value = (ScriptObject)get("print");
2776        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2777
2778        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2779        final ScriptObject options = newObject();
2780        copyOptions(options, scriptEnv);
2781        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2782
2783        // Nashorn extension: global.$ENV (scripting-mode-only)
2784        final ScriptObject env = newObject();
2785        if (System.getSecurityManager() == null) {
2786            // do not fill $ENV if we have a security manager around
2787            // Retrieve current state of ENV variables.
2788            env.putAll(System.getenv(), scriptEnv._strict);
2789
2790            // Set the PWD variable to a value that is guaranteed to be understood
2791            // by the underlying platform.
2792            env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
2793        }
2794        addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2795
2796        // add other special properties for exec support
2797        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2798        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2799        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2800    }
2801
2802    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2803        for (final Field f : scriptEnv.getClass().getFields()) {
2804            try {
2805                options.set(f.getName(), f.get(scriptEnv), 0);
2806            } catch (final IllegalArgumentException | IllegalAccessException exp) {
2807                throw new RuntimeException(exp);
2808            }
2809        }
2810    }
2811
2812    private void copyBuiltins() {
2813        this.array             = this.builtinArray;
2814        this._boolean          = this.builtinBoolean;
2815        this.error             = this.builtinError;
2816        this.function          = this.builtinFunction;
2817        this.com               = this.builtinCom;
2818        this.edu               = this.builtinEdu;
2819        this.java              = this.builtinJava;
2820        this.javafx            = this.builtinJavafx;
2821        this.javax             = this.builtinJavax;
2822        this.org               = this.builtinOrg;
2823        this.math              = this.builtinMath;
2824        this.number            = this.builtinNumber;
2825        this.object            = this.builtinObject;
2826        this.packages          = this.builtinPackages;
2827        this.referenceError    = this.builtinReferenceError;
2828        this.string            = this.builtinString;
2829        this.syntaxError       = this.builtinSyntaxError;
2830        this.typeError         = this.builtinTypeError;
2831    }
2832
2833    private void initDebug() {
2834        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2835    }
2836
2837    private Object printImpl(final boolean newLine, final Object... objects) {
2838        final ScriptContext sc = currentContext();
2839        @SuppressWarnings("resource")
2840        final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
2841        final StringBuilder sb = new StringBuilder();
2842
2843        for (final Object obj : objects) {
2844            if (sb.length() != 0) {
2845                sb.append(' ');
2846            }
2847
2848            sb.append(JSType.toString(obj));
2849        }
2850
2851        // Print all at once to ensure thread friendly result.
2852        if (newLine) {
2853            out.println(sb.toString());
2854        } else {
2855            out.print(sb.toString());
2856        }
2857
2858        out.flush();
2859
2860        return UNDEFINED;
2861    }
2862
2863    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2864        try {
2865            // Assuming class name pattern for built-in JS constructors.
2866            final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX);
2867
2868            sb.append("Native");
2869            sb.append(name);
2870            sb.append("$Constructor");
2871
2872            final Class<?> funcClass = Class.forName(sb.toString());
2873            final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance());
2874
2875            if (res instanceof ScriptFunction) {
2876                // All global constructor prototypes are not-writable,
2877                // not-enumerable and not-configurable.
2878                final ScriptFunction func = (ScriptFunction)res;
2879                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2880            }
2881
2882            if (res.getProto() == null) {
2883                res.setInitialProto(getObjectPrototype());
2884            }
2885
2886            res.setIsBuiltin();
2887
2888            return res;
2889        } catch (final Exception e) {
2890            if (e instanceof RuntimeException) {
2891                throw (RuntimeException)e;
2892            } else {
2893                throw new RuntimeException(e);
2894            }
2895        }
2896    }
2897
2898    private ScriptObject initPrototype(final String name, final ScriptObject prototype) {
2899        try {
2900            // Assuming class name pattern for JS prototypes
2901            final String className = PACKAGE_PREFIX + name + "$Prototype";
2902
2903            final Class<?> funcClass = Class.forName(className);
2904            final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance();
2905
2906            res.setIsBuiltin();
2907            res.setInitialProto(prototype);
2908            return res;
2909        } catch (final Exception e) {
2910            if (e instanceof RuntimeException) {
2911                throw (RuntimeException)e;
2912            } else {
2913                throw new RuntimeException(e);
2914            }
2915        }
2916    }
2917
2918    private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2919        final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2920
2921        list.addAll(Arrays.asList(func.getMap().getProperties()));
2922
2923        if (func instanceof ScriptFunction) {
2924            final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2925            if (proto != null) {
2926                list.addAll(Arrays.asList(proto.getMap().getProperties()));
2927            }
2928        }
2929
2930        final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2931        if (prop != null) {
2932            list.add(prop);
2933        }
2934
2935        return list;
2936    }
2937
2938    /**
2939     * Given a builtin object, traverse its properties recursively and associate them with a name that
2940     * will be a key to their invalidation switchpoint.
2941     * @param name name for key
2942     * @param func builtin script object
2943     */
2944    private void tagBuiltinProperties(final String name, final ScriptObject func) {
2945        SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2946        if (sp == null) {
2947            sp = context.newBuiltinSwitchPoint(name);
2948        }
2949
2950        //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2951        //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2952        for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2953            prop.setBuiltinSwitchPoint(sp);
2954        }
2955    }
2956
2957    // Function and Object constructors are inter-dependent. Also,
2958    // Function.prototype
2959    // functions are not properly initialized. We fix the references here.
2960    // NOTE: be careful if you want to re-order the operations here. You may
2961    // have
2962    // to play with object references carefully!!
2963    private void initFunctionAndObject() {
2964        // First-n-foremost is Function
2965
2966        this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2967
2968        // create global anonymous function
2969        final ScriptFunction anon = ScriptFunction.createAnonymous();
2970        // need to copy over members of Function.prototype to anon function
2971        anon.addBoundProperties(getFunctionPrototype());
2972
2973        // Function.prototype === Object.getPrototypeOf(Function) ===
2974        // <anon-function>
2975        builtinFunction.setInitialProto(anon);
2976        builtinFunction.setPrototype(anon);
2977        anon.set("constructor", builtinFunction, 0);
2978        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2979
2980        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2981        this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
2982        typeErrorThrower.preventExtensions();
2983
2984        // now initialize Object
2985        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2986        final ScriptObject ObjectPrototype = getObjectPrototype();
2987        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2988        anon.setInitialProto(ObjectPrototype);
2989
2990        // ES6 draft compliant __proto__ property of Object.prototype
2991        // accessors on Object.prototype for "__proto__"
2992        final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__);
2993        final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__);
2994        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2995
2996        // Function valued properties of Function.prototype were not properly
2997        // initialized. Because, these were created before global.function and
2998        // global.object were not initialized.
2999        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
3000        for (final jdk.nashorn.internal.runtime.Property property : properties) {
3001            final Object key = property.getKey();
3002            final Object value = builtinFunction.get(key);
3003
3004            if (value instanceof ScriptFunction && value != anon) {
3005                final ScriptFunction func = (ScriptFunction)value;
3006                func.setInitialProto(getFunctionPrototype());
3007                final ScriptObject prototype = ScriptFunction.getPrototype(func);
3008                if (prototype != null) {
3009                    prototype.setInitialProto(ObjectPrototype);
3010                }
3011            }
3012        }
3013
3014        // For function valued properties of Object and Object.prototype, make
3015        // sure prototype's proto chain ends with Object.prototype
3016        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
3017            final Object key = property.getKey();
3018            final Object value = builtinObject.get(key);
3019
3020            if (value instanceof ScriptFunction) {
3021                final ScriptFunction func = (ScriptFunction)value;
3022                final ScriptObject prototype = ScriptFunction.getPrototype(func);
3023                if (prototype != null) {
3024                    prototype.setInitialProto(ObjectPrototype);
3025                }
3026            }
3027        }
3028
3029        properties = getObjectPrototype().getMap().getProperties();
3030
3031        for (final jdk.nashorn.internal.runtime.Property property : properties) {
3032            final Object key   = property.getKey();
3033            if (key.equals("constructor")) {
3034                continue;
3035            }
3036
3037            final Object value = ObjectPrototype.get(key);
3038            if (value instanceof ScriptFunction) {
3039                final ScriptFunction func = (ScriptFunction)value;
3040                final ScriptObject prototype = ScriptFunction.getPrototype(func);
3041                if (prototype != null) {
3042                    prototype.setInitialProto(ObjectPrototype);
3043                }
3044            }
3045        }
3046
3047        tagBuiltinProperties("Object", builtinObject);
3048        tagBuiltinProperties("Function", builtinFunction);
3049        tagBuiltinProperties("Function", anon);
3050    }
3051
3052    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
3053        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
3054    }
3055
3056    RegExpResult getLastRegExpResult() {
3057        return lastRegExpResult;
3058    }
3059
3060    void setLastRegExpResult(final RegExpResult regExpResult) {
3061        this.lastRegExpResult = regExpResult;
3062    }
3063
3064    @Override
3065    protected boolean isGlobal() {
3066        return true;
3067    }
3068
3069    /**
3070     * A class representing the ES6 global lexical scope.
3071     */
3072    private static class LexicalScope extends ScriptObject {
3073
3074        LexicalScope(final Global global) {
3075            super(global, PropertyMap.newMap());
3076            setIsInternal();
3077        }
3078
3079        @Override
3080        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3081            return filterInvocation(super.findGetMethod(desc, request));
3082        }
3083
3084        @Override
3085        protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3086            return filterInvocation(super.findSetMethod(desc, request));
3087        }
3088
3089        @Override
3090        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
3091            // We override this method just to make it callable by Global
3092            return super.addBoundProperty(propMap, source, property, extensible);
3093        }
3094
3095        private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
3096            final MethodType type = invocation.getInvocation().type();
3097            return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
3098        }
3099    }
3100
3101}
3102