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