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