Global.java revision 1626:d99fa86747ee
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    /*
1061     * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
1062     */
1063    private ScriptFunction typeErrorThrower;
1064
1065    // Used to store the last RegExp result to support deprecated RegExp constructor properties
1066    private RegExpResult lastRegExpResult;
1067
1068    private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
1069    private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
1070    private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
1071    private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
1072    private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
1073    private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
1074    private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
1075    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
1076
1077    // initialized by nasgen
1078    private static PropertyMap $nasgenmap$;
1079
1080    // context to which this global belongs to
1081    private final Context context;
1082
1083    // current ScriptContext to use - can be null.
1084    private ThreadLocal<ScriptContext> scontext;
1085    // current ScriptEngine associated - can be null.
1086    private ScriptEngine engine;
1087
1088    // ES6 global lexical scope.
1089    private final LexicalScope lexicalScope;
1090
1091    // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
1092    private SwitchPoint lexicalScopeSwitchPoint;
1093
1094    /**
1095     * Set the current script context
1096     * @param ctxt script context
1097     */
1098    public void setScriptContext(final ScriptContext ctxt) {
1099        assert scontext != null;
1100        scontext.set(ctxt);
1101    }
1102
1103    /**
1104     * Get the current script context
1105     * @return current script context
1106     */
1107    public ScriptContext getScriptContext() {
1108        assert scontext != null;
1109        return scontext.get();
1110    }
1111
1112    private ScriptContext currentContext() {
1113        final ScriptContext sc = scontext != null? scontext.get() : null;
1114        return (sc != null)? sc : (engine != null? engine.getContext() : null);
1115    }
1116
1117    @Override
1118    protected Context getContext() {
1119        return context;
1120    }
1121
1122    @Override
1123    protected boolean useDualFields() {
1124        return context.useDualFields();
1125    }
1126
1127    // performs initialization checks for Global constructor and returns the
1128    // PropertyMap, if everything is fine.
1129    private static PropertyMap checkAndGetMap(final Context context) {
1130        // security check first
1131        final SecurityManager sm = System.getSecurityManager();
1132        if (sm != null) {
1133            sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
1134        }
1135
1136        Objects.requireNonNull(context);
1137
1138        return $nasgenmap$;
1139    }
1140
1141    /**
1142     * Constructor
1143     *
1144     * @param context the context
1145     */
1146    public Global(final Context context) {
1147        super(checkAndGetMap(context));
1148        this.context = context;
1149        this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
1150    }
1151
1152    /**
1153     * Script access to "current" Global instance
1154     *
1155     * @return the global singleton
1156     */
1157    public static Global instance() {
1158        return Objects.requireNonNull(Context.getGlobal());
1159    }
1160
1161    private static Global instanceFrom(final Object self) {
1162        return self instanceof Global? (Global)self : instance();
1163    }
1164
1165    /**
1166     * Check if we have a Global instance
1167     * @return true if one exists
1168     */
1169    public static boolean hasInstance() {
1170        return Context.getGlobal() != null;
1171    }
1172
1173    /**
1174     * Script access to {@link ScriptEnvironment}
1175     *
1176     * @return the script environment
1177     */
1178    static ScriptEnvironment getEnv() {
1179        return instance().getContext().getEnv();
1180    }
1181
1182    /**
1183     * Script access to {@link Context}
1184     *
1185     * @return the context
1186     */
1187    static Context getThisContext() {
1188        return instance().getContext();
1189    }
1190
1191    // Runtime interface to Global
1192
1193    /**
1194     * Is there a class filter in the current Context?
1195     * @return class filter
1196     */
1197    public ClassFilter getClassFilter() {
1198        return context.getClassFilter();
1199    }
1200
1201    /**
1202     * Is this global of the given Context?
1203     * @param ctxt the context
1204     * @return true if this global belongs to the given Context
1205     */
1206    public boolean isOfContext(final Context ctxt) {
1207        return this.context == ctxt;
1208    }
1209
1210    /**
1211     * Does this global belong to a strict Context?
1212     * @return true if this global belongs to a strict Context
1213     */
1214    public boolean isStrictContext() {
1215        return context.getEnv()._strict;
1216    }
1217
1218    /**
1219     * Initialize standard builtin objects like "Object", "Array", "Function" etc.
1220     * as well as our extension builtin objects like "Java", "JSAdapter" as properties
1221     * of the global scope object.
1222     *
1223     * @param eng ScriptEngine to initialize
1224     */
1225    public void initBuiltinObjects(final ScriptEngine eng) {
1226        if (this.builtinObject != null) {
1227            // already initialized, just return
1228            return;
1229        }
1230
1231        TO_STRING = new InvokeByName("toString", ScriptObject.class);
1232        VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
1233
1234        this.engine = eng;
1235        if (this.engine != null) {
1236            this.scontext = new ThreadLocal<>();
1237        }
1238        init(eng);
1239    }
1240
1241    /**
1242     * Wrap a Java object as corresponding script object
1243     *
1244     * @param obj object to wrap
1245     * @return    wrapped object
1246     */
1247    public Object wrapAsObject(final Object obj) {
1248        if (obj instanceof Boolean) {
1249            return new NativeBoolean((Boolean)obj, this);
1250        } else if (obj instanceof Number) {
1251            return new NativeNumber(((Number)obj).doubleValue(), this);
1252        } else if (isString(obj)) {
1253            return new NativeString((CharSequence)obj, this);
1254        } else if (obj instanceof Object[]) { // extension
1255            return new NativeArray(ArrayData.allocate((Object[])obj), this);
1256        } else if (obj instanceof double[]) { // extension
1257            return new NativeArray(ArrayData.allocate((double[])obj), this);
1258        } else if (obj instanceof int[]) {
1259            return new NativeArray(ArrayData.allocate((int[]) obj), this);
1260        } else if (obj instanceof ArrayData) {
1261            return new NativeArray((ArrayData) obj, this);
1262        } else if (obj instanceof Symbol) {
1263            return new NativeSymbol((Symbol) obj, this);
1264        } else {
1265            // FIXME: more special cases? Map? List?
1266            return obj;
1267        }
1268    }
1269
1270    /**
1271     * Lookup helper for JS primitive types
1272     *
1273     * @param request the link request for the dynamic call site.
1274     * @param self     self reference
1275     *
1276     * @return guarded invocation
1277     */
1278    public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
1279        if (isString(self)) {
1280            return NativeString.lookupPrimitive(request, self);
1281        } else if (self instanceof Number) {
1282            return NativeNumber.lookupPrimitive(request, self);
1283        } else if (self instanceof Boolean) {
1284            return NativeBoolean.lookupPrimitive(request, self);
1285        } else if (self instanceof Symbol) {
1286            return NativeSymbol.lookupPrimitive(request, self);
1287        }
1288        throw new IllegalArgumentException("Unsupported primitive: " + self);
1289    }
1290
1291    /**
1292     * Returns a method handle that creates a wrapper object for a JS primitive value.
1293     *
1294     * @param self receiver object
1295     * @return method handle to create wrapper objects for primitive receiver
1296     */
1297    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
1298        if (isString(self)) {
1299            return NativeString.WRAPFILTER;
1300        } else if (self instanceof Number) {
1301            return NativeNumber.WRAPFILTER;
1302        } else if (self instanceof Boolean) {
1303            return NativeBoolean.WRAPFILTER;
1304        }
1305        throw new IllegalArgumentException("Unsupported primitive: " + self);
1306    }
1307
1308
1309    /**
1310     * Create a new empty script object
1311     *
1312     * @return the new ScriptObject
1313     */
1314    public ScriptObject newObject() {
1315        return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
1316    }
1317
1318    /**
1319     * Default value of given type
1320     *
1321     * @param sobj     script object
1322     * @param typeHint type hint
1323     *
1324     * @return default value
1325     */
1326    public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
1327        // When the [[DefaultValue]] internal method of O is called with no hint,
1328        // then it behaves as if the hint were Number, unless O is a Date object
1329        // in which case it behaves as if the hint were String.
1330        Class<?> hint = typeHint;
1331        if (hint == null) {
1332            hint = Number.class;
1333        }
1334
1335        try {
1336            if (hint == String.class) {
1337
1338                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1339
1340                if (Bootstrap.isCallable(toString)) {
1341                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1342                    if (JSType.isPrimitive(value)) {
1343                        return value;
1344                    }
1345                }
1346
1347                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1348                if (Bootstrap.isCallable(valueOf)) {
1349                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1350                    if (JSType.isPrimitive(value)) {
1351                        return value;
1352                    }
1353                }
1354                throw typeError(this, "cannot.get.default.string");
1355            }
1356
1357            if (hint == Number.class) {
1358                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1359                if (Bootstrap.isCallable(valueOf)) {
1360                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1361                    if (JSType.isPrimitive(value)) {
1362                        return value;
1363                    }
1364                }
1365
1366                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1367                if (Bootstrap.isCallable(toString)) {
1368                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1369                    if (JSType.isPrimitive(value)) {
1370                        return value;
1371                    }
1372                }
1373
1374                throw typeError(this, "cannot.get.default.number");
1375            }
1376        } catch (final RuntimeException | Error e) {
1377            throw e;
1378        } catch (final Throwable t) {
1379            throw new RuntimeException(t);
1380        }
1381
1382        return UNDEFINED;
1383    }
1384
1385    /**
1386     * Is the given ScriptObject an ECMAScript Error object?
1387     *
1388     * @param sobj the object being checked
1389     * @return true if sobj is an Error object
1390     */
1391    public boolean isError(final ScriptObject sobj) {
1392        final ScriptObject errorProto = getErrorPrototype();
1393        ScriptObject proto = sobj.getProto();
1394        while (proto != null) {
1395            if (proto == errorProto) {
1396                return true;
1397            }
1398            proto = proto.getProto();
1399        }
1400        return false;
1401    }
1402
1403    /**
1404     * Create a new ECMAScript Error object.
1405     *
1406     * @param msg error message
1407     * @return newly created Error object
1408     */
1409    public ScriptObject newError(final String msg) {
1410        return new NativeError(msg, this);
1411    }
1412
1413    /**
1414     * Create a new ECMAScript EvalError object.
1415     *
1416     * @param msg error message
1417     * @return newly created EvalError object
1418     */
1419    public ScriptObject newEvalError(final String msg) {
1420        return new NativeEvalError(msg, this);
1421    }
1422
1423    /**
1424     * Create a new ECMAScript RangeError object.
1425     *
1426     * @param msg error message
1427     * @return newly created RangeError object
1428     */
1429    public ScriptObject newRangeError(final String msg) {
1430        return new NativeRangeError(msg, this);
1431    }
1432
1433    /**
1434     * Create a new ECMAScript ReferenceError object.
1435     *
1436     * @param msg error message
1437     * @return newly created ReferenceError object
1438     */
1439    public ScriptObject newReferenceError(final String msg) {
1440        return new NativeReferenceError(msg, this);
1441    }
1442
1443    /**
1444     * Create a new ECMAScript SyntaxError object.
1445     *
1446     * @param msg error message
1447     * @return newly created SyntaxError object
1448     */
1449    public ScriptObject newSyntaxError(final String msg) {
1450        return new NativeSyntaxError(msg, this);
1451    }
1452
1453    /**
1454     * Create a new ECMAScript TypeError object.
1455     *
1456     * @param msg error message
1457     * @return newly created TypeError object
1458     */
1459    public ScriptObject newTypeError(final String msg) {
1460        return new NativeTypeError(msg, this);
1461    }
1462
1463    /**
1464     * Create a new ECMAScript URIError object.
1465     *
1466     * @param msg error message
1467     * @return newly created URIError object
1468     */
1469    public ScriptObject newURIError(final String msg) {
1470        return new NativeURIError(msg, this);
1471    }
1472
1473    /**
1474     * Create a new ECMAScript GenericDescriptor object.
1475     *
1476     * @param configurable is the property configurable?
1477     * @param enumerable is the property enumerable?
1478     * @return newly created GenericDescriptor object
1479     */
1480    public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1481        return new GenericPropertyDescriptor(configurable, enumerable, this);
1482    }
1483
1484    /**
1485     * Create a new ECMAScript DatePropertyDescriptor object.
1486     *
1487     * @param value of the data property
1488     * @param configurable is the property configurable?
1489     * @param enumerable is the property enumerable?
1490     * @param writable is the property writable?
1491     * @return newly created DataPropertyDescriptor object
1492     */
1493    public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1494        return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1495    }
1496
1497    /**
1498     * Create a new ECMAScript AccessorPropertyDescriptor object.
1499     *
1500     * @param get getter function of the user accessor property
1501     * @param set setter function of the user accessor property
1502     * @param configurable is the property configurable?
1503     * @param enumerable is the property enumerable?
1504     * @return newly created AccessorPropertyDescriptor object
1505     */
1506    public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1507        final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1508
1509        if (get == null) {
1510            desc.delete(PropertyDescriptor.GET, false);
1511        }
1512
1513        if (set == null) {
1514            desc.delete(PropertyDescriptor.SET, false);
1515        }
1516
1517        return desc;
1518    }
1519
1520    private <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1521        final T obj = map.get(key);
1522        if (obj != null) {
1523            return obj;
1524        }
1525
1526        final Global oldGlobal = Context.getGlobal();
1527        final boolean differentGlobal = oldGlobal != this;
1528        try {
1529            if (differentGlobal) {
1530                Context.setGlobal(this);
1531            }
1532            final T newObj = creator.call();
1533            final T existingObj = map.putIfAbsent(key, newObj);
1534            return existingObj != null ? existingObj : newObj;
1535        } catch (final Exception exp) {
1536            throw new RuntimeException(exp);
1537        } finally {
1538            if (differentGlobal) {
1539                Context.setGlobal(oldGlobal);
1540            }
1541        }
1542    }
1543
1544    private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1545
1546
1547    /**
1548     * Get cached InvokeByName object for the given key
1549     * @param key key to be associated with InvokeByName object
1550     * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1551     * @return InvokeByName object associated with the key.
1552     */
1553    public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1554        return getLazilyCreatedValue(key, creator, namedInvokers);
1555    }
1556
1557    private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1558
1559    /**
1560     * Get cached dynamic method handle for the given key
1561     * @param key key to be associated with dynamic method handle
1562     * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1563     * @return dynamic method handle associated with the key.
1564     */
1565    public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1566        return getLazilyCreatedValue(key, creator, dynamicInvokers);
1567    }
1568
1569    /**
1570     * Hook to search missing variables in ScriptContext if available
1571     * @param self used to detect if scope call or not (this function is 'strict')
1572     * @param name name of the variable missing
1573     * @return value of the missing variable or undefined (or TypeError for scope search)
1574     */
1575    public static Object __noSuchProperty__(final Object self, final Object name) {
1576        final Global global = Global.instance();
1577        final ScriptContext sctxt = global.currentContext();
1578        final String nameStr = name.toString();
1579
1580        if (sctxt != null) {
1581            final int scope = sctxt.getAttributesScope(nameStr);
1582            if (scope != -1) {
1583                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1584            }
1585        }
1586
1587        switch (nameStr) {
1588        case "context":
1589            return sctxt;
1590        case "engine":
1591            return global.engine;
1592        default:
1593            break;
1594        }
1595
1596        if (self == UNDEFINED) {
1597            // scope access and so throw ReferenceError
1598            throw referenceError(global, "not.defined", nameStr);
1599        }
1600
1601        return UNDEFINED;
1602    }
1603
1604    /**
1605     * This is the eval used when 'indirect' eval call is made.
1606     *
1607     * var global = this;
1608     * global.eval("print('hello')");
1609     *
1610     * @param self  eval scope
1611     * @param str   eval string
1612     *
1613     * @return the result of eval
1614     */
1615    public static Object eval(final Object self, final Object str) {
1616        return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false);
1617    }
1618
1619    /**
1620     * Direct eval
1621     *
1622     * @param self     The scope of eval passed as 'self'
1623     * @param str      Evaluated code
1624     * @param callThis "this" to be passed to the evaluated code
1625     * @param location location of the eval call
1626     * @param strict   is eval called from a strict mode code?
1627     *
1628     * @return the return value of the eval
1629     *
1630     * This is directly invoked from generated when eval(code) is called in user code
1631     */
1632    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1633        if (!isString(str)) {
1634            return str;
1635        }
1636        final Global global = Global.instanceFrom(self);
1637        final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1638
1639        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1640    }
1641
1642    /**
1643     * Global print implementation - Nashorn extension
1644     *
1645     * @param self    scope
1646     * @param objects arguments to print
1647     *
1648     * @return result of print (undefined)
1649     */
1650    public static Object print(final Object self, final Object... objects) {
1651        return Global.instanceFrom(self).printImpl(false, objects);
1652    }
1653
1654    /**
1655     * Global println implementation - Nashorn extension
1656     *
1657     * @param self    scope
1658     * @param objects arguments to print
1659     *
1660     * @return result of println (undefined)
1661     */
1662    public static Object println(final Object self, final Object... objects) {
1663        return Global.instanceFrom(self).printImpl(true, objects);
1664    }
1665
1666    /**
1667     * Global load implementation - Nashorn extension.
1668     *
1669     * <p>
1670     * load builtin loads the given script. Script source can be a URL or a File
1671     * or a script object with name and script properties. Evaluated code gets
1672     * global object "this" and uses global object as scope for evaluation.
1673     * </p>
1674     * <p>
1675     * If self is undefined or null or global, then global object is used
1676     * as scope as well as "this" for the evaluated code. If self is any other
1677     * object, then it is indirect load call. With indirect load call, the
1678     * properties of scope are available to evaluated script as variables. Also,
1679     * global scope properties are accessible. Any var, function definition in
1680     * evaluated script goes into an object that is not accessible to user scripts.
1681     * </p>
1682     * Thus the indirect load call is equivalent to the following:
1683     * <pre>
1684     * <code>
1685     * (function (scope, source) {
1686     *    with(scope) {
1687     *        eval(&lt;script_from_source&gt;);
1688     *    }
1689     * })(self, source);
1690     * </code>
1691     * </pre>
1692     *
1693     * @param self    scope to use for the script evaluation
1694     * @param source  script source
1695     *
1696     * @return result of load (may be undefined)
1697     *
1698     * @throws IOException if source could not be read
1699     */
1700    public static Object load(final Object self, final Object source) throws IOException {
1701        final Global global = Global.instanceFrom(self);
1702        return global.getContext().load(self, source);
1703    }
1704
1705    /**
1706     * Global loadWithNewGlobal implementation - Nashorn extension.
1707     *
1708     * loadWithNewGlobal builtin loads the given script from a URL or a File
1709     * or a script object with name and script properties. Evaluated code gets
1710     * new global object "this" and uses that new global object as scope for evaluation.
1711     *
1712     * @param self self This value is ignored by this function
1713     * @param args optional arguments to be passed to the loaded script
1714     *
1715     * @return result of load (may be undefined)
1716     *
1717     * @throws IOException if source could not be read
1718     */
1719    public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1720        final Global global = Global.instanceFrom(self);
1721        final int length = args.length;
1722        final boolean hasArgs = 0 < length;
1723        final Object from = hasArgs ? args[0] : UNDEFINED;
1724        final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1725
1726        return global.getContext().loadWithNewGlobal(from, arguments);
1727    }
1728
1729    /**
1730     * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1731     *
1732     * @param self  self reference
1733     * @param code  exit code
1734     *
1735     * @return undefined (will never be reached)
1736     */
1737    public static Object exit(final Object self, final Object code) {
1738        System.exit(JSType.toInt32(code));
1739        return UNDEFINED;
1740    }
1741
1742    // builtin prototype accessors
1743
1744    /**
1745     * Get the builtin Object prototype.
1746     * @return the Object prototype.
1747     */
1748    public ScriptObject getObjectPrototype() {
1749        return ScriptFunction.getPrototype(builtinObject);
1750    }
1751
1752    /**
1753     * Get the builtin Function prototype.
1754     * @return the Function prototype.
1755     */
1756    public ScriptObject getFunctionPrototype() {
1757        return ScriptFunction.getPrototype(builtinFunction);
1758    }
1759
1760    /**
1761     * Get the builtin Array prototype.
1762     * @return the Array prototype
1763     */
1764    public ScriptObject getArrayPrototype() {
1765        return ScriptFunction.getPrototype(builtinArray);
1766    }
1767
1768    ScriptObject getBooleanPrototype() {
1769        return ScriptFunction.getPrototype(builtinBoolean);
1770    }
1771
1772    ScriptObject getNumberPrototype() {
1773        return ScriptFunction.getPrototype(builtinNumber);
1774    }
1775
1776    ScriptObject getDatePrototype() {
1777        return ScriptFunction.getPrototype(getBuiltinDate());
1778    }
1779
1780    ScriptObject getRegExpPrototype() {
1781        return ScriptFunction.getPrototype(getBuiltinRegExp());
1782    }
1783
1784    ScriptObject getStringPrototype() {
1785        return ScriptFunction.getPrototype(builtinString);
1786    }
1787
1788    ScriptObject getErrorPrototype() {
1789        return ScriptFunction.getPrototype(builtinError);
1790    }
1791
1792    ScriptObject getEvalErrorPrototype() {
1793        return ScriptFunction.getPrototype(getBuiltinEvalError());
1794    }
1795
1796    ScriptObject getRangeErrorPrototype() {
1797        return ScriptFunction.getPrototype(getBuiltinRangeError());
1798    }
1799
1800    ScriptObject getReferenceErrorPrototype() {
1801        return ScriptFunction.getPrototype(builtinReferenceError);
1802    }
1803
1804    ScriptObject getSyntaxErrorPrototype() {
1805        return ScriptFunction.getPrototype(builtinSyntaxError);
1806    }
1807
1808    ScriptObject getTypeErrorPrototype() {
1809        return ScriptFunction.getPrototype(builtinTypeError);
1810    }
1811
1812    ScriptObject getURIErrorPrototype() {
1813        return ScriptFunction.getPrototype(getBuiltinURIError());
1814    }
1815
1816    ScriptObject getJavaImporterPrototype() {
1817        return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1818    }
1819
1820    ScriptObject getJSAdapterPrototype() {
1821        return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1822    }
1823
1824    ScriptObject getSymbolPrototype() {
1825        return ScriptFunction.getPrototype(getBuiltinSymbol());
1826    }
1827
1828    ScriptObject getMapPrototype() {
1829        return ScriptFunction.getPrototype(getBuiltinMap());
1830    }
1831
1832    ScriptObject getWeakMapPrototype() {
1833        return ScriptFunction.getPrototype(getBuiltinWeakMap());
1834    }
1835
1836    ScriptObject getSetPrototype() {
1837        return ScriptFunction.getPrototype(getBuiltinSet());
1838    }
1839
1840    ScriptObject getWeakSetPrototype() {
1841        return ScriptFunction.getPrototype(getBuiltinWeakSet());
1842    }
1843
1844    ScriptObject getIteratorPrototype() {
1845        if (builtinIteratorPrototype == null) {
1846            builtinIteratorPrototype = initPrototype("AbstractIterator", getObjectPrototype());
1847        }
1848        return builtinIteratorPrototype;
1849    }
1850
1851    ScriptObject getMapIteratorPrototype() {
1852        if (builtinMapIteratorPrototype == null) {
1853            builtinMapIteratorPrototype = initPrototype("MapIterator", getIteratorPrototype());
1854        }
1855        return builtinMapIteratorPrototype;
1856    }
1857
1858    ScriptObject getSetIteratorPrototype() {
1859        if (builtinSetIteratorPrototype == null) {
1860            builtinSetIteratorPrototype = initPrototype("SetIterator", getIteratorPrototype());
1861        }
1862        return builtinSetIteratorPrototype;
1863    }
1864
1865    ScriptObject getArrayIteratorPrototype() {
1866        if (builtinArrayIteratorPrototype == null) {
1867            builtinArrayIteratorPrototype = initPrototype("ArrayIterator", getIteratorPrototype());
1868        }
1869        return builtinArrayIteratorPrototype;
1870    }
1871
1872    ScriptObject getStringIteratorPrototype() {
1873        if (builtinStringIteratorPrototype == null) {
1874            builtinStringIteratorPrototype = initPrototype("StringIterator", getIteratorPrototype());
1875        }
1876        return builtinStringIteratorPrototype;
1877    }
1878
1879    private synchronized ScriptFunction getBuiltinArrayBuffer() {
1880        if (this.builtinArrayBuffer == null) {
1881            this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1882        }
1883        return this.builtinArrayBuffer;
1884    }
1885
1886    ScriptObject getArrayBufferPrototype() {
1887        return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1888    }
1889
1890    private synchronized ScriptFunction getBuiltinDataView() {
1891        if (this.builtinDataView == null) {
1892            this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1893        }
1894        return this.builtinDataView;
1895    }
1896
1897    ScriptObject getDataViewPrototype() {
1898        return ScriptFunction.getPrototype(getBuiltinDataView());
1899    }
1900
1901    private synchronized ScriptFunction getBuiltinInt8Array() {
1902        if (this.builtinInt8Array == null) {
1903            this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1904        }
1905        return this.builtinInt8Array;
1906    }
1907
1908    ScriptObject getInt8ArrayPrototype() {
1909        return ScriptFunction.getPrototype(getBuiltinInt8Array());
1910    }
1911
1912    private synchronized ScriptFunction getBuiltinUint8Array() {
1913        if (this.builtinUint8Array == null) {
1914            this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1915        }
1916        return this.builtinUint8Array;
1917    }
1918
1919    ScriptObject getUint8ArrayPrototype() {
1920        return ScriptFunction.getPrototype(getBuiltinUint8Array());
1921    }
1922
1923    private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1924        if (this.builtinUint8ClampedArray == null) {
1925            this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1926        }
1927        return this.builtinUint8ClampedArray;
1928    }
1929
1930    ScriptObject getUint8ClampedArrayPrototype() {
1931        return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1932    }
1933
1934    private synchronized ScriptFunction getBuiltinInt16Array() {
1935        if (this.builtinInt16Array == null) {
1936            this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1937        }
1938        return this.builtinInt16Array;
1939    }
1940
1941    ScriptObject getInt16ArrayPrototype() {
1942        return ScriptFunction.getPrototype(getBuiltinInt16Array());
1943    }
1944
1945    private synchronized ScriptFunction getBuiltinUint16Array() {
1946        if (this.builtinUint16Array == null) {
1947            this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1948        }
1949        return this.builtinUint16Array;
1950    }
1951
1952    ScriptObject getUint16ArrayPrototype() {
1953        return ScriptFunction.getPrototype(getBuiltinUint16Array());
1954    }
1955
1956    private synchronized ScriptFunction getBuiltinInt32Array() {
1957        if (this.builtinInt32Array == null) {
1958            this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1959        }
1960        return this.builtinInt32Array;
1961    }
1962
1963    ScriptObject getInt32ArrayPrototype() {
1964        return ScriptFunction.getPrototype(getBuiltinInt32Array());
1965    }
1966
1967    private synchronized ScriptFunction getBuiltinUint32Array() {
1968        if (this.builtinUint32Array == null) {
1969            this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1970        }
1971        return this.builtinUint32Array;
1972    }
1973
1974    ScriptObject getUint32ArrayPrototype() {
1975        return ScriptFunction.getPrototype(getBuiltinUint32Array());
1976    }
1977
1978    private synchronized ScriptFunction getBuiltinFloat32Array() {
1979        if (this.builtinFloat32Array == null) {
1980            this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1981        }
1982        return this.builtinFloat32Array;
1983    }
1984
1985    ScriptObject getFloat32ArrayPrototype() {
1986        return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1987    }
1988
1989    private synchronized ScriptFunction getBuiltinFloat64Array() {
1990        if (this.builtinFloat64Array == null) {
1991            this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1992        }
1993        return this.builtinFloat64Array;
1994    }
1995
1996    ScriptObject getFloat64ArrayPrototype() {
1997        return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1998    }
1999
2000    /**
2001     * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties.
2002     *
2003     * @return the TypeError throwing function
2004     */
2005    public ScriptFunction getTypeErrorThrower() {
2006        return typeErrorThrower;
2007    }
2008
2009    private synchronized ScriptFunction getBuiltinDate() {
2010        if (this.builtinDate == null) {
2011            this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
2012            final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
2013            // initialize default date
2014            this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
2015        }
2016        return this.builtinDate;
2017    }
2018
2019    private synchronized ScriptFunction getBuiltinEvalError() {
2020        if (this.builtinEvalError == null) {
2021            this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
2022        }
2023        return this.builtinEvalError;
2024    }
2025
2026    private ScriptFunction getBuiltinFunction() {
2027        return builtinFunction;
2028    }
2029
2030    /**
2031     * Get the switchpoint used to check property changes for Function.prototype.apply
2032     * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
2033     */
2034    public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
2035        return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
2036    }
2037
2038    private static boolean isBuiltinFunctionProperty(final String name) {
2039        final Global instance = Global.instance();
2040        final ScriptFunction builtinFunction = instance.getBuiltinFunction();
2041        if (builtinFunction == null) {
2042            return false; //conservative for compile-only mode
2043        }
2044        final boolean isBuiltinFunction = instance.function == builtinFunction;
2045        return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
2046    }
2047
2048    /**
2049     * Check if the Function.prototype.apply has not been replaced
2050     * @return true if Function.prototype.apply has been replaced
2051     */
2052    public static boolean isBuiltinFunctionPrototypeApply() {
2053        return isBuiltinFunctionProperty("apply");
2054    }
2055
2056    /**
2057     * Check if the Function.prototype.apply has not been replaced
2058     * @return true if Function.prototype.call has been replaced
2059     */
2060    public static boolean isBuiltinFunctionPrototypeCall() {
2061        return isBuiltinFunctionProperty("call");
2062    }
2063
2064    private synchronized ScriptFunction getBuiltinJSAdapter() {
2065        if (this.builtinJSAdapter == null) {
2066            this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
2067        }
2068        return builtinJSAdapter;
2069    }
2070
2071    private synchronized ScriptObject getBuiltinJSON() {
2072        if (this.builtinJSON == null) {
2073            this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
2074        }
2075        return this.builtinJSON;
2076    }
2077
2078    private synchronized ScriptFunction getBuiltinJavaImporter() {
2079        if (this.builtinJavaImporter == null) {
2080            this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
2081        }
2082        return this.builtinJavaImporter;
2083    }
2084
2085    private synchronized ScriptObject getBuiltinJavaApi() {
2086        if (this.builtinJavaApi == null) {
2087            this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
2088        }
2089        return this.builtinJavaApi;
2090    }
2091
2092    private synchronized ScriptFunction getBuiltinRangeError() {
2093        if (this.builtinRangeError == null) {
2094            this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2095        }
2096        return builtinRangeError;
2097    }
2098
2099    private synchronized ScriptFunction getBuiltinRegExp() {
2100        if (this.builtinRegExp == null) {
2101            this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2102            final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2103            // initialize default regexp object
2104            this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2105            // RegExp.prototype should behave like a RegExp object. So copy the
2106            // properties.
2107            regExpProto.addBoundProperties(DEFAULT_REGEXP);
2108        }
2109        return builtinRegExp;
2110    }
2111
2112    private synchronized ScriptFunction getBuiltinURIError() {
2113        if (this.builtinURIError == null) {
2114            this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2115        }
2116        return this.builtinURIError;
2117    }
2118
2119    private synchronized ScriptFunction getBuiltinSymbol() {
2120        if (this.builtinSymbol == null) {
2121            this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class);
2122        }
2123        return this.builtinSymbol;
2124    }
2125
2126    private synchronized ScriptFunction getBuiltinMap() {
2127        if (this.builtinMap == null) {
2128            this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class);
2129        }
2130        return this.builtinMap;
2131    }
2132
2133    private synchronized ScriptFunction getBuiltinWeakMap() {
2134        if (this.builtinWeakMap == null) {
2135            this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class);
2136        }
2137        return this.builtinWeakMap;
2138    }
2139
2140    private synchronized ScriptFunction getBuiltinSet() {
2141        if (this.builtinSet == null) {
2142            this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class);
2143        }
2144        return this.builtinSet;
2145    }
2146
2147    private synchronized ScriptFunction getBuiltinWeakSet() {
2148        if (this.builtinWeakSet == null) {
2149            this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class);
2150        }
2151        return this.builtinWeakSet;
2152    }
2153
2154    @Override
2155    public String getClassName() {
2156        return "global";
2157    }
2158
2159    /**
2160     * Copy function used to clone NativeRegExp objects.
2161     *
2162     * @param regexp a NativeRegExp to clone
2163     *
2164     * @return copy of the given regexp object
2165     */
2166    public static Object regExpCopy(final Object regexp) {
2167        return new NativeRegExp((NativeRegExp)regexp);
2168    }
2169
2170    /**
2171     * Convert given object to NativeRegExp type.
2172     *
2173     * @param obj object to be converted
2174     * @return NativeRegExp instance
2175     */
2176    public static NativeRegExp toRegExp(final Object obj) {
2177        if (obj instanceof NativeRegExp) {
2178            return (NativeRegExp)obj;
2179        }
2180        return new NativeRegExp(JSType.toString(obj));
2181    }
2182
2183    /**
2184     * ECMA 9.9 ToObject implementation
2185     *
2186     * @param obj  an item for which to run ToObject
2187     * @return ToObject version of given item
2188     */
2189    public static Object toObject(final Object obj) {
2190        if (obj == null || obj == UNDEFINED) {
2191            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2192        }
2193
2194        if (obj instanceof ScriptObject) {
2195            return obj;
2196        }
2197
2198        return instance().wrapAsObject(obj);
2199    }
2200
2201    /**
2202     * Allocate a new object array.
2203     *
2204     * @param initial object values.
2205     * @return the new array
2206     */
2207    public static NativeArray allocate(final Object[] initial) {
2208        ArrayData arrayData = ArrayData.allocate(initial);
2209
2210        for (int index = 0; index < initial.length; index++) {
2211            final Object value = initial[index];
2212
2213            if (value == ScriptRuntime.EMPTY) {
2214                arrayData = arrayData.delete(index);
2215            }
2216        }
2217
2218        return new NativeArray(arrayData);
2219    }
2220
2221    /**
2222     * Allocate a new number array.
2223     *
2224     * @param initial number values.
2225     * @return the new array
2226     */
2227    public static NativeArray allocate(final double[] initial) {
2228        return new NativeArray(ArrayData.allocate(initial));
2229    }
2230
2231    /**
2232     * Allocate a new integer array.
2233     *
2234     * @param initial number values.
2235     * @return the new array
2236     */
2237    public static NativeArray allocate(final int[] initial) {
2238        return new NativeArray(ArrayData.allocate(initial));
2239    }
2240
2241    /**
2242     * Allocate a new object array for arguments.
2243     *
2244     * @param arguments initial arguments passed.
2245     * @param callee reference to the function that uses arguments object
2246     * @param numParams actual number of declared parameters
2247     *
2248     * @return the new array
2249     */
2250    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2251        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2252    }
2253
2254    /**
2255     * Called from generated to check if given function is the builtin 'eval'. If
2256     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2257     *
2258     * @param  fn function object that is checked
2259     * @return true if fn is the builtin eval
2260     */
2261    public static boolean isEval(final Object fn) {
2262        return fn == Global.instance().builtinEval;
2263    }
2264
2265    /**
2266     * Called from generated to replace a location property placeholder with the actual location property value.
2267     *
2268     * @param  placeholder the value tested for being a placeholder for a location property
2269     * @param  locationProperty the actual value for the location property
2270     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2271     */
2272    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2273        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2274    }
2275
2276    /**
2277     * Called from runtime internals to check if the passed value is a location property placeholder.
2278     * @param  placeholder the value tested for being a placeholder for a location property
2279     * @return true if the value is a placeholder, false otherwise.
2280     */
2281    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2282        return placeholder == LAZY_SENTINEL;
2283    }
2284
2285    /**
2286     * Create a new RegExp object.
2287     *
2288     * @param expression Regular expression.
2289     * @param options    Search options.
2290     *
2291     * @return New RegExp object.
2292     */
2293    public static Object newRegExp(final String expression, final String options) {
2294        if (options == null) {
2295            return new NativeRegExp(expression);
2296        }
2297        return new NativeRegExp(expression, options);
2298    }
2299
2300    /**
2301     * Get the object prototype
2302     *
2303     * @return the object prototype
2304     */
2305    public static ScriptObject objectPrototype() {
2306        return Global.instance().getObjectPrototype();
2307    }
2308
2309    /**
2310     * Create a new empty object instance.
2311     *
2312     * @return New empty object.
2313     */
2314    public static ScriptObject newEmptyInstance() {
2315        return Global.instance().newObject();
2316    }
2317
2318    /**
2319     * Check if a given object is a ScriptObject, raises an exception if this is
2320     * not the case
2321     *
2322     * @param obj and object to check
2323     * @return the script object
2324     */
2325    public static ScriptObject checkObject(final Object obj) {
2326        if (!(obj instanceof ScriptObject)) {
2327            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2328        }
2329        return (ScriptObject)obj;
2330    }
2331
2332    /**
2333     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2334     * if this object is null or undefined.
2335     *
2336     * @param obj an object to check
2337     */
2338    public static void checkObjectCoercible(final Object obj) {
2339        if (obj == null || obj == UNDEFINED) {
2340            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2341        }
2342    }
2343
2344    /**
2345     * Return the ES6 global scope for lexically declared bindings.
2346     * @return the ES6 lexical global scope.
2347     */
2348    public final ScriptObject getLexicalScope() {
2349        assert context.getEnv()._es6;
2350        return lexicalScope;
2351    }
2352
2353    @Override
2354    public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2355        PropertyMap ownMap = getMap();
2356        LexicalScope lexScope = null;
2357        PropertyMap lexicalMap = null;
2358        boolean hasLexicalDefinitions = false;
2359
2360        if (context.getEnv()._es6) {
2361            lexScope = (LexicalScope) getLexicalScope();
2362            lexicalMap = lexScope.getMap();
2363
2364            for (final jdk.nashorn.internal.runtime.Property property : properties) {
2365                if (property.isLexicalBinding()) {
2366                    hasLexicalDefinitions = true;
2367                }
2368                // ES6 15.1.8 steps 6. and 7.
2369                final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2370                if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2371                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2372                }
2373                final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2374                if (lexicalProperty != null && !property.isConfigurable()) {
2375                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString());
2376                }
2377            }
2378        }
2379
2380        final boolean extensible = isExtensible();
2381        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2382            if (property.isLexicalBinding()) {
2383                assert lexScope != null;
2384                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
2385
2386                if (ownMap.findProperty(property.getKey()) != null) {
2387                    // If property exists in the global object invalidate any global constant call sites.
2388                    invalidateGlobalConstant(property.getKey());
2389                }
2390            } else {
2391                ownMap = addBoundProperty(ownMap, source, property, extensible);
2392            }
2393        }
2394
2395        setMap(ownMap);
2396
2397        if (hasLexicalDefinitions) {
2398            assert lexScope != null;
2399            lexScope.setMap(lexicalMap);
2400            invalidateLexicalSwitchPoint();
2401        }
2402    }
2403
2404    @Override
2405    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
2406        final String name = NashornCallSiteDescriptor.getOperand(desc);
2407        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2408
2409        if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2410            if (lexicalScope.hasOwnProperty(name)) {
2411                return lexicalScope.findGetMethod(desc, request, operation);
2412            }
2413        }
2414
2415        final GuardedInvocation invocation =  super.findGetMethod(desc, request, operation);
2416
2417        // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2418        // because those are invalidated per-key in the addBoundProperties method above.
2419        // We therefore check if the invocation does already have a switchpoint and the property is non-inherited,
2420        // assuming this only applies to global constants. If other non-inherited properties will
2421        // start using switchpoints some time in the future we'll have to revisit this.
2422        if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2423            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2424        }
2425
2426        return invocation;
2427    }
2428
2429    @Override
2430    protected FindProperty findProperty(final Object key, final boolean deep, final ScriptObject start) {
2431        if (lexicalScope != null && start != this && start.isScope()) {
2432            final FindProperty find = lexicalScope.findProperty(key, false);
2433            if (find != null) {
2434                return find;
2435            }
2436        }
2437        return super.findProperty(key, deep, start);
2438    }
2439
2440    @Override
2441    public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2442        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2443
2444        if (lexicalScope != null && isScope) {
2445            final String name = NashornCallSiteDescriptor.getOperand(desc);
2446            if (lexicalScope.hasOwnProperty(name)) {
2447                return lexicalScope.findSetMethod(desc, request);
2448            }
2449        }
2450
2451        final GuardedInvocation invocation = super.findSetMethod(desc, request);
2452
2453        if (isScope && context.getEnv()._es6) {
2454            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2455        }
2456
2457        return invocation;
2458    }
2459
2460    /**
2461     * Adds jjs shell interactive mode builtin functions to global scope.
2462     */
2463    public void addShellBuiltins() {
2464        Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT);
2465        addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2466
2467        value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT);
2468        addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2469    }
2470
2471    private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2472        SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2473        if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2474            switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2475        }
2476        return switchPoint;
2477    }
2478
2479    private synchronized void invalidateLexicalSwitchPoint() {
2480        if (lexicalScopeSwitchPoint != null) {
2481            context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2482            SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2483        }
2484    }
2485
2486
2487    @SuppressWarnings("unused")
2488    private static Object lexicalScopeFilter(final Object self) {
2489        if (self instanceof Global) {
2490            return ((Global) self).getLexicalScope();
2491        }
2492        return self;
2493    }
2494
2495    private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2496        final T func = initConstructor(name, clazz);
2497        tagBuiltinProperties(name, func);
2498        return func;
2499    }
2500
2501    private void init(final ScriptEngine eng) {
2502        assert Context.getGlobal() == this : "this global is not set as current";
2503
2504        final ScriptEnvironment env = getContext().getEnv();
2505
2506        // initialize Function and Object constructor
2507        initFunctionAndObject();
2508
2509        // Now fix Global's own proto.
2510        this.setInitialProto(getObjectPrototype());
2511
2512        // initialize global function properties
2513        this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL);
2514
2515        this.parseInt = ScriptFunction.createBuiltin("parseInt",   GlobalFunctions.PARSEINT,
2516                    new Specialization[] {
2517                    new Specialization(GlobalFunctions.PARSEINT_Z),
2518                    new Specialization(GlobalFunctions.PARSEINT_I),
2519                    new Specialization(GlobalFunctions.PARSEINT_OI),
2520                    new Specialization(GlobalFunctions.PARSEINT_O) });
2521        this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2522        this.isNaN = ScriptFunction.createBuiltin("isNaN",   GlobalFunctions.IS_NAN,
2523                   new Specialization[] {
2524                        new Specialization(GlobalFunctions.IS_NAN_I),
2525                        new Specialization(GlobalFunctions.IS_NAN_J),
2526                        new Specialization(GlobalFunctions.IS_NAN_D) });
2527        this.parseFloat         = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
2528        this.isNaN              = ScriptFunction.createBuiltin("isNaN",      GlobalFunctions.IS_NAN);
2529        this.isFinite           = ScriptFunction.createBuiltin("isFinite",   GlobalFunctions.IS_FINITE);
2530        this.encodeURI          = ScriptFunction.createBuiltin("encodeURI",  GlobalFunctions.ENCODE_URI);
2531        this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2532        this.decodeURI          = ScriptFunction.createBuiltin("decodeURI",  GlobalFunctions.DECODE_URI);
2533        this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2534        this.escape             = ScriptFunction.createBuiltin("escape",     GlobalFunctions.ESCAPE);
2535        this.unescape           = ScriptFunction.createBuiltin("unescape",   GlobalFunctions.UNESCAPE);
2536        this.print              = ScriptFunction.createBuiltin("print",      env._print_no_newline ? PRINT : PRINTLN);
2537        this.load               = ScriptFunction.createBuiltin("load",       LOAD);
2538        this.loadWithNewGlobal  = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2539        this.exit               = ScriptFunction.createBuiltin("exit",       EXIT);
2540        this.quit               = ScriptFunction.createBuiltin("quit",       EXIT);
2541
2542        // built-in constructors
2543        this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2544        this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2545        this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2546        this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2547        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2548
2549        // initialize String.prototype.length to 0
2550        // add String.prototype.length
2551        final ScriptObject stringPrototype = getStringPrototype();
2552        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2553
2554        // set isArray flag on Array.prototype
2555        final ScriptObject arrayPrototype = getArrayPrototype();
2556        arrayPrototype.setIsArray();
2557
2558        if (env._es6) {
2559            this.symbol   = LAZY_SENTINEL;
2560            this.map      = LAZY_SENTINEL;
2561            this.weakMap  = LAZY_SENTINEL;
2562            this.set      = LAZY_SENTINEL;
2563            this.weakSet  = LAZY_SENTINEL;
2564        } else {
2565            // We need to manually delete nasgen-generated properties we don't want
2566            this.delete("Symbol", false);
2567            this.delete("Map", false);
2568            this.delete("WeakMap", false);
2569            this.delete("Set", false);
2570            this.delete("WeakSet", false);
2571            builtinObject.delete("getOwnPropertySymbols", false);
2572            arrayPrototype.delete("entries", false);
2573            arrayPrototype.delete("keys", false);
2574            arrayPrototype.delete("values", false);
2575        }
2576
2577        // Error stuff
2578        initErrorObjects();
2579
2580        // java access
2581        if (! env._no_java) {
2582            this.javaApi = LAZY_SENTINEL;
2583            this.javaImporter = LAZY_SENTINEL;
2584            initJavaAccess();
2585        }
2586
2587        if (! env._no_typed_arrays) {
2588            this.arrayBuffer       = LAZY_SENTINEL;
2589            this.dataView          = LAZY_SENTINEL;
2590            this.int8Array         = LAZY_SENTINEL;
2591            this.uint8Array        = LAZY_SENTINEL;
2592            this.uint8ClampedArray = LAZY_SENTINEL;
2593            this.int16Array        = LAZY_SENTINEL;
2594            this.uint16Array       = LAZY_SENTINEL;
2595            this.int32Array        = LAZY_SENTINEL;
2596            this.uint32Array       = LAZY_SENTINEL;
2597            this.float32Array      = LAZY_SENTINEL;
2598            this.float64Array      = LAZY_SENTINEL;
2599        }
2600
2601        if (env._scripting) {
2602            initScripting(env);
2603        }
2604
2605        if (Context.DEBUG) {
2606            boolean debugOkay;
2607            final SecurityManager sm = System.getSecurityManager();
2608            if (sm != null) {
2609                try {
2610                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2611                    debugOkay = true;
2612                } catch (final SecurityException ignored) {
2613                    // if no permission, don't initialize Debug object
2614                    debugOkay = false;
2615                }
2616
2617            } else {
2618                debugOkay = true;
2619            }
2620
2621            if (debugOkay) {
2622                initDebug();
2623            }
2624        }
2625
2626        copyBuiltins();
2627
2628        // expose script (command line) arguments as "arguments" property of global
2629        arguments = wrapAsObject(env.getArguments().toArray());
2630        if (env._scripting) {
2631            // synonym for "arguments" in scripting mode
2632            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2633        }
2634
2635        if (eng != null) {
2636            // default file name
2637            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2638            // __noSuchProperty__ hook for ScriptContext search of missing variables
2639            final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2640            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2641        }
2642    }
2643
2644    private void initErrorObjects() {
2645        // Error objects
2646        this.builtinError = initConstructor("Error", ScriptFunction.class);
2647        final ScriptObject errorProto = getErrorPrototype();
2648
2649        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2650        final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK);
2651        final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK);
2652        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2653        final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER);
2654        final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER);
2655        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2656        final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2657        final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2658        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2659        final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME);
2660        final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME);
2661        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2662
2663        // ECMA 15.11.4.2 Error.prototype.name
2664        // Error.prototype.name = "Error";
2665        errorProto.set(NativeError.NAME, "Error", 0);
2666        // ECMA 15.11.4.3 Error.prototype.message
2667        // Error.prototype.message = "";
2668        errorProto.set(NativeError.MESSAGE, "", 0);
2669
2670        tagBuiltinProperties("Error", builtinError);
2671
2672        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2673        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2674        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2675    }
2676
2677    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2678        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2679        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2680        prototype.set(NativeError.NAME, name, 0);
2681        prototype.set(NativeError.MESSAGE, "", 0);
2682        prototype.setInitialProto(errorProto);
2683        tagBuiltinProperties(name, cons);
2684        return cons;
2685    }
2686
2687    private void initJavaAccess() {
2688        final ScriptObject objectProto = getObjectPrototype();
2689        this.builtinPackages = new NativeJavaPackage("", objectProto);
2690        this.builtinCom = new NativeJavaPackage("com", objectProto);
2691        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2692        this.builtinJava = new NativeJavaPackage("java", objectProto);
2693        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2694        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2695        this.builtinOrg = new NativeJavaPackage("org", objectProto);
2696    }
2697
2698    private void initScripting(final ScriptEnvironment scriptEnv) {
2699        ScriptObject value;
2700        value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE);
2701        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2702
2703        value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY);
2704        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2705
2706        final String execName = ScriptingFunctions.EXEC_NAME;
2707        value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC);
2708        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2709
2710        // Nashorn extension: global.echo (scripting-mode-only)
2711        // alias for "print"
2712        value = (ScriptObject)get("print");
2713        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2714
2715        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2716        final ScriptObject options = newObject();
2717        copyOptions(options, scriptEnv);
2718        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2719
2720        // Nashorn extension: global.$ENV (scripting-mode-only)
2721        final ScriptObject env = newObject();
2722        if (System.getSecurityManager() == null) {
2723            // do not fill $ENV if we have a security manager around
2724            // Retrieve current state of ENV variables.
2725            env.putAll(System.getenv(), scriptEnv._strict);
2726
2727            // Some platforms, e.g., Windows, do not define the PWD environment
2728            // variable, so that the $ENV.PWD property needs to be explicitly
2729            // set.
2730            if (!env.containsKey(ScriptingFunctions.PWD_NAME)) {
2731                env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
2732            }
2733        }
2734        addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2735
2736        // add other special properties for exec support
2737        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2738        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2739        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2740    }
2741
2742    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2743        for (final Field f : scriptEnv.getClass().getFields()) {
2744            try {
2745                options.set(f.getName(), f.get(scriptEnv), 0);
2746            } catch (final IllegalArgumentException | IllegalAccessException exp) {
2747                throw new RuntimeException(exp);
2748            }
2749        }
2750    }
2751
2752    private void copyBuiltins() {
2753        this.array             = this.builtinArray;
2754        this._boolean          = this.builtinBoolean;
2755        this.error             = this.builtinError;
2756        this.function          = this.builtinFunction;
2757        this.com               = this.builtinCom;
2758        this.edu               = this.builtinEdu;
2759        this.java              = this.builtinJava;
2760        this.javafx            = this.builtinJavafx;
2761        this.javax             = this.builtinJavax;
2762        this.org               = this.builtinOrg;
2763        this.math              = this.builtinMath;
2764        this.number            = this.builtinNumber;
2765        this.object            = this.builtinObject;
2766        this.packages          = this.builtinPackages;
2767        this.referenceError    = this.builtinReferenceError;
2768        this.string            = this.builtinString;
2769        this.syntaxError       = this.builtinSyntaxError;
2770        this.typeError         = this.builtinTypeError;
2771    }
2772
2773    private void initDebug() {
2774        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2775    }
2776
2777    private Object printImpl(final boolean newLine, final Object... objects) {
2778        final ScriptContext sc = currentContext();
2779        @SuppressWarnings("resource")
2780        final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
2781        final StringBuilder sb = new StringBuilder();
2782
2783        for (final Object obj : objects) {
2784            if (sb.length() != 0) {
2785                sb.append(' ');
2786            }
2787
2788            sb.append(JSType.toString(obj));
2789        }
2790
2791        // Print all at once to ensure thread friendly result.
2792        if (newLine) {
2793            out.println(sb.toString());
2794        } else {
2795            out.print(sb.toString());
2796        }
2797
2798        out.flush();
2799
2800        return UNDEFINED;
2801    }
2802
2803    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2804        try {
2805            // Assuming class name pattern for built-in JS constructors.
2806            final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX);
2807
2808            sb.append("Native");
2809            sb.append(name);
2810            sb.append("$Constructor");
2811
2812            final Class<?> funcClass = Class.forName(sb.toString());
2813            final T res = clazz.cast(funcClass.newInstance());
2814
2815            if (res instanceof ScriptFunction) {
2816                // All global constructor prototypes are not-writable,
2817                // not-enumerable and not-configurable.
2818                final ScriptFunction func = (ScriptFunction)res;
2819                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2820            }
2821
2822            if (res.getProto() == null) {
2823                res.setInitialProto(getObjectPrototype());
2824            }
2825
2826            res.setIsBuiltin();
2827
2828            return res;
2829        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2830            throw new RuntimeException(e);
2831        }
2832    }
2833
2834    private ScriptObject initPrototype(final String name, final ScriptObject prototype) {
2835        try {
2836            // Assuming class name pattern for JS prototypes
2837            final String className = PACKAGE_PREFIX + name + "$Prototype";
2838
2839            final Class<?> funcClass = Class.forName(className);
2840            final ScriptObject res = (ScriptObject) funcClass.newInstance();
2841
2842            res.setIsBuiltin();
2843            res.setInitialProto(prototype);
2844            return res;
2845        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2846            throw new RuntimeException(e);
2847        }
2848    }
2849
2850    private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2851        final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2852
2853        list.addAll(Arrays.asList(func.getMap().getProperties()));
2854
2855        if (func instanceof ScriptFunction) {
2856            final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2857            if (proto != null) {
2858                list.addAll(Arrays.asList(proto.getMap().getProperties()));
2859            }
2860        }
2861
2862        final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2863        if (prop != null) {
2864            list.add(prop);
2865        }
2866
2867        return list;
2868    }
2869
2870    /**
2871     * Given a builtin object, traverse its properties recursively and associate them with a name that
2872     * will be a key to their invalidation switchpoint.
2873     * @param name name for key
2874     * @param func builtin script object
2875     */
2876    private void tagBuiltinProperties(final String name, final ScriptObject func) {
2877        SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2878        if (sp == null) {
2879            sp = context.newBuiltinSwitchPoint(name);
2880        }
2881
2882        //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2883        //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2884        for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2885            prop.setBuiltinSwitchPoint(sp);
2886        }
2887    }
2888
2889    // Function and Object constructors are inter-dependent. Also,
2890    // Function.prototype
2891    // functions are not properly initialized. We fix the references here.
2892    // NOTE: be careful if you want to re-order the operations here. You may
2893    // have
2894    // to play with object references carefully!!
2895    private void initFunctionAndObject() {
2896        // First-n-foremost is Function
2897
2898        this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2899
2900        // create global anonymous function
2901        final ScriptFunction anon = ScriptFunction.createAnonymous();
2902        // need to copy over members of Function.prototype to anon function
2903        anon.addBoundProperties(getFunctionPrototype());
2904
2905        // Function.prototype === Object.getPrototypeOf(Function) ===
2906        // <anon-function>
2907        builtinFunction.setInitialProto(anon);
2908        builtinFunction.setPrototype(anon);
2909        anon.set("constructor", builtinFunction, 0);
2910        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2911
2912        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2913        this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
2914        typeErrorThrower.preventExtensions();
2915
2916        // now initialize Object
2917        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2918        final ScriptObject ObjectPrototype = getObjectPrototype();
2919        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2920        anon.setInitialProto(ObjectPrototype);
2921
2922        // ES6 draft compliant __proto__ property of Object.prototype
2923        // accessors on Object.prototype for "__proto__"
2924        final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__);
2925        final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__);
2926        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2927
2928        // Function valued properties of Function.prototype were not properly
2929        // initialized. Because, these were created before global.function and
2930        // global.object were not initialized.
2931        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2932        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2933            final Object key = property.getKey();
2934            final Object value = builtinFunction.get(key);
2935
2936            if (value instanceof ScriptFunction && value != anon) {
2937                final ScriptFunction func = (ScriptFunction)value;
2938                func.setInitialProto(getFunctionPrototype());
2939                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2940                if (prototype != null) {
2941                    prototype.setInitialProto(ObjectPrototype);
2942                }
2943            }
2944        }
2945
2946        // For function valued properties of Object and Object.prototype, make
2947        // sure prototype's proto chain ends with Object.prototype
2948        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2949            final Object key = property.getKey();
2950            final Object value = builtinObject.get(key);
2951
2952            if (value instanceof ScriptFunction) {
2953                final ScriptFunction func = (ScriptFunction)value;
2954                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2955                if (prototype != null) {
2956                    prototype.setInitialProto(ObjectPrototype);
2957                }
2958            }
2959        }
2960
2961        properties = getObjectPrototype().getMap().getProperties();
2962
2963        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2964            final Object key   = property.getKey();
2965            if (key.equals("constructor")) {
2966                continue;
2967            }
2968
2969            final Object value = ObjectPrototype.get(key);
2970            if (value instanceof ScriptFunction) {
2971                final ScriptFunction func = (ScriptFunction)value;
2972                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2973                if (prototype != null) {
2974                    prototype.setInitialProto(ObjectPrototype);
2975                }
2976            }
2977        }
2978
2979        tagBuiltinProperties("Object", builtinObject);
2980        tagBuiltinProperties("Function", builtinFunction);
2981        tagBuiltinProperties("Function", anon);
2982    }
2983
2984    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2985        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2986    }
2987
2988    RegExpResult getLastRegExpResult() {
2989        return lastRegExpResult;
2990    }
2991
2992    void setLastRegExpResult(final RegExpResult regExpResult) {
2993        this.lastRegExpResult = regExpResult;
2994    }
2995
2996    @Override
2997    protected boolean isGlobal() {
2998        return true;
2999    }
3000
3001    /**
3002     * A class representing the ES6 global lexical scope.
3003     */
3004    private static class LexicalScope extends ScriptObject {
3005
3006        LexicalScope(final Global global) {
3007            super(global, PropertyMap.newMap());
3008        }
3009
3010        @Override
3011        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
3012            return filterInvocation(super.findGetMethod(desc, request, operation));
3013        }
3014
3015        @Override
3016        protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3017            return filterInvocation(super.findSetMethod(desc, request));
3018        }
3019
3020        @Override
3021        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
3022            // We override this method just to make it callable by Global
3023            return super.addBoundProperty(propMap, source, property, extensible);
3024        }
3025
3026        private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
3027            final MethodType type = invocation.getInvocation().type();
3028            return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
3029        }
3030    }
3031
3032}
3033