Global.java revision 1805:7caf1f762f1d
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    // This also serves as placeholder value used in place of a location property
94    // (__FILE__, __DIR__, __LINE__)
95    private static final Object LAZY_SENTINEL = 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__ = LAZY_SENTINEL;
979
980    /** Nashorn extension: current script's directory */
981    @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
982    public static final Object __DIR__ = LAZY_SENTINEL;
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__ = LAZY_SENTINEL;
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 (this.builtinJavaImporter == null) {
2097            this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
2098        }
2099        return this.builtinJavaImporter;
2100    }
2101
2102    private synchronized ScriptObject getBuiltinJavaApi() {
2103        if (this.builtinJavaApi == null) {
2104            this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
2105            this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend");
2106            this.builtInJavaTo = (ScriptFunction)builtinJavaApi.get("to");
2107        }
2108        return this.builtinJavaApi;
2109    }
2110
2111    /**
2112     * Returns true if the passed function is the built-in "Java.extend".
2113     * @param fn the function in question
2114     * @return true if the function is built-in "Java.extend"
2115     */
2116    public static boolean isBuiltInJavaExtend(final ScriptFunction fn) {
2117        if(!"extend".equals(fn.getName())) {
2118            // Avoid hitting the thread local if the name doesn't match.
2119            return false;
2120        }
2121        return fn == Context.getGlobal().builtInJavaExtend;
2122    }
2123
2124    /**
2125     * Returns true if the passed function is the built-in "Java.to".
2126     * @param fn the function in question
2127     * @return true if the function is built-in "Java.to"
2128     */
2129    public static boolean isBuiltInJavaTo(final ScriptFunction fn) {
2130        if(!"to".equals(fn.getName())) {
2131            // Avoid hitting the thread local if the name doesn't match.
2132            return false;
2133        }
2134        return fn == Context.getGlobal().builtInJavaTo;
2135    }
2136
2137
2138    private synchronized ScriptFunction getBuiltinRangeError() {
2139        if (this.builtinRangeError == null) {
2140            this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2141        }
2142        return builtinRangeError;
2143    }
2144
2145    private synchronized ScriptFunction getBuiltinRegExp() {
2146        if (this.builtinRegExp == null) {
2147            this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2148            final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2149            // initialize default regexp object
2150            this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2151            // RegExp.prototype should behave like a RegExp object. So copy the
2152            // properties.
2153            regExpProto.addBoundProperties(DEFAULT_REGEXP);
2154        }
2155        return builtinRegExp;
2156    }
2157
2158    private synchronized ScriptFunction getBuiltinURIError() {
2159        if (this.builtinURIError == null) {
2160            this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2161        }
2162        return this.builtinURIError;
2163    }
2164
2165    private synchronized ScriptFunction getBuiltinSymbol() {
2166        if (this.builtinSymbol == null) {
2167            this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class);
2168        }
2169        return this.builtinSymbol;
2170    }
2171
2172    private synchronized ScriptFunction getBuiltinMap() {
2173        if (this.builtinMap == null) {
2174            this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class);
2175        }
2176        return this.builtinMap;
2177    }
2178
2179    private synchronized ScriptFunction getBuiltinWeakMap() {
2180        if (this.builtinWeakMap == null) {
2181            this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class);
2182        }
2183        return this.builtinWeakMap;
2184    }
2185
2186    private synchronized ScriptFunction getBuiltinSet() {
2187        if (this.builtinSet == null) {
2188            this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class);
2189        }
2190        return this.builtinSet;
2191    }
2192
2193    private synchronized ScriptFunction getBuiltinWeakSet() {
2194        if (this.builtinWeakSet == null) {
2195            this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class);
2196        }
2197        return this.builtinWeakSet;
2198    }
2199
2200    @Override
2201    public String getClassName() {
2202        return "global";
2203    }
2204
2205    /**
2206     * Copy function used to clone NativeRegExp objects.
2207     *
2208     * @param regexp a NativeRegExp to clone
2209     *
2210     * @return copy of the given regexp object
2211     */
2212    public static Object regExpCopy(final Object regexp) {
2213        return new NativeRegExp((NativeRegExp)regexp);
2214    }
2215
2216    /**
2217     * Convert given object to NativeRegExp type.
2218     *
2219     * @param obj object to be converted
2220     * @return NativeRegExp instance
2221     */
2222    public static NativeRegExp toRegExp(final Object obj) {
2223        if (obj instanceof NativeRegExp) {
2224            return (NativeRegExp)obj;
2225        }
2226        return new NativeRegExp(JSType.toString(obj));
2227    }
2228
2229    /**
2230     * ECMA 9.9 ToObject implementation
2231     *
2232     * @param obj  an item for which to run ToObject
2233     * @return ToObject version of given item
2234     */
2235    public static Object toObject(final Object obj) {
2236        if (obj == null || obj == UNDEFINED) {
2237            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2238        }
2239
2240        if (obj instanceof ScriptObject) {
2241            return obj;
2242        }
2243
2244        return instance().wrapAsObject(obj);
2245    }
2246
2247    /**
2248     * Allocate a new object array.
2249     *
2250     * @param initial object values.
2251     * @return the new array
2252     */
2253    public static NativeArray allocate(final Object[] initial) {
2254        ArrayData arrayData = ArrayData.allocate(initial);
2255
2256        for (int index = 0; index < initial.length; index++) {
2257            final Object value = initial[index];
2258
2259            if (value == ScriptRuntime.EMPTY) {
2260                arrayData = arrayData.delete(index);
2261            }
2262        }
2263
2264        return new NativeArray(arrayData);
2265    }
2266
2267    /**
2268     * Allocate a new number array.
2269     *
2270     * @param initial number values.
2271     * @return the new array
2272     */
2273    public static NativeArray allocate(final double[] initial) {
2274        return new NativeArray(ArrayData.allocate(initial));
2275    }
2276
2277    /**
2278     * Allocate a new integer array.
2279     *
2280     * @param initial number values.
2281     * @return the new array
2282     */
2283    public static NativeArray allocate(final int[] initial) {
2284        return new NativeArray(ArrayData.allocate(initial));
2285    }
2286
2287    /**
2288     * Allocate a new object array for arguments.
2289     *
2290     * @param arguments initial arguments passed.
2291     * @param callee reference to the function that uses arguments object
2292     * @param numParams actual number of declared parameters
2293     *
2294     * @return the new array
2295     */
2296    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2297        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2298    }
2299
2300    /**
2301     * Called from generated to check if given function is the builtin 'eval'. If
2302     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2303     *
2304     * @param  fn function object that is checked
2305     * @return true if fn is the builtin eval
2306     */
2307    public static boolean isEval(final Object fn) {
2308        return fn == Global.instance().builtinEval;
2309    }
2310
2311    /**
2312     * Called from generated to replace a location property placeholder with the actual location property value.
2313     *
2314     * @param  placeholder the value tested for being a placeholder for a location property
2315     * @param  locationProperty the actual value for the location property
2316     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2317     */
2318    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2319        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2320    }
2321
2322    /**
2323     * Called from runtime internals to check if the passed value is a location property placeholder.
2324     * @param  placeholder the value tested for being a placeholder for a location property
2325     * @return true if the value is a placeholder, false otherwise.
2326     */
2327    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2328        return placeholder == LAZY_SENTINEL;
2329    }
2330
2331    /**
2332     * Create a new RegExp object.
2333     *
2334     * @param expression Regular expression.
2335     * @param options    Search options.
2336     *
2337     * @return New RegExp object.
2338     */
2339    public static Object newRegExp(final String expression, final String options) {
2340        if (options == null) {
2341            return new NativeRegExp(expression);
2342        }
2343        return new NativeRegExp(expression, options);
2344    }
2345
2346    /**
2347     * Get the object prototype
2348     *
2349     * @return the object prototype
2350     */
2351    public static ScriptObject objectPrototype() {
2352        return Global.instance().getObjectPrototype();
2353    }
2354
2355    /**
2356     * Create a new empty object instance.
2357     *
2358     * @return New empty object.
2359     */
2360    public static ScriptObject newEmptyInstance() {
2361        return Global.instance().newObject();
2362    }
2363
2364    /**
2365     * Check if a given object is a ScriptObject, raises an exception if this is
2366     * not the case
2367     *
2368     * @param obj and object to check
2369     * @return the script object
2370     */
2371    public static ScriptObject checkObject(final Object obj) {
2372        if (!(obj instanceof ScriptObject)) {
2373            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2374        }
2375        return (ScriptObject)obj;
2376    }
2377
2378    /**
2379     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2380     * if this object is null or undefined.
2381     *
2382     * @param obj an object to check
2383     */
2384    public static void checkObjectCoercible(final Object obj) {
2385        if (obj == null || obj == UNDEFINED) {
2386            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2387        }
2388    }
2389
2390    /**
2391     * Return the ES6 global scope for lexically declared bindings.
2392     * @return the ES6 lexical global scope.
2393     */
2394    public final ScriptObject getLexicalScope() {
2395        assert context.getEnv()._es6;
2396        return lexicalScope;
2397    }
2398
2399    @Override
2400    public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2401        PropertyMap ownMap = getMap();
2402        LexicalScope lexScope = null;
2403        PropertyMap lexicalMap = null;
2404        boolean hasLexicalDefinitions = false;
2405
2406        if (context.getEnv()._es6) {
2407            lexScope = (LexicalScope) getLexicalScope();
2408            lexicalMap = lexScope.getMap();
2409
2410            for (final jdk.nashorn.internal.runtime.Property property : properties) {
2411                if (property.isLexicalBinding()) {
2412                    hasLexicalDefinitions = true;
2413                }
2414                // ES6 15.1.8 steps 6. and 7.
2415                final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2416                if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2417                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2418                }
2419                final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2420                if (lexicalProperty != null && !property.isConfigurable()) {
2421                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2422                }
2423            }
2424        }
2425
2426        final boolean extensible = isExtensible();
2427        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2428            if (property.isLexicalBinding()) {
2429                assert lexScope != null;
2430                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
2431
2432                if (ownMap.findProperty(property.getKey()) != null) {
2433                    // If property exists in the global object invalidate any global constant call sites.
2434                    invalidateGlobalConstant(property.getKey());
2435                }
2436            } else {
2437                ownMap = addBoundProperty(ownMap, source, property, extensible);
2438            }
2439        }
2440
2441        setMap(ownMap);
2442
2443        if (hasLexicalDefinitions) {
2444            assert lexScope != null;
2445            lexScope.setMap(lexicalMap);
2446            invalidateLexicalSwitchPoint();
2447        }
2448    }
2449
2450    @Override
2451    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2452        final String name = NashornCallSiteDescriptor.getOperand(desc);
2453        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2454
2455        if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2456            if (lexicalScope.hasOwnProperty(name)) {
2457                return lexicalScope.findGetMethod(desc, request);
2458            }
2459        }
2460
2461        final GuardedInvocation invocation =  super.findGetMethod(desc, request);
2462
2463        // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2464        // because those are invalidated per-key in the addBoundProperties method above.
2465        // We therefore check if the invocation does already have a switchpoint and the property is non-inherited,
2466        // assuming this only applies to global constants. If other non-inherited properties will
2467        // start using switchpoints some time in the future we'll have to revisit this.
2468        if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2469            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2470        }
2471
2472        return invocation;
2473    }
2474
2475    @Override
2476    protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) {
2477        if (lexicalScope != null && isScope) {
2478            final FindProperty find = lexicalScope.findProperty(key, false);
2479            if (find != null) {
2480                return find;
2481            }
2482        }
2483        return super.findProperty(key, deep, isScope, start);
2484    }
2485
2486    @Override
2487    public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2488        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2489
2490        if (lexicalScope != null && isScope) {
2491            final String name = NashornCallSiteDescriptor.getOperand(desc);
2492            if (lexicalScope.hasOwnProperty(name)) {
2493                return lexicalScope.findSetMethod(desc, request);
2494            }
2495        }
2496
2497        final GuardedInvocation invocation = super.findSetMethod(desc, request);
2498
2499        if (isScope && context.getEnv()._es6) {
2500            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2501        }
2502
2503        return invocation;
2504    }
2505
2506    /**
2507     * Adds jjs shell interactive mode builtin functions to global scope.
2508     */
2509    public void addShellBuiltins() {
2510        Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT);
2511        addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2512
2513        value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT);
2514        addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2515    }
2516
2517    private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2518        SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2519        if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2520            switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2521        }
2522        return switchPoint;
2523    }
2524
2525    private synchronized void invalidateLexicalSwitchPoint() {
2526        if (lexicalScopeSwitchPoint != null) {
2527            context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2528            SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2529        }
2530    }
2531
2532
2533    @SuppressWarnings("unused")
2534    private static Object lexicalScopeFilter(final Object self) {
2535        if (self instanceof Global) {
2536            return ((Global) self).getLexicalScope();
2537        }
2538        return self;
2539    }
2540
2541    private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2542        final T func = initConstructor(name, clazz);
2543        tagBuiltinProperties(name, func);
2544        return func;
2545    }
2546
2547    private void init(final ScriptEngine eng) {
2548        assert Context.getGlobal() == this : "this global is not set as current";
2549
2550        final ScriptEnvironment env = getContext().getEnv();
2551
2552        // initialize Function and Object constructor
2553        initFunctionAndObject();
2554
2555        // Now fix Global's own proto.
2556        this.setInitialProto(getObjectPrototype());
2557
2558        // initialize global function properties
2559        this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL);
2560
2561        this.parseInt = ScriptFunction.createBuiltin("parseInt",   GlobalFunctions.PARSEINT,
2562                    new Specialization[] {
2563                    new Specialization(GlobalFunctions.PARSEINT_Z),
2564                    new Specialization(GlobalFunctions.PARSEINT_I),
2565                    new Specialization(GlobalFunctions.PARSEINT_OI),
2566                    new Specialization(GlobalFunctions.PARSEINT_O) });
2567        this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2568        this.isNaN = ScriptFunction.createBuiltin("isNaN",   GlobalFunctions.IS_NAN,
2569                   new Specialization[] {
2570                        new Specialization(GlobalFunctions.IS_NAN_I),
2571                        new Specialization(GlobalFunctions.IS_NAN_J),
2572                        new Specialization(GlobalFunctions.IS_NAN_D) });
2573        this.parseFloat         = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2574        this.isNaN              = ScriptFunction.createBuiltin("isNaN",      GlobalFunctions.IS_NAN);
2575        this.isFinite           = ScriptFunction.createBuiltin("isFinite",   GlobalFunctions.IS_FINITE);
2576        this.encodeURI          = ScriptFunction.createBuiltin("encodeURI",  GlobalFunctions.ENCODE_URI);
2577        this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2578        this.decodeURI          = ScriptFunction.createBuiltin("decodeURI",  GlobalFunctions.DECODE_URI);
2579        this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2580        this.escape             = ScriptFunction.createBuiltin("escape",     GlobalFunctions.ESCAPE);
2581        this.unescape           = ScriptFunction.createBuiltin("unescape",   GlobalFunctions.UNESCAPE);
2582        this.print              = ScriptFunction.createBuiltin("print",      env._print_no_newline ? PRINT : PRINTLN);
2583        this.load               = ScriptFunction.createBuiltin("load",       LOAD);
2584        this.loadWithNewGlobal  = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2585        this.exit               = ScriptFunction.createBuiltin("exit",       EXIT);
2586        this.quit               = ScriptFunction.createBuiltin("quit",       EXIT);
2587
2588        // built-in constructors
2589        this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2590        this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2591        this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2592        this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2593        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2594
2595        // initialize String.prototype.length to 0
2596        // add String.prototype.length
2597        final ScriptObject stringPrototype = getStringPrototype();
2598        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2599
2600        // set isArray flag on Array.prototype
2601        final ScriptObject arrayPrototype = getArrayPrototype();
2602        arrayPrototype.setIsArray();
2603
2604        if (env._es6) {
2605            this.symbol   = LAZY_SENTINEL;
2606            this.map      = LAZY_SENTINEL;
2607            this.weakMap  = LAZY_SENTINEL;
2608            this.set      = LAZY_SENTINEL;
2609            this.weakSet  = LAZY_SENTINEL;
2610        } else {
2611            // We need to manually delete nasgen-generated properties we don't want
2612            this.delete("Symbol", false);
2613            this.delete("Map", false);
2614            this.delete("WeakMap", false);
2615            this.delete("Set", false);
2616            this.delete("WeakSet", false);
2617            builtinObject.delete("getOwnPropertySymbols", false);
2618            arrayPrototype.delete("entries", false);
2619            arrayPrototype.delete("keys", false);
2620            arrayPrototype.delete("values", false);
2621        }
2622
2623        // Error stuff
2624        initErrorObjects();
2625
2626        // java access
2627        if (! env._no_java) {
2628            this.javaApi = LAZY_SENTINEL;
2629            this.javaImporter = LAZY_SENTINEL;
2630            initJavaAccess();
2631        }
2632
2633        if (! env._no_typed_arrays) {
2634            this.arrayBuffer       = LAZY_SENTINEL;
2635            this.dataView          = LAZY_SENTINEL;
2636            this.int8Array         = LAZY_SENTINEL;
2637            this.uint8Array        = LAZY_SENTINEL;
2638            this.uint8ClampedArray = LAZY_SENTINEL;
2639            this.int16Array        = LAZY_SENTINEL;
2640            this.uint16Array       = LAZY_SENTINEL;
2641            this.int32Array        = LAZY_SENTINEL;
2642            this.uint32Array       = LAZY_SENTINEL;
2643            this.float32Array      = LAZY_SENTINEL;
2644            this.float64Array      = LAZY_SENTINEL;
2645        }
2646
2647        if (env._scripting) {
2648            initScripting(env);
2649        }
2650
2651        if (Context.DEBUG) {
2652            boolean debugOkay;
2653            final SecurityManager sm = System.getSecurityManager();
2654            if (sm != null) {
2655                try {
2656                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2657                    debugOkay = true;
2658                } catch (final SecurityException ignored) {
2659                    // if no permission, don't initialize Debug object
2660                    debugOkay = false;
2661                }
2662
2663            } else {
2664                debugOkay = true;
2665            }
2666
2667            if (debugOkay) {
2668                initDebug();
2669            }
2670        }
2671
2672        copyBuiltins();
2673
2674        // expose script (command line) arguments as "arguments" property of global
2675        arguments = wrapAsObject(env.getArguments().toArray());
2676        if (env._scripting) {
2677            // synonym for "arguments" in scripting mode
2678            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2679        }
2680
2681        if (eng != null) {
2682            // default file name
2683            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2684            // __noSuchProperty__ hook for ScriptContext search of missing variables
2685            final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2686            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2687        }
2688    }
2689
2690    private void initErrorObjects() {
2691        // Error objects
2692        this.builtinError = initConstructor("Error", ScriptFunction.class);
2693        final ScriptObject errorProto = getErrorPrototype();
2694
2695        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2696        final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK);
2697        final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK);
2698        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2699        final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER);
2700        final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER);
2701        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2702        final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2703        final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2704        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2705        final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME);
2706        final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME);
2707        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2708
2709        // ECMA 15.11.4.2 Error.prototype.name
2710        // Error.prototype.name = "Error";
2711        errorProto.set(NativeError.NAME, "Error", 0);
2712        // ECMA 15.11.4.3 Error.prototype.message
2713        // Error.prototype.message = "";
2714        errorProto.set(NativeError.MESSAGE, "", 0);
2715
2716        tagBuiltinProperties("Error", builtinError);
2717
2718        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2719        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2720        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2721    }
2722
2723    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2724        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2725        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2726        prototype.set(NativeError.NAME, name, 0);
2727        prototype.set(NativeError.MESSAGE, "", 0);
2728        prototype.setInitialProto(errorProto);
2729        tagBuiltinProperties(name, cons);
2730        return cons;
2731    }
2732
2733    private void initJavaAccess() {
2734        final ScriptObject objectProto = getObjectPrototype();
2735        this.builtinPackages = new NativeJavaPackage("", objectProto);
2736        this.builtinCom = new NativeJavaPackage("com", objectProto);
2737        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2738        this.builtinJava = new NativeJavaPackage("java", objectProto);
2739        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2740        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2741        this.builtinOrg = new NativeJavaPackage("org", objectProto);
2742    }
2743
2744    private void initScripting(final ScriptEnvironment scriptEnv) {
2745        ScriptObject value;
2746        value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE);
2747        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2748
2749        value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY);
2750        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2751
2752        final String execName = ScriptingFunctions.EXEC_NAME;
2753        value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC);
2754        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2755
2756        // Nashorn extension: global.echo (scripting-mode-only)
2757        // alias for "print"
2758        value = (ScriptObject)get("print");
2759        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2760
2761        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2762        final ScriptObject options = newObject();
2763        copyOptions(options, scriptEnv);
2764        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2765
2766        // Nashorn extension: global.$ENV (scripting-mode-only)
2767        final ScriptObject env = newObject();
2768        if (System.getSecurityManager() == null) {
2769            // do not fill $ENV if we have a security manager around
2770            // Retrieve current state of ENV variables.
2771            env.putAll(System.getenv(), scriptEnv._strict);
2772
2773            // Set the PWD variable to a value that is guaranteed to be understood
2774            // by the underlying platform.
2775            env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
2776        }
2777        addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2778
2779        // add other special properties for exec support
2780        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2781        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2782        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2783    }
2784
2785    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2786        for (final Field f : scriptEnv.getClass().getFields()) {
2787            try {
2788                options.set(f.getName(), f.get(scriptEnv), 0);
2789            } catch (final IllegalArgumentException | IllegalAccessException exp) {
2790                throw new RuntimeException(exp);
2791            }
2792        }
2793    }
2794
2795    private void copyBuiltins() {
2796        this.array             = this.builtinArray;
2797        this._boolean          = this.builtinBoolean;
2798        this.error             = this.builtinError;
2799        this.function          = this.builtinFunction;
2800        this.com               = this.builtinCom;
2801        this.edu               = this.builtinEdu;
2802        this.java              = this.builtinJava;
2803        this.javafx            = this.builtinJavafx;
2804        this.javax             = this.builtinJavax;
2805        this.org               = this.builtinOrg;
2806        this.math              = this.builtinMath;
2807        this.number            = this.builtinNumber;
2808        this.object            = this.builtinObject;
2809        this.packages          = this.builtinPackages;
2810        this.referenceError    = this.builtinReferenceError;
2811        this.string            = this.builtinString;
2812        this.syntaxError       = this.builtinSyntaxError;
2813        this.typeError         = this.builtinTypeError;
2814    }
2815
2816    private void initDebug() {
2817        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2818    }
2819
2820    private Object printImpl(final boolean newLine, final Object... objects) {
2821        final ScriptContext sc = currentContext();
2822        @SuppressWarnings("resource")
2823        final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
2824        final StringBuilder sb = new StringBuilder();
2825
2826        for (final Object obj : objects) {
2827            if (sb.length() != 0) {
2828                sb.append(' ');
2829            }
2830
2831            sb.append(JSType.toString(obj));
2832        }
2833
2834        // Print all at once to ensure thread friendly result.
2835        if (newLine) {
2836            out.println(sb.toString());
2837        } else {
2838            out.print(sb.toString());
2839        }
2840
2841        out.flush();
2842
2843        return UNDEFINED;
2844    }
2845
2846    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2847        try {
2848            // Assuming class name pattern for built-in JS constructors.
2849            final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX);
2850
2851            sb.append("Native");
2852            sb.append(name);
2853            sb.append("$Constructor");
2854
2855            final Class<?> funcClass = Class.forName(sb.toString());
2856            final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance());
2857
2858            if (res instanceof ScriptFunction) {
2859                // All global constructor prototypes are not-writable,
2860                // not-enumerable and not-configurable.
2861                final ScriptFunction func = (ScriptFunction)res;
2862                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2863            }
2864
2865            if (res.getProto() == null) {
2866                res.setInitialProto(getObjectPrototype());
2867            }
2868
2869            res.setIsBuiltin();
2870
2871            return res;
2872        } catch (final Exception e) {
2873            if (e instanceof RuntimeException) {
2874                throw (RuntimeException)e;
2875            } else {
2876                throw new RuntimeException(e);
2877            }
2878        }
2879    }
2880
2881    private ScriptObject initPrototype(final String name, final ScriptObject prototype) {
2882        try {
2883            // Assuming class name pattern for JS prototypes
2884            final String className = PACKAGE_PREFIX + name + "$Prototype";
2885
2886            final Class<?> funcClass = Class.forName(className);
2887            final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance();
2888
2889            res.setIsBuiltin();
2890            res.setInitialProto(prototype);
2891            return res;
2892        } catch (final Exception e) {
2893            if (e instanceof RuntimeException) {
2894                throw (RuntimeException)e;
2895            } else {
2896                throw new RuntimeException(e);
2897            }
2898        }
2899    }
2900
2901    private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2902        final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2903
2904        list.addAll(Arrays.asList(func.getMap().getProperties()));
2905
2906        if (func instanceof ScriptFunction) {
2907            final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2908            if (proto != null) {
2909                list.addAll(Arrays.asList(proto.getMap().getProperties()));
2910            }
2911        }
2912
2913        final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2914        if (prop != null) {
2915            list.add(prop);
2916        }
2917
2918        return list;
2919    }
2920
2921    /**
2922     * Given a builtin object, traverse its properties recursively and associate them with a name that
2923     * will be a key to their invalidation switchpoint.
2924     * @param name name for key
2925     * @param func builtin script object
2926     */
2927    private void tagBuiltinProperties(final String name, final ScriptObject func) {
2928        SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2929        if (sp == null) {
2930            sp = context.newBuiltinSwitchPoint(name);
2931        }
2932
2933        //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2934        //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2935        for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2936            prop.setBuiltinSwitchPoint(sp);
2937        }
2938    }
2939
2940    // Function and Object constructors are inter-dependent. Also,
2941    // Function.prototype
2942    // functions are not properly initialized. We fix the references here.
2943    // NOTE: be careful if you want to re-order the operations here. You may
2944    // have
2945    // to play with object references carefully!!
2946    private void initFunctionAndObject() {
2947        // First-n-foremost is Function
2948
2949        this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2950
2951        // create global anonymous function
2952        final ScriptFunction anon = ScriptFunction.createAnonymous();
2953        // need to copy over members of Function.prototype to anon function
2954        anon.addBoundProperties(getFunctionPrototype());
2955
2956        // Function.prototype === Object.getPrototypeOf(Function) ===
2957        // <anon-function>
2958        builtinFunction.setInitialProto(anon);
2959        builtinFunction.setPrototype(anon);
2960        anon.set("constructor", builtinFunction, 0);
2961        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2962
2963        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2964        this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
2965        typeErrorThrower.preventExtensions();
2966
2967        // now initialize Object
2968        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2969        final ScriptObject ObjectPrototype = getObjectPrototype();
2970        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2971        anon.setInitialProto(ObjectPrototype);
2972
2973        // ES6 draft compliant __proto__ property of Object.prototype
2974        // accessors on Object.prototype for "__proto__"
2975        final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__);
2976        final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__);
2977        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2978
2979        // Function valued properties of Function.prototype were not properly
2980        // initialized. Because, these were created before global.function and
2981        // global.object were not initialized.
2982        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2983        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2984            final Object key = property.getKey();
2985            final Object value = builtinFunction.get(key);
2986
2987            if (value instanceof ScriptFunction && value != anon) {
2988                final ScriptFunction func = (ScriptFunction)value;
2989                func.setInitialProto(getFunctionPrototype());
2990                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2991                if (prototype != null) {
2992                    prototype.setInitialProto(ObjectPrototype);
2993                }
2994            }
2995        }
2996
2997        // For function valued properties of Object and Object.prototype, make
2998        // sure prototype's proto chain ends with Object.prototype
2999        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
3000            final Object key = property.getKey();
3001            final Object value = builtinObject.get(key);
3002
3003            if (value instanceof ScriptFunction) {
3004                final ScriptFunction func = (ScriptFunction)value;
3005                final ScriptObject prototype = ScriptFunction.getPrototype(func);
3006                if (prototype != null) {
3007                    prototype.setInitialProto(ObjectPrototype);
3008                }
3009            }
3010        }
3011
3012        properties = getObjectPrototype().getMap().getProperties();
3013
3014        for (final jdk.nashorn.internal.runtime.Property property : properties) {
3015            final Object key   = property.getKey();
3016            if (key.equals("constructor")) {
3017                continue;
3018            }
3019
3020            final Object value = ObjectPrototype.get(key);
3021            if (value instanceof ScriptFunction) {
3022                final ScriptFunction func = (ScriptFunction)value;
3023                final ScriptObject prototype = ScriptFunction.getPrototype(func);
3024                if (prototype != null) {
3025                    prototype.setInitialProto(ObjectPrototype);
3026                }
3027            }
3028        }
3029
3030        tagBuiltinProperties("Object", builtinObject);
3031        tagBuiltinProperties("Function", builtinFunction);
3032        tagBuiltinProperties("Function", anon);
3033    }
3034
3035    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
3036        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
3037    }
3038
3039    RegExpResult getLastRegExpResult() {
3040        return lastRegExpResult;
3041    }
3042
3043    void setLastRegExpResult(final RegExpResult regExpResult) {
3044        this.lastRegExpResult = regExpResult;
3045    }
3046
3047    @Override
3048    protected boolean isGlobal() {
3049        return true;
3050    }
3051
3052    /**
3053     * A class representing the ES6 global lexical scope.
3054     */
3055    private static class LexicalScope extends ScriptObject {
3056
3057        LexicalScope(final Global global) {
3058            super(global, PropertyMap.newMap());
3059            setIsInternal();
3060        }
3061
3062        @Override
3063        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3064            return filterInvocation(super.findGetMethod(desc, request));
3065        }
3066
3067        @Override
3068        protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3069            return filterInvocation(super.findSetMethod(desc, request));
3070        }
3071
3072        @Override
3073        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
3074            // We override this method just to make it callable by Global
3075            return super.addBoundProperty(propMap, source, property, extensible);
3076        }
3077
3078        private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
3079            final MethodType type = invocation.getInvocation().type();
3080            return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
3081        }
3082    }
3083
3084}
3085