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