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