Global.java revision 1096:ca0e54c45981
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.ScriptRuntime.UNDEFINED;
32
33import java.io.IOException;
34import java.io.PrintWriter;
35import java.lang.invoke.MethodHandle;
36import java.lang.invoke.MethodHandles;
37import java.lang.invoke.SwitchPoint;
38import java.lang.reflect.Field;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.List;
42import java.util.Map;
43import java.util.concurrent.Callable;
44import java.util.concurrent.ConcurrentHashMap;
45import javax.script.ScriptContext;
46import javax.script.ScriptEngine;
47import jdk.internal.dynalink.linker.GuardedInvocation;
48import jdk.internal.dynalink.linker.LinkRequest;
49import jdk.nashorn.api.scripting.ClassFilter;
50import jdk.nashorn.api.scripting.ScriptObjectMirror;
51import jdk.nashorn.internal.lookup.Lookup;
52import jdk.nashorn.internal.objects.annotations.Attribute;
53import jdk.nashorn.internal.objects.annotations.Property;
54import jdk.nashorn.internal.objects.annotations.ScriptClass;
55import jdk.nashorn.internal.runtime.ConsString;
56import jdk.nashorn.internal.runtime.Context;
57import jdk.nashorn.internal.runtime.GlobalFunctions;
58import jdk.nashorn.internal.runtime.JSType;
59import jdk.nashorn.internal.runtime.NativeJavaPackage;
60import jdk.nashorn.internal.runtime.PropertyDescriptor;
61import jdk.nashorn.internal.runtime.PropertyMap;
62import jdk.nashorn.internal.runtime.Scope;
63import jdk.nashorn.internal.runtime.ScriptEnvironment;
64import jdk.nashorn.internal.runtime.ScriptFunction;
65import jdk.nashorn.internal.runtime.ScriptObject;
66import jdk.nashorn.internal.runtime.ScriptRuntime;
67import jdk.nashorn.internal.runtime.ScriptingFunctions;
68import jdk.nashorn.internal.runtime.Specialization;
69import jdk.nashorn.internal.runtime.arrays.ArrayData;
70import jdk.nashorn.internal.runtime.linker.Bootstrap;
71import jdk.nashorn.internal.runtime.linker.InvokeByName;
72import jdk.nashorn.internal.runtime.regexp.RegExpResult;
73import jdk.nashorn.internal.scripts.JO;
74
75/**
76 * Representation of global scope.
77 */
78@ScriptClass("Global")
79public final class Global extends ScriptObject implements Scope {
80    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
81    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
82    private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
83    private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
84
85    /**
86     * Optimistic builtin names that require switchpoint invalidation
87     * upon assignment. Overly conservative, but works for now, to avoid
88     * any complicated scope checks and especially heavy weight guards
89     * like
90     *
91     * <pre>
92     *     public boolean setterGuard(final Object receiver) {
93     *         final Global          global = Global.instance();
94     *         final ScriptObject    sobj   = global.getFunctionPrototype();
95     *         final Object          apply  = sobj.get("apply");
96     *         return apply == receiver;
97     *     }
98     * </pre>
99     *
100     * Naturally, checking for builtin classes like NativeFunction is cheaper,
101     * it's when you start adding property checks for said builtins you have
102     * problems with guard speed.
103     */
104
105    /** Nashorn extension: arguments array */
106    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
107    public Object arguments;
108
109    /** ECMA 15.1.2.2 parseInt (string , radix) */
110    @Property(attributes = Attribute.NOT_ENUMERABLE)
111    public Object parseInt;
112
113    /** ECMA 15.1.2.3 parseFloat (string) */
114    @Property(attributes = Attribute.NOT_ENUMERABLE)
115    public Object parseFloat;
116
117    /** ECMA 15.1.2.4 isNaN (number) */
118    @Property(attributes = Attribute.NOT_ENUMERABLE)
119    public Object isNaN;
120
121    /** ECMA 15.1.2.5 isFinite (number) */
122    @Property(attributes = Attribute.NOT_ENUMERABLE)
123    public Object isFinite;
124
125    /** ECMA 15.1.3.3 encodeURI */
126    @Property(attributes = Attribute.NOT_ENUMERABLE)
127    public Object encodeURI;
128
129    /** ECMA 15.1.3.4 encodeURIComponent */
130    @Property(attributes = Attribute.NOT_ENUMERABLE)
131    public Object encodeURIComponent;
132
133    /** ECMA 15.1.3.1 decodeURI */
134    @Property(attributes = Attribute.NOT_ENUMERABLE)
135    public Object decodeURI;
136
137    /** ECMA 15.1.3.2 decodeURIComponent */
138    @Property(attributes = Attribute.NOT_ENUMERABLE)
139    public Object decodeURIComponent;
140
141    /** ECMA B.2.1 escape (string) */
142    @Property(attributes = Attribute.NOT_ENUMERABLE)
143    public Object escape;
144
145    /** ECMA B.2.2 unescape (string) */
146    @Property(attributes = Attribute.NOT_ENUMERABLE)
147    public Object unescape;
148
149    /** Nashorn extension: global.print */
150    @Property(attributes = Attribute.NOT_ENUMERABLE)
151    public Object print;
152
153    /** Nashorn extension: global.load */
154    @Property(attributes = Attribute.NOT_ENUMERABLE)
155    public Object load;
156
157    /** Nashorn extension: global.loadWithNewGlobal */
158    @Property(attributes = Attribute.NOT_ENUMERABLE)
159    public Object loadWithNewGlobal;
160
161    /** Nashorn extension: global.exit */
162    @Property(attributes = Attribute.NOT_ENUMERABLE)
163    public Object exit;
164
165    /** Nashorn extension: global.quit */
166    @Property(attributes = Attribute.NOT_ENUMERABLE)
167    public Object quit;
168
169    /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
170    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
171    public final double NaN = Double.NaN;
172
173    /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
174    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
175    public final double Infinity = Double.POSITIVE_INFINITY;
176
177    /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
178    @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
179    public final Object undefined = UNDEFINED;
180
181    /** ECMA 15.1.2.1 eval(x) */
182    @Property(attributes = Attribute.NOT_ENUMERABLE)
183    public Object eval;
184
185    /** ECMA 15.1.4.1 Object constructor. */
186    @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
187    public volatile Object object;
188
189    /** ECMA 15.1.4.2 Function constructor. */
190    @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
191    public volatile Object function;
192
193    /** ECMA 15.1.4.3 Array constructor. */
194    @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
195    public volatile Object array;
196
197    /** ECMA 15.1.4.4 String constructor */
198    @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
199    public volatile Object string;
200
201    /** ECMA 15.1.4.5 Boolean constructor */
202    @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
203    public volatile Object _boolean;
204
205    /** ECMA 15.1.4.6 - Number constructor */
206    @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
207    public volatile Object number;
208
209    /** ECMA 15.1.4.7 Date constructor */
210    @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
211    public volatile Object date;
212
213    /** ECMA 15.1.4.8 RegExp constructor */
214    @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
215    public volatile Object regexp;
216
217    /** ECMA 15.12 - The JSON object */
218    @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
219    public volatile Object json;
220
221    /** Nashorn extension: global.JSAdapter */
222    @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
223    public volatile Object jsadapter;
224
225    /** ECMA 15.8 - The Math object */
226    @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
227    public volatile Object math;
228
229    /** Error object */
230    @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
231    public volatile Object error;
232
233    /** EvalError object */
234    @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
235    public volatile Object evalError;
236
237    /** RangeError object */
238    @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
239    public volatile Object rangeError;
240
241    /** ReferenceError object */
242    @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
243    public volatile Object referenceError;
244
245    /** SyntaxError object */
246    @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
247    public volatile Object syntaxError;
248
249    /** TypeError object */
250    @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
251    public volatile Object typeError;
252
253    /** URIError object */
254    @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
255    public volatile Object uriError;
256
257    /** ArrayBuffer object */
258    @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
259    public volatile Object arrayBuffer;
260
261    /** DataView object */
262    @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
263    public volatile Object dataView;
264
265    /** TypedArray (int8) */
266    @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
267    public volatile Object int8Array;
268
269    /** TypedArray (uint8) */
270    @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
271    public volatile Object uint8Array;
272
273    /** TypedArray (uint8) - Clamped */
274    @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
275    public volatile Object uint8ClampedArray;
276
277    /** TypedArray (int16) */
278    @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
279    public volatile Object int16Array;
280
281    /** TypedArray (uint16) */
282    @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
283    public volatile Object uint16Array;
284
285    /** TypedArray (int32) */
286    @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
287    public volatile Object int32Array;
288
289    /** TypedArray (uint32) */
290    @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
291    public volatile Object uint32Array;
292
293    /** TypedArray (float32) */
294    @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
295    public volatile Object float32Array;
296
297    /** TypedArray (float64) */
298    @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
299    public volatile Object float64Array;
300
301    /** Nashorn extension: Java access - global.Packages */
302    @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
303    public volatile Object packages;
304
305    /** Nashorn extension: Java access - global.com */
306    @Property(attributes = Attribute.NOT_ENUMERABLE)
307    public volatile Object com;
308
309    /** Nashorn extension: Java access - global.edu */
310    @Property(attributes = Attribute.NOT_ENUMERABLE)
311    public volatile Object edu;
312
313    /** Nashorn extension: Java access - global.java */
314    @Property(attributes = Attribute.NOT_ENUMERABLE)
315    public volatile Object java;
316
317    /** Nashorn extension: Java access - global.javafx */
318    @Property(attributes = Attribute.NOT_ENUMERABLE)
319    public volatile Object javafx;
320
321    /** Nashorn extension: Java access - global.javax */
322    @Property(attributes = Attribute.NOT_ENUMERABLE)
323    public volatile Object javax;
324
325    /** Nashorn extension: Java access - global.org */
326    @Property(attributes = Attribute.NOT_ENUMERABLE)
327    public volatile Object org;
328
329    /** Nashorn extension: Java access - global.javaImporter */
330    @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
331    public volatile Object javaImporter;
332
333    /** Nashorn extension: global.Java Object constructor. */
334    @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
335    public volatile Object javaApi;
336
337    /** Nashorn extension: current script's file name */
338    @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
339    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
340
341    /** Nashorn extension: current script's directory */
342    @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
343    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
344
345    /** Nashorn extension: current source line number being executed */
346    @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
347    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
348
349    /** Used as Date.prototype's default value */
350    public NativeDate   DEFAULT_DATE;
351
352    /** Used as RegExp.prototype's default value */
353    public NativeRegExp DEFAULT_REGEXP;
354
355    /*
356     * Built-in constructor objects: Even if user changes dynamic values of
357     * "Object", "Array" etc., we still want to keep original values of these
358     * constructors here. For example, we need to be able to create array,
359     * regexp literals even after user overwrites global "Array" or "RegExp"
360     * constructor - see also ECMA 262 spec. Annex D.
361     */
362    private ScriptFunction builtinFunction;
363    private ScriptFunction builtinObject;
364    private ScriptFunction builtinArray;
365    private ScriptFunction builtinBoolean;
366    private ScriptFunction builtinDate;
367    private ScriptObject   builtinJSON;
368    private ScriptFunction builtinJSAdapter;
369    private ScriptObject   builtinMath;
370    private ScriptFunction builtinNumber;
371    private ScriptFunction builtinRegExp;
372    private ScriptFunction builtinString;
373    private ScriptFunction builtinError;
374    private ScriptFunction builtinEval;
375    private ScriptFunction builtinEvalError;
376    private ScriptFunction builtinRangeError;
377    private ScriptFunction builtinReferenceError;
378    private ScriptFunction builtinSyntaxError;
379    private ScriptFunction builtinTypeError;
380    private ScriptFunction builtinURIError;
381    private ScriptObject   builtinPackages;
382    private ScriptObject   builtinCom;
383    private ScriptObject   builtinEdu;
384    private ScriptObject   builtinJava;
385    private ScriptObject   builtinJavafx;
386    private ScriptObject   builtinJavax;
387    private ScriptObject   builtinOrg;
388    private ScriptFunction builtinJavaImporter;
389    private ScriptObject   builtinJavaApi;
390    private ScriptFunction builtinArrayBuffer;
391    private ScriptFunction builtinDataView;
392    private ScriptFunction builtinInt8Array;
393    private ScriptFunction builtinUint8Array;
394    private ScriptFunction builtinUint8ClampedArray;
395    private ScriptFunction builtinInt16Array;
396    private ScriptFunction builtinUint16Array;
397    private ScriptFunction builtinInt32Array;
398    private ScriptFunction builtinUint32Array;
399    private ScriptFunction builtinFloat32Array;
400    private ScriptFunction builtinFloat64Array;
401
402    /*
403     * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
404     */
405    private ScriptFunction typeErrorThrower;
406
407    // Flag to indicate that a split method issued a return statement
408    private int splitState = -1;
409
410    // Used to store the last RegExp result to support deprecated RegExp constructor properties
411    private RegExpResult lastRegExpResult;
412
413    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
414    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
415    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
416    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
417    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
418    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
419    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
420
421    // initialized by nasgen
422    private static PropertyMap $nasgenmap$;
423
424    // context to which this global belongs to
425    private final Context context;
426
427    // current ScriptContext to use - can be null.
428    private ScriptContext scontext;
429    // current ScriptEngine associated - can be null.
430    private ScriptEngine engine;
431
432    /**
433     * Set the current script context
434     * @param scontext script context
435     */
436    public void setScriptContext(final ScriptContext scontext) {
437        this.scontext = scontext;
438    }
439
440    @Override
441    protected Context getContext() {
442        return context;
443    }
444
445    // performs initialization checks for Global constructor and returns the
446    // PropertyMap, if everything is fine.
447    private static PropertyMap checkAndGetMap(final Context context) {
448        // security check first
449        final SecurityManager sm = System.getSecurityManager();
450        if (sm != null) {
451            sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
452        }
453
454        // null check on context
455        context.getClass();
456
457        return $nasgenmap$;
458    }
459
460    /**
461     * Constructor
462     *
463     * @param context the context
464     */
465    public Global(final Context context) {
466        super(checkAndGetMap(context));
467        this.context = context;
468        this.setIsScope();
469    }
470
471    /**
472     * Script access to "current" Global instance
473     *
474     * @return the global singleton
475     */
476    public static Global instance() {
477        final Global global = Context.getGlobal();
478        global.getClass(); // null check
479        return global;
480    }
481
482    private static Global instanceFrom(final Object self) {
483        return self instanceof Global? (Global)self : instance();
484    }
485
486    /**
487     * Check if we have a Global instance
488     * @return true if one exists
489     */
490    public static boolean hasInstance() {
491        return Context.getGlobal() != null;
492    }
493
494    /**
495     * Script access to {@link ScriptEnvironment}
496     *
497     * @return the script environment
498     */
499    static ScriptEnvironment getEnv() {
500        return instance().getContext().getEnv();
501    }
502
503    /**
504     * Script access to {@link Context}
505     *
506     * @return the context
507     */
508    static Context getThisContext() {
509        return instance().getContext();
510    }
511
512    // Runtime interface to Global
513
514    /**
515     * Is there a class filter in the current Context?
516     * @return class filter
517     */
518    public ClassFilter getClassFilter() {
519        return context.getClassFilter();
520    }
521
522    /**
523     * Is this global of the given Context?
524     * @param ctxt the context
525     * @return true if this global belongs to the given Context
526     */
527    public boolean isOfContext(final Context ctxt) {
528        return this.context == ctxt;
529    }
530
531    /**
532     * Does this global belong to a strict Context?
533     * @return true if this global belongs to a strict Context
534     */
535    public boolean isStrictContext() {
536        return context.getEnv()._strict;
537    }
538
539    /**
540     * Initialize standard builtin objects like "Object", "Array", "Function" etc.
541     * as well as our extension builtin objects like "Java", "JSAdapter" as properties
542     * of the global scope object.
543     *
544     * @param eng ScriptEngine to initialize
545     */
546    public void initBuiltinObjects(final ScriptEngine eng) {
547        if (this.builtinObject != null) {
548            // already initialized, just return
549            return;
550        }
551
552        this.engine = eng;
553        init(eng);
554    }
555
556    /**
557     * Wrap a Java object as corresponding script object
558     *
559     * @param obj object to wrap
560     * @return    wrapped object
561     */
562    public Object wrapAsObject(final Object obj) {
563        if (obj instanceof Boolean) {
564            return new NativeBoolean((Boolean)obj, this);
565        } else if (obj instanceof Number) {
566            return new NativeNumber(((Number)obj).doubleValue(), this);
567        } else if (obj instanceof String || obj instanceof ConsString) {
568            return new NativeString((CharSequence)obj, this);
569        } else if (obj instanceof Object[]) { // extension
570            return new NativeArray((Object[])obj);
571        } else if (obj instanceof double[]) { // extension
572            return new NativeArray((double[])obj);
573        } else if (obj instanceof long[]) {
574            return new NativeArray((long[])obj);
575        } else if (obj instanceof int[]) {
576            return new NativeArray((int[])obj);
577        } else {
578            // FIXME: more special cases? Map? List?
579            return obj;
580        }
581    }
582
583    /**
584     * Lookup helper for JS primitive types
585     *
586     * @param request the link request for the dynamic call site.
587     * @param self     self reference
588     *
589     * @return guarded invocation
590     */
591    public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
592        if (self instanceof String || self instanceof ConsString) {
593            return NativeString.lookupPrimitive(request, self);
594        } else if (self instanceof Number) {
595            return NativeNumber.lookupPrimitive(request, self);
596        } else if (self instanceof Boolean) {
597            return NativeBoolean.lookupPrimitive(request, self);
598        }
599        throw new IllegalArgumentException("Unsupported primitive: " + self);
600    }
601
602    /**
603     * Returns a method handle that creates a wrapper object for a JS primitive value.
604     *
605     * @param self receiver object
606     * @return method handle to create wrapper objects for primitive receiver
607     */
608    public static MethodHandle getPrimitiveWrapFilter(final Object self) {
609        if (self instanceof String || self instanceof ConsString) {
610            return NativeString.WRAPFILTER;
611        } else if (self instanceof Number) {
612            return NativeNumber.WRAPFILTER;
613        } else if (self instanceof Boolean) {
614            return NativeBoolean.WRAPFILTER;
615        }
616        throw new IllegalArgumentException("Unsupported primitive: " + self);
617    }
618
619
620    /**
621     * Create a new empty script object
622     *
623     * @return the new ScriptObject
624     */
625    public ScriptObject newObject() {
626        return new JO(getObjectPrototype(), JO.getInitialMap());
627    }
628
629    /**
630     * Default value of given type
631     *
632     * @param sobj     script object
633     * @param typeHint type hint
634     *
635     * @return default value
636     */
637    public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
638        // When the [[DefaultValue]] internal method of O is called with no hint,
639        // then it behaves as if the hint were Number, unless O is a Date object
640        // in which case it behaves as if the hint were String.
641        Class<?> hint = typeHint;
642        if (hint == null) {
643            hint = Number.class;
644        }
645
646        try {
647            if (hint == String.class) {
648
649                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
650
651                if (Bootstrap.isCallable(toString)) {
652                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
653                    if (JSType.isPrimitive(value)) {
654                        return value;
655                    }
656                }
657
658                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
659                if (Bootstrap.isCallable(valueOf)) {
660                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
661                    if (JSType.isPrimitive(value)) {
662                        return value;
663                    }
664                }
665                throw typeError(this, "cannot.get.default.string");
666            }
667
668            if (hint == Number.class) {
669                final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
670                if (Bootstrap.isCallable(valueOf)) {
671                    final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
672                    if (JSType.isPrimitive(value)) {
673                        return value;
674                    }
675                }
676
677                final Object toString = TO_STRING.getGetter().invokeExact(sobj);
678                if (Bootstrap.isCallable(toString)) {
679                    final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
680                    if (JSType.isPrimitive(value)) {
681                        return value;
682                    }
683                }
684
685                throw typeError(this, "cannot.get.default.number");
686            }
687        } catch (final RuntimeException | Error e) {
688            throw e;
689        } catch (final Throwable t) {
690            throw new RuntimeException(t);
691        }
692
693        return UNDEFINED;
694    }
695
696    /**
697     * Is the given ScriptObject an ECMAScript Error object?
698     *
699     * @param sobj the object being checked
700     * @return true if sobj is an Error object
701     */
702    public boolean isError(final ScriptObject sobj) {
703        final ScriptObject errorProto = getErrorPrototype();
704        ScriptObject proto = sobj.getProto();
705        while (proto != null) {
706            if (proto == errorProto) {
707                return true;
708            }
709            proto = proto.getProto();
710        }
711        return false;
712    }
713
714    /**
715     * Create a new ECMAScript Error object.
716     *
717     * @param msg error message
718     * @return newly created Error object
719     */
720    public ScriptObject newError(final String msg) {
721        return new NativeError(msg, this);
722    }
723
724    /**
725     * Create a new ECMAScript EvalError object.
726     *
727     * @param msg error message
728     * @return newly created EvalError object
729     */
730    public ScriptObject newEvalError(final String msg) {
731        return new NativeEvalError(msg, this);
732    }
733
734    /**
735     * Create a new ECMAScript RangeError object.
736     *
737     * @param msg error message
738     * @return newly created RangeError object
739     */
740    public ScriptObject newRangeError(final String msg) {
741        return new NativeRangeError(msg, this);
742    }
743
744    /**
745     * Create a new ECMAScript ReferenceError object.
746     *
747     * @param msg error message
748     * @return newly created ReferenceError object
749     */
750    public ScriptObject newReferenceError(final String msg) {
751        return new NativeReferenceError(msg, this);
752    }
753
754    /**
755     * Create a new ECMAScript SyntaxError object.
756     *
757     * @param msg error message
758     * @return newly created SyntaxError object
759     */
760    public ScriptObject newSyntaxError(final String msg) {
761        return new NativeSyntaxError(msg, this);
762    }
763
764    /**
765     * Create a new ECMAScript TypeError object.
766     *
767     * @param msg error message
768     * @return newly created TypeError object
769     */
770    public ScriptObject newTypeError(final String msg) {
771        return new NativeTypeError(msg, this);
772    }
773
774    /**
775     * Create a new ECMAScript URIError object.
776     *
777     * @param msg error message
778     * @return newly created URIError object
779     */
780    public ScriptObject newURIError(final String msg) {
781        return new NativeURIError(msg, this);
782    }
783
784    /**
785     * Create a new ECMAScript GenericDescriptor object.
786     *
787     * @param configurable is the property configurable?
788     * @param enumerable is the property enumerable?
789     * @return newly created GenericDescriptor object
790     */
791    public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
792        return new GenericPropertyDescriptor(configurable, enumerable, this);
793    }
794
795    /**
796     * Create a new ECMAScript DatePropertyDescriptor object.
797     *
798     * @param value of the data property
799     * @param configurable is the property configurable?
800     * @param enumerable is the property enumerable?
801     * @param writable is the property writable?
802     * @return newly created DataPropertyDescriptor object
803     */
804    public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
805        return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
806    }
807
808    /**
809     * Create a new ECMAScript AccessorPropertyDescriptor object.
810     *
811     * @param get getter function of the user accessor property
812     * @param set setter function of the user accessor property
813     * @param configurable is the property configurable?
814     * @param enumerable is the property enumerable?
815     * @return newly created AccessorPropertyDescriptor object
816     */
817    public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
818        final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
819
820        if (get == null) {
821            desc.delete(PropertyDescriptor.GET, false);
822        }
823
824        if (set == null) {
825            desc.delete(PropertyDescriptor.SET, false);
826        }
827
828        return desc;
829    }
830
831    private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
832        final T obj = map.get(key);
833        if (obj != null) {
834            return obj;
835        }
836
837        try {
838            final T newObj = creator.call();
839            final T existingObj = map.putIfAbsent(key, newObj);
840            return existingObj != null ? existingObj : newObj;
841        } catch (final Exception exp) {
842            throw new RuntimeException(exp);
843        }
844    }
845
846    private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
847
848
849    /**
850     * Get cached InvokeByName object for the given key
851     * @param key key to be associated with InvokeByName object
852     * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
853     * @return InvokeByName object associated with the key.
854     */
855    public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
856        return getLazilyCreatedValue(key, creator, namedInvokers);
857    }
858
859    private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
860
861    /**
862     * Get cached dynamic method handle for the given key
863     * @param key key to be associated with dynamic method handle
864     * @param creator if method handle is absent 'creator' is called to make one (lazy init)
865     * @return dynamic method handle associated with the key.
866     */
867    public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
868        return getLazilyCreatedValue(key, creator, dynamicInvokers);
869    }
870
871    /**
872     * Hook to search missing variables in ScriptContext if available
873     * @param self used to detect if scope call or not (this function is 'strict')
874     * @param name name of the variable missing
875     * @return value of the missing variable or undefined (or TypeError for scope search)
876     */
877    public static Object __noSuchProperty__(final Object self, final Object name) {
878        final Global global = Global.instance();
879        final ScriptContext sctxt = global.scontext;
880        final String nameStr = name.toString();
881
882        if (sctxt != null) {
883            final int scope = sctxt.getAttributesScope(nameStr);
884            if (scope != -1) {
885                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
886            }
887        }
888
889        switch (nameStr) {
890        case "context":
891            return sctxt;
892        case "engine":
893            return global.engine;
894        default:
895            break;
896        }
897
898        if (self == UNDEFINED) {
899            // scope access and so throw ReferenceError
900            throw referenceError(global, "not.defined", nameStr);
901        }
902
903        return UNDEFINED;
904    }
905
906    /**
907     * This is the eval used when 'indirect' eval call is made.
908     *
909     * var global = this;
910     * global.eval("print('hello')");
911     *
912     * @param self  eval scope
913     * @param str   eval string
914     *
915     * @return the result of eval
916     */
917    public static Object eval(final Object self, final Object str) {
918        return directEval(self, str, UNDEFINED, UNDEFINED, false);
919    }
920
921    /**
922     * Direct eval
923     *
924     * @param self     The scope of eval passed as 'self'
925     * @param str      Evaluated code
926     * @param callThis "this" to be passed to the evaluated code
927     * @param location location of the eval call
928     * @param strict   is eval called a strict mode code?
929     *
930     * @return the return value of the eval
931     *
932     * This is directly invoked from generated when eval(code) is called in user code
933     */
934    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
935        if (!(str instanceof String || str instanceof ConsString)) {
936            return str;
937        }
938        final Global global = Global.instanceFrom(self);
939        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
940
941        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
942    }
943
944    /**
945     * Global print implementation - Nashorn extension
946     *
947     * @param self    scope
948     * @param objects arguments to print
949     *
950     * @return result of print (undefined)
951     */
952    public static Object print(final Object self, final Object... objects) {
953        return Global.instanceFrom(self).printImpl(false, objects);
954    }
955
956    /**
957     * Global println implementation - Nashorn extension
958     *
959     * @param self    scope
960     * @param objects arguments to print
961     *
962     * @return result of println (undefined)
963     */
964    public static Object println(final Object self, final Object... objects) {
965        return Global.instanceFrom(self).printImpl(true, objects);
966    }
967
968    /**
969     * Global load implementation - Nashorn extension
970     *
971     * @param self    scope
972     * @param source  source to load
973     *
974     * @return result of load (undefined)
975     *
976     * @throws IOException if source could not be read
977     */
978    public static Object load(final Object self, final Object source) throws IOException {
979        final Global global = Global.instanceFrom(self);
980        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
981        return global.getContext().load(scope, source);
982    }
983
984    /**
985     * Global loadWithNewGlobal implementation - Nashorn extension
986     *
987     * @param self scope
988     * @param args from plus (optional) arguments to be passed to the loaded script
989     *
990     * @return result of load (may be undefined)
991     *
992     * @throws IOException if source could not be read
993     */
994    public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
995        final Global global = Global.instanceFrom(self);
996        final int length = args.length;
997        final boolean hasArgs = 0 < length;
998        final Object from = hasArgs ? args[0] : UNDEFINED;
999        final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1000
1001        return global.getContext().loadWithNewGlobal(from, arguments);
1002    }
1003
1004    /**
1005     * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1006     *
1007     * @param self  self reference
1008     * @param code  exit code
1009     *
1010     * @return undefined (will never be reached)
1011     */
1012    public static Object exit(final Object self, final Object code) {
1013        System.exit(JSType.toInt32(code));
1014        return UNDEFINED;
1015    }
1016
1017    // builtin prototype accessors
1018    ScriptObject getFunctionPrototype() {
1019        return ScriptFunction.getPrototype(builtinFunction);
1020    }
1021
1022    ScriptObject getObjectPrototype() {
1023        return ScriptFunction.getPrototype(builtinObject);
1024    }
1025
1026    ScriptObject getArrayPrototype() {
1027        return ScriptFunction.getPrototype(builtinArray);
1028    }
1029
1030    ScriptObject getBooleanPrototype() {
1031        return ScriptFunction.getPrototype(builtinBoolean);
1032    }
1033
1034    ScriptObject getNumberPrototype() {
1035        return ScriptFunction.getPrototype(builtinNumber);
1036    }
1037
1038    ScriptObject getDatePrototype() {
1039        return ScriptFunction.getPrototype(builtinDate);
1040    }
1041
1042    ScriptObject getRegExpPrototype() {
1043        return ScriptFunction.getPrototype(builtinRegExp);
1044    }
1045
1046    ScriptObject getStringPrototype() {
1047        return ScriptFunction.getPrototype(builtinString);
1048    }
1049
1050    ScriptObject getErrorPrototype() {
1051        return ScriptFunction.getPrototype(builtinError);
1052    }
1053
1054    ScriptObject getEvalErrorPrototype() {
1055        return ScriptFunction.getPrototype(builtinEvalError);
1056    }
1057
1058    ScriptObject getRangeErrorPrototype() {
1059        return ScriptFunction.getPrototype(builtinRangeError);
1060    }
1061
1062    ScriptObject getReferenceErrorPrototype() {
1063        return ScriptFunction.getPrototype(builtinReferenceError);
1064    }
1065
1066    ScriptObject getSyntaxErrorPrototype() {
1067        return ScriptFunction.getPrototype(builtinSyntaxError);
1068    }
1069
1070    ScriptObject getTypeErrorPrototype() {
1071        return ScriptFunction.getPrototype(builtinTypeError);
1072    }
1073
1074    ScriptObject getURIErrorPrototype() {
1075        return ScriptFunction.getPrototype(builtinURIError);
1076    }
1077
1078    ScriptObject getJavaImporterPrototype() {
1079        return ScriptFunction.getPrototype(builtinJavaImporter);
1080    }
1081
1082    ScriptObject getJSAdapterPrototype() {
1083        return ScriptFunction.getPrototype(builtinJSAdapter);
1084    }
1085
1086    ScriptObject getArrayBufferPrototype() {
1087        return ScriptFunction.getPrototype(builtinArrayBuffer);
1088    }
1089
1090    ScriptObject getDataViewPrototype() {
1091        return ScriptFunction.getPrototype(builtinDataView);
1092    }
1093
1094    ScriptObject getInt8ArrayPrototype() {
1095        return ScriptFunction.getPrototype(builtinInt8Array);
1096    }
1097
1098    ScriptObject getUint8ArrayPrototype() {
1099        return ScriptFunction.getPrototype(builtinUint8Array);
1100    }
1101
1102    ScriptObject getUint8ClampedArrayPrototype() {
1103        return ScriptFunction.getPrototype(builtinUint8ClampedArray);
1104    }
1105
1106    ScriptObject getInt16ArrayPrototype() {
1107        return ScriptFunction.getPrototype(builtinInt16Array);
1108    }
1109
1110    ScriptObject getUint16ArrayPrototype() {
1111        return ScriptFunction.getPrototype(builtinUint16Array);
1112    }
1113
1114    ScriptObject getInt32ArrayPrototype() {
1115        return ScriptFunction.getPrototype(builtinInt32Array);
1116    }
1117
1118    ScriptObject getUint32ArrayPrototype() {
1119        return ScriptFunction.getPrototype(builtinUint32Array);
1120    }
1121
1122    ScriptObject getFloat32ArrayPrototype() {
1123        return ScriptFunction.getPrototype(builtinFloat32Array);
1124    }
1125
1126    ScriptObject getFloat64ArrayPrototype() {
1127        return ScriptFunction.getPrototype(builtinFloat64Array);
1128    }
1129
1130    private ScriptFunction getBuiltinArray() {
1131        return builtinArray;
1132    }
1133
1134    ScriptFunction getTypeErrorThrower() {
1135        return typeErrorThrower;
1136    }
1137
1138    /**
1139     * Called from compiled script code to test if builtin has been overridden
1140     *
1141     * @return true if builtin array has not been overridden
1142     */
1143    public static boolean isBuiltinArray() {
1144        final Global instance = Global.instance();
1145        return instance.array == instance.getBuiltinArray();
1146    }
1147
1148    private ScriptFunction getBuiltinBoolean() {
1149        return builtinBoolean;
1150    }
1151
1152    /**
1153     * Called from compiled script code to test if builtin has been overridden
1154     *
1155     * @return true if builtin boolean has not been overridden
1156     */
1157    public static boolean isBuiltinBoolean() {
1158        final Global instance = Global.instance();
1159        return instance._boolean == instance.getBuiltinBoolean();
1160    }
1161
1162    private ScriptFunction getBuiltinDate() {
1163        return builtinDate;
1164    }
1165
1166    /**
1167     * Called from compiled script code to test if builtin has been overridden
1168     *
1169     * @return true if builtin date has not been overridden
1170     */
1171    public static boolean isBuiltinDate() {
1172        final Global instance = Global.instance();
1173        return instance.date == instance.getBuiltinDate();
1174    }
1175
1176    private ScriptFunction getBuiltinError() {
1177        return builtinError;
1178    }
1179
1180    /**
1181     * Called from compiled script code to test if builtin has been overridden
1182     *
1183     * @return true if builtin error has not been overridden
1184     */
1185    public static boolean isBuiltinError() {
1186        final Global instance = Global.instance();
1187        return instance.error == instance.getBuiltinError();
1188    }
1189
1190    private ScriptFunction getBuiltinEvalError() {
1191        return builtinEvalError;
1192    }
1193
1194    /**
1195     * Called from compiled script code to test if builtin has been overridden
1196     *
1197     * @return true if builtin eval error has not been overridden
1198     */
1199    public static boolean isBuiltinEvalError() {
1200        final Global instance = Global.instance();
1201        return instance.evalError == instance.getBuiltinEvalError();
1202    }
1203
1204    private ScriptFunction getBuiltinFunction() {
1205        return builtinFunction;
1206    }
1207
1208    /**
1209     * Called from compiled script code to test if builtin has been overridden
1210     *
1211     * @return true if builtin function has not been overridden
1212     */
1213    public static boolean isBuiltinFunction() {
1214        final Global instance = Global.instance();
1215        return instance.function == instance.getBuiltinFunction();
1216    }
1217
1218    /**
1219     * Get the switchpoint used to check property changes for Function.prototype.apply
1220     * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1221     */
1222    public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1223        return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1224    }
1225
1226    private static boolean isBuiltinFunctionProperty(final String name) {
1227        final Global instance = Global.instance();
1228        final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1229        if (builtinFunction == null) {
1230            return false; //conservative for compile-only mode
1231        }
1232        final boolean isBuiltinFunction = instance.function == builtinFunction;
1233        return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1234    }
1235
1236    /**
1237     * Check if the Function.prototype.apply has not been replaced
1238     * @return true if Function.prototype.apply has been replaced
1239     */
1240    public static boolean isBuiltinFunctionPrototypeApply() {
1241        return isBuiltinFunctionProperty("apply");
1242    }
1243
1244    /**
1245     * Check if the Function.prototype.apply has not been replaced
1246     * @return true if Function.prototype.call has been replaced
1247     */
1248    public static boolean isBuiltinFunctionPrototypeCall() {
1249        return isBuiltinFunctionProperty("call");
1250    }
1251
1252    private ScriptFunction getBuiltinJSAdapter() {
1253        return builtinJSAdapter;
1254    }
1255
1256    /**
1257     * Called from compiled script code to test if builtin has been overridden
1258     *
1259     * @return true if builtin JSAdapter has not been overridden
1260     */
1261    public static boolean isBuiltinJSAdapter() {
1262        final Global instance = Global.instance();
1263        return instance.jsadapter == instance.getBuiltinJSAdapter();
1264    }
1265
1266    private ScriptObject getBuiltinJSON() {
1267        return builtinJSON;
1268    }
1269
1270    /**
1271     * Called from compiled script code to test if builtin has been overridden
1272     *
1273     * @return true if builtin JSON has has not been overridden
1274     */
1275    public static boolean isBuiltinJSON() {
1276        final Global instance = Global.instance();
1277        return instance.json == instance.getBuiltinJSON();
1278    }
1279
1280    private ScriptObject getBuiltinJava() {
1281        return builtinJava;
1282    }
1283
1284    /**
1285     * Called from compiled script code to test if builtin has been overridden
1286     *
1287     * @return true if builtin Java has not been overridden
1288     */
1289    public static boolean isBuiltinJava() {
1290        final Global instance = Global.instance();
1291        return instance.java == instance.getBuiltinJava();
1292    }
1293
1294    private ScriptObject getBuiltinJavax() {
1295        return builtinJavax;
1296    }
1297
1298    /**
1299     * Called from compiled script code to test if builtin has been overridden
1300     *
1301     * @return true if builtin Javax has not been overridden
1302     */
1303    public static boolean isBuiltinJavax() {
1304        final Global instance = Global.instance();
1305        return instance.javax == instance.getBuiltinJavax();
1306    }
1307
1308    private ScriptObject getBuiltinJavaImporter() {
1309        return builtinJavaImporter;
1310    }
1311
1312    /**
1313     * Called from compiled script code to test if builtin has been overridden
1314     *
1315     * @return true if builtin Java importer has not been overridden
1316     */
1317    public static boolean isBuiltinJavaImporter() {
1318        final Global instance = Global.instance();
1319        return instance.javaImporter == instance.getBuiltinJavaImporter();
1320    }
1321
1322    private ScriptObject getBuiltinMath() {
1323        return builtinMath;
1324    }
1325
1326    /**
1327     * Called from compiled script code to test if builtin has been overridden
1328     *
1329     * @return true if builtin math has not been overridden
1330     */
1331    public static boolean isBuiltinMath() {
1332        final Global instance = Global.instance();
1333        return instance.math == instance.getBuiltinMath();
1334    }
1335
1336    private ScriptFunction getBuiltinNumber() {
1337        return builtinNumber;
1338    }
1339
1340    /**
1341     * Called from compiled script code to test if builtin has been overridden
1342     *
1343     * @return true if builtin number has not been overridden
1344     */
1345    public static boolean isBuiltinNumber() {
1346        final Global instance = Global.instance();
1347        return instance.number == instance.getBuiltinNumber();
1348    }
1349
1350    private ScriptFunction getBuiltinObject() {
1351        return builtinObject;
1352    }
1353
1354    /**
1355     * Called from compiled script code to test if builtin has been overridden
1356     *
1357     * @return true if builtin object has not been overridden
1358     */
1359    public static boolean isBuiltinObject() {
1360        final Global instance = Global.instance();
1361        return instance.object == instance.getBuiltinObject();
1362    }
1363
1364    private ScriptObject getBuiltinPackages() {
1365        return builtinPackages;
1366    }
1367
1368    /**
1369     * Called from compiled script code to test if builtin has been overridden
1370     *
1371     * @return true if builtin package has not been overridden
1372     */
1373    public static boolean isBuiltinPackages() {
1374        final Global instance = Global.instance();
1375        return instance.packages == instance.getBuiltinPackages();
1376    }
1377
1378    private ScriptFunction getBuiltinRangeError() {
1379        return builtinRangeError;
1380    }
1381
1382    /**
1383     * Called from compiled script code to test if builtin has been overridden
1384     *
1385     * @return true if builtin range error has not been overridden
1386     */
1387    public static boolean isBuiltinRangeError() {
1388        final Global instance = Global.instance();
1389        return instance.rangeError == instance.getBuiltinRangeError();
1390    }
1391
1392    private ScriptFunction getBuiltinReferenceError() {
1393        return builtinReferenceError;
1394    }
1395
1396    /**
1397     * Called from compiled script code to test if builtin has been overridden
1398     *
1399     * @return true if builtin reference error has not been overridden
1400     */
1401    public static boolean isBuiltinReferenceError() {
1402        final Global instance = Global.instance();
1403        return instance.referenceError == instance.getBuiltinReferenceError();
1404    }
1405
1406    private ScriptFunction getBuiltinRegExp() {
1407        return builtinRegExp;
1408    }
1409
1410    /**
1411     * Called from compiled script code to test if builtin has been overridden
1412     *
1413     * @return true if builtin regexp has not been overridden
1414     */
1415    public static boolean isBuiltinRegExp() {
1416        final Global instance = Global.instance();
1417        return instance.regexp == instance.getBuiltinRegExp();
1418    }
1419
1420    private ScriptFunction getBuiltinString() {
1421        return builtinString;
1422    }
1423
1424    /**
1425     * Called from compiled script code to test if builtin has been overridden
1426     *
1427     * @return true if builtin Java has not been overridden
1428     */
1429    public static boolean isBuiltinString() {
1430        final Global instance = Global.instance();
1431        return instance.string == instance.getBuiltinString();
1432    }
1433
1434    private ScriptFunction getBuiltinSyntaxError() {
1435        return builtinSyntaxError;
1436    }
1437
1438    /**
1439     * Called from compiled script code to test if builtin has been overridden
1440     *
1441     * @return true if builtin syntax error has not been overridden
1442     */
1443    public static boolean isBuiltinSyntaxError() {
1444        final Global instance = Global.instance();
1445        return instance.syntaxError == instance.getBuiltinSyntaxError();
1446    }
1447
1448    private ScriptFunction getBuiltinTypeError() {
1449        return builtinTypeError;
1450    }
1451
1452    /**
1453     * Called from compiled script code to test if builtin has been overridden
1454     *
1455     * @return true if builtin type error has not been overridden
1456     */
1457    public static boolean isBuiltinTypeError() {
1458        final Global instance = Global.instance();
1459        return instance.typeError == instance.getBuiltinTypeError();
1460    }
1461
1462    private ScriptFunction getBuiltinURIError() {
1463        return builtinURIError;
1464    }
1465
1466    /**
1467     * Called from compiled script code to test if builtin has been overridden
1468     *
1469     * @return true if builtin URI error has not been overridden
1470     */
1471    public static boolean isBuiltinURIError() {
1472        final Global instance = Global.instance();
1473        return instance.uriError == instance.getBuiltinURIError();
1474    }
1475
1476    @Override
1477    public String getClassName() {
1478        return "global";
1479    }
1480
1481    /**
1482     * Copy function used to clone NativeRegExp objects.
1483     *
1484     * @param regexp a NativeRegExp to clone
1485     *
1486     * @return copy of the given regexp object
1487     */
1488    public static Object regExpCopy(final Object regexp) {
1489        return new NativeRegExp((NativeRegExp)regexp);
1490    }
1491
1492    /**
1493     * Convert given object to NativeRegExp type.
1494     *
1495     * @param obj object to be converted
1496     * @return NativeRegExp instance
1497     */
1498    public static NativeRegExp toRegExp(final Object obj) {
1499        if (obj instanceof NativeRegExp) {
1500            return (NativeRegExp)obj;
1501        }
1502        return new NativeRegExp(JSType.toString(obj));
1503    }
1504
1505    /**
1506     * ECMA 9.9 ToObject implementation
1507     *
1508     * @param obj  an item for which to run ToObject
1509     * @return ToObject version of given item
1510     */
1511    public static Object toObject(final Object obj) {
1512        if (obj == null || obj == UNDEFINED) {
1513            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1514        }
1515
1516        if (obj instanceof ScriptObject) {
1517            return obj;
1518        }
1519
1520        return instance().wrapAsObject(obj);
1521    }
1522
1523    /**
1524     * Allocate a new object array.
1525     *
1526     * @param initial object values.
1527     * @return the new array
1528     */
1529    public static NativeArray allocate(final Object[] initial) {
1530        ArrayData arrayData = ArrayData.allocate(initial);
1531
1532        for (int index = 0; index < initial.length; index++) {
1533            final Object value = initial[index];
1534
1535            if (value == ScriptRuntime.EMPTY) {
1536                arrayData = arrayData.delete(index);
1537            }
1538        }
1539
1540        return new NativeArray(arrayData);
1541    }
1542
1543    /**
1544     * Allocate a new number array.
1545     *
1546     * @param initial number values.
1547     * @return the new array
1548     */
1549    public static NativeArray allocate(final double[] initial) {
1550        return new NativeArray(ArrayData.allocate(initial));
1551    }
1552
1553    /**
1554     * Allocate a new long array.
1555     *
1556     * @param initial number values.
1557     * @return the new array
1558     */
1559    public static NativeArray allocate(final long[] initial) {
1560        return new NativeArray(ArrayData.allocate(initial));
1561    }
1562
1563    /**
1564     * Allocate a new integer array.
1565     *
1566     * @param initial number values.
1567     * @return the new array
1568     */
1569    public static NativeArray allocate(final int[] initial) {
1570        return new NativeArray(ArrayData.allocate(initial));
1571    }
1572
1573    /**
1574     * Allocate a new object array for arguments.
1575     *
1576     * @param arguments initial arguments passed.
1577     * @param callee reference to the function that uses arguments object
1578     * @param numParams actual number of declared parameters
1579     *
1580     * @return the new array
1581     */
1582    public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1583        return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1584    }
1585
1586    /**
1587     * Called from generated to check if given function is the builtin 'eval'. If
1588     * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1589     *
1590     * @param  fn function object that is checked
1591     * @return true if fn is the builtin eval
1592     */
1593    public static boolean isEval(final Object fn) {
1594        return fn == Global.instance().builtinEval;
1595    }
1596
1597    /**
1598     * Called from generated to replace a location property placeholder with the actual location property value.
1599     *
1600     * @param  placeholder the value tested for being a placeholder for a location property
1601     * @param  locationProperty the actual value for the location property
1602     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
1603     */
1604    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
1605        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
1606    }
1607
1608    /**
1609     * Called from runtime internals to check if the passed value is a location property placeholder.
1610     * @param  placeholder the value tested for being a placeholder for a location property
1611     * @return true if the value is a placeholder, false otherwise.
1612     */
1613    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
1614        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
1615    }
1616
1617    /**
1618     * Create a new RegExp object.
1619     *
1620     * @param expression Regular expression.
1621     * @param options    Search options.
1622     *
1623     * @return New RegExp object.
1624     */
1625    public static Object newRegExp(final String expression, final String options) {
1626        if (options == null) {
1627            return new NativeRegExp(expression);
1628        }
1629        return new NativeRegExp(expression, options);
1630    }
1631
1632    /**
1633     * Get the object prototype
1634     *
1635     * @return the object prototype
1636     */
1637    public static ScriptObject objectPrototype() {
1638        return Global.instance().getObjectPrototype();
1639    }
1640
1641    /**
1642     * Create a new empty object instance.
1643     *
1644     * @return New empty object.
1645     */
1646    public static ScriptObject newEmptyInstance() {
1647        return Global.instance().newObject();
1648    }
1649
1650    /**
1651     * Check if a given object is a ScriptObject, raises an exception if this is
1652     * not the case
1653     *
1654     * @param obj and object to check
1655     * @return the script object
1656     */
1657    public static ScriptObject checkObject(final Object obj) {
1658        if (!(obj instanceof ScriptObject)) {
1659            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1660        }
1661        return (ScriptObject)obj;
1662    }
1663
1664    /**
1665     * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1666     * if this object is null or undefined.
1667     *
1668     * @param obj an object to check
1669     */
1670    public static void checkObjectCoercible(final Object obj) {
1671        if (obj == null || obj == UNDEFINED) {
1672            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1673        }
1674    }
1675
1676    /**
1677     * Get the current split state.
1678     *
1679     * @return current split state
1680     */
1681    @Override
1682    public int getSplitState() {
1683        return splitState;
1684    }
1685
1686    /**
1687     * Set the current split state.
1688     *
1689     * @param state current split state
1690     */
1691    @Override
1692    public void setSplitState(final int state) {
1693        splitState = state;
1694    }
1695
1696    private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
1697        final T func = initConstructor(name, clazz);
1698        tagBuiltinProperties(name, func);
1699        return func;
1700    }
1701
1702    private void init(final ScriptEngine eng) {
1703        assert Context.getGlobal() == this : "this global is not set as current";
1704
1705        final ScriptEnvironment env = getContext().getEnv();
1706
1707        // initialize Function and Object constructor
1708        initFunctionAndObject();
1709
1710        // Now fix Global's own proto.
1711        this.setInitialProto(getObjectPrototype());
1712
1713        // initialize global function properties
1714        this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1715
1716        this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
1717                    new Specialization[] {
1718                    new Specialization(GlobalFunctions.PARSEINT_Z),
1719                    new Specialization(GlobalFunctions.PARSEINT_I),
1720                    new Specialization(GlobalFunctions.PARSEINT_J),
1721                    new Specialization(GlobalFunctions.PARSEINT_OI),
1722                    new Specialization(GlobalFunctions.PARSEINT_O) });
1723        this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1724        this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
1725                   new Specialization[] {
1726                        new Specialization(GlobalFunctions.IS_NAN_I),
1727                        new Specialization(GlobalFunctions.IS_NAN_J),
1728                        new Specialization(GlobalFunctions.IS_NAN_D) });
1729        this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1730        this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1731        this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1732        this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1733        this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1734        this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1735        this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1736        this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1737        this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1738        this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1739        this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1740        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1741        this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1742        this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1743
1744        // built-in constructors
1745        this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
1746        this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
1747        this.builtinDate      = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1748        this.builtinJSON      = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1749        this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1750        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
1751        this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
1752        this.builtinRegExp    = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
1753        this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
1754
1755        // initialize String.prototype.length to 0
1756        // add String.prototype.length
1757        final ScriptObject stringPrototype = getStringPrototype();
1758        stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1759
1760        // set isArray flag on Array.prototype
1761        final ScriptObject arrayPrototype = getArrayPrototype();
1762        arrayPrototype.setIsArray();
1763
1764        this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1765
1766        // initialize default regexp object
1767        this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1768
1769        // RegExp.prototype should behave like a RegExp object. So copy the
1770        // properties.
1771        final ScriptObject regExpProto = getRegExpPrototype();
1772        regExpProto.addBoundProperties(DEFAULT_REGEXP);
1773
1774        // Error stuff
1775        initErrorObjects();
1776
1777        // java access
1778        if (! env._no_java) {
1779            initJavaAccess();
1780        }
1781
1782        if (! env._no_typed_arrays) {
1783            initTypedArray();
1784        }
1785
1786        if (env._scripting) {
1787            initScripting(env);
1788        }
1789
1790        if (Context.DEBUG) {
1791            boolean debugOkay;
1792            final SecurityManager sm = System.getSecurityManager();
1793            if (sm != null) {
1794                try {
1795                    sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1796                    debugOkay = true;
1797                } catch (final SecurityException ignored) {
1798                    // if no permission, don't initialize Debug object
1799                    debugOkay = false;
1800                }
1801
1802            } else {
1803                debugOkay = true;
1804            }
1805
1806            if (debugOkay) {
1807                initDebug();
1808            }
1809        }
1810
1811        copyBuiltins();
1812
1813        // expose script (command line) arguments as "arguments" property of global
1814        arguments = wrapAsObject(env.getArguments().toArray());
1815        if (env._scripting) {
1816            // synonym for "arguments" in scripting mode
1817            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
1818        }
1819
1820        if (eng != null) {
1821            // default file name
1822            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
1823            // __noSuchProperty__ hook for ScriptContext search of missing variables
1824            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
1825            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
1826        }
1827    }
1828
1829    private void initErrorObjects() {
1830        // Error objects
1831        this.builtinError = initConstructor("Error", ScriptFunction.class);
1832        final ScriptObject errorProto = getErrorPrototype();
1833
1834        // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1835        final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1836        final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1837        errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1838        final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1839        final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1840        errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1841        final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1842        final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1843        errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1844        final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1845        final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1846        errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1847
1848        // ECMA 15.11.4.2 Error.prototype.name
1849        // Error.prototype.name = "Error";
1850        errorProto.set(NativeError.NAME, "Error", 0);
1851        // ECMA 15.11.4.3 Error.prototype.message
1852        // Error.prototype.message = "";
1853        errorProto.set(NativeError.MESSAGE, "", 0);
1854
1855        tagBuiltinProperties("Error", builtinError);
1856
1857        this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1858        this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1859        this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1860        this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1861        this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1862        this.builtinURIError = initErrorSubtype("URIError", errorProto);
1863    }
1864
1865    private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1866        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
1867        final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1868        prototype.set(NativeError.NAME, name, 0);
1869        prototype.set(NativeError.MESSAGE, "", 0);
1870        prototype.setInitialProto(errorProto);
1871        tagBuiltinProperties(name, cons);
1872        return cons;
1873    }
1874
1875    private void initJavaAccess() {
1876        final ScriptObject objectProto = getObjectPrototype();
1877        this.builtinPackages = new NativeJavaPackage("", objectProto);
1878        this.builtinCom = new NativeJavaPackage("com", objectProto);
1879        this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1880        this.builtinJava = new NativeJavaPackage("java", objectProto);
1881        this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1882        this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1883        this.builtinOrg = new NativeJavaPackage("org", objectProto);
1884        this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1885        this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1886    }
1887
1888    private void initScripting(final ScriptEnvironment scriptEnv) {
1889        Object value;
1890        value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1891        addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1892
1893        value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1894        addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1895
1896        final String execName = ScriptingFunctions.EXEC_NAME;
1897        value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1898        addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1899
1900        // Nashorn extension: global.echo (scripting-mode-only)
1901        // alias for "print"
1902        value = get("print");
1903        addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1904
1905        // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1906        final ScriptObject options = newObject();
1907        copyOptions(options, scriptEnv);
1908        addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1909
1910        // Nashorn extension: global.$ENV (scripting-mode-only)
1911        if (System.getSecurityManager() == null) {
1912            // do not fill $ENV if we have a security manager around
1913            // Retrieve current state of ENV variables.
1914            final ScriptObject env = newObject();
1915            env.putAll(System.getenv(), scriptEnv._strict);
1916            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1917        } else {
1918            addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1919        }
1920
1921        // add other special properties for exec support
1922        addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1923        addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1924        addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1925    }
1926
1927    private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1928        for (final Field f : scriptEnv.getClass().getFields()) {
1929            try {
1930                options.set(f.getName(), f.get(scriptEnv), 0);
1931            } catch (final IllegalArgumentException | IllegalAccessException exp) {
1932                throw new RuntimeException(exp);
1933            }
1934        }
1935    }
1936
1937    private void initTypedArray() {
1938        this.builtinArrayBuffer       = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1939        this.builtinDataView          = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1940        this.builtinInt8Array         = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1941        this.builtinUint8Array        = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1942        this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1943        this.builtinInt16Array        = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1944        this.builtinUint16Array       = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1945        this.builtinInt32Array        = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1946        this.builtinUint32Array       = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1947        this.builtinFloat32Array      = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1948        this.builtinFloat64Array      = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1949
1950    }
1951
1952    private void copyBuiltins() {
1953        this.array             = this.builtinArray;
1954        this._boolean          = this.builtinBoolean;
1955        this.date              = this.builtinDate;
1956        this.error             = this.builtinError;
1957        this.evalError         = this.builtinEvalError;
1958        this.function          = this.builtinFunction;
1959        this.jsadapter         = this.builtinJSAdapter;
1960        this.json              = this.builtinJSON;
1961        this.com               = this.builtinCom;
1962        this.edu               = this.builtinEdu;
1963        this.java              = this.builtinJava;
1964        this.javafx            = this.builtinJavafx;
1965        this.javax             = this.builtinJavax;
1966        this.org               = this.builtinOrg;
1967        this.javaImporter      = this.builtinJavaImporter;
1968        this.javaApi           = this.builtinJavaApi;
1969        this.math              = this.builtinMath;
1970        this.number            = this.builtinNumber;
1971        this.object            = this.builtinObject;
1972        this.packages          = this.builtinPackages;
1973        this.rangeError        = this.builtinRangeError;
1974        this.referenceError    = this.builtinReferenceError;
1975        this.regexp            = this.builtinRegExp;
1976        this.string            = this.builtinString;
1977        this.syntaxError       = this.builtinSyntaxError;
1978        this.typeError         = this.builtinTypeError;
1979        this.uriError          = this.builtinURIError;
1980        this.arrayBuffer       = this.builtinArrayBuffer;
1981        this.dataView          = this.builtinDataView;
1982        this.int8Array         = this.builtinInt8Array;
1983        this.uint8Array        = this.builtinUint8Array;
1984        this.uint8ClampedArray = this.builtinUint8ClampedArray;
1985        this.int16Array        = this.builtinInt16Array;
1986        this.uint16Array       = this.builtinUint16Array;
1987        this.int32Array        = this.builtinInt32Array;
1988        this.uint32Array       = this.builtinUint32Array;
1989        this.float32Array      = this.builtinFloat32Array;
1990        this.float64Array      = this.builtinFloat64Array;
1991    }
1992
1993    private void initDebug() {
1994        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
1995    }
1996
1997    private Object printImpl(final boolean newLine, final Object... objects) {
1998        @SuppressWarnings("resource")
1999        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2000        final StringBuilder sb = new StringBuilder();
2001
2002        for (final Object obj : objects) {
2003            if (sb.length() != 0) {
2004                sb.append(' ');
2005            }
2006
2007            sb.append(JSType.toString(obj));
2008        }
2009
2010        // Print all at once to ensure thread friendly result.
2011        if (newLine) {
2012            out.println(sb.toString());
2013        } else {
2014            out.print(sb.toString());
2015        }
2016
2017        out.flush();
2018
2019        return UNDEFINED;
2020    }
2021
2022    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2023        try {
2024            // Assuming class name pattern for built-in JS constructors.
2025            final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2026
2027            sb.append("Native");
2028            sb.append(name);
2029            sb.append("$Constructor");
2030
2031            final Class<?> funcClass = Class.forName(sb.toString());
2032            final T res = clazz.cast(funcClass.newInstance());
2033
2034            if (res instanceof ScriptFunction) {
2035                // All global constructor prototypes are not-writable,
2036                // not-enumerable and not-configurable.
2037                final ScriptFunction func = (ScriptFunction)res;
2038                func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2039            }
2040
2041            if (res.getProto() == null) {
2042                res.setInitialProto(getObjectPrototype());
2043            }
2044
2045            res.setIsBuiltin();
2046
2047            return res;
2048        } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2049            throw new RuntimeException(e);
2050        }
2051    }
2052
2053    private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2054        final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2055
2056        list.addAll(Arrays.asList(func.getMap().getProperties()));
2057
2058        if (func instanceof ScriptFunction) {
2059            final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2060            if (proto != null) {
2061                list.addAll(Arrays.asList(proto.getMap().getProperties()));
2062            }
2063        }
2064
2065        final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2066        if (prop != null) {
2067            list.add(prop);
2068        }
2069
2070        return list;
2071    }
2072
2073    /**
2074     * Given a builtin object, traverse its properties recursively and associate them with a name that
2075     * will be a key to their invalidation switchpoint.
2076     * @param name name for key
2077     * @param func builtin script object
2078     */
2079    private void tagBuiltinProperties(final String name, final ScriptObject func) {
2080        SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2081        if (sp == null) {
2082            sp = context.newBuiltinSwitchPoint(name);
2083        }
2084
2085        //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2086        //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2087        for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2088            prop.setBuiltinSwitchPoint(sp);
2089        }
2090    }
2091
2092    // Function and Object constructors are inter-dependent. Also,
2093    // Function.prototype
2094    // functions are not properly initialized. We fix the references here.
2095    // NOTE: be careful if you want to re-order the operations here. You may
2096    // have
2097    // to play with object references carefully!!
2098    private void initFunctionAndObject() {
2099        // First-n-foremost is Function
2100
2101        this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2102
2103        // create global anonymous function
2104        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2105        // need to copy over members of Function.prototype to anon function
2106        anon.addBoundProperties(getFunctionPrototype());
2107
2108        // Function.prototype === Object.getPrototypeOf(Function) ===
2109        // <anon-function>
2110        builtinFunction.setInitialProto(anon);
2111        builtinFunction.setPrototype(anon);
2112        anon.set("constructor", builtinFunction, 0);
2113        anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2114
2115        // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2116        this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2117        typeErrorThrower.setPrototype(UNDEFINED);
2118        // Non-constructor built-in functions do not have "prototype" property
2119        typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2120        typeErrorThrower.preventExtensions();
2121
2122        // now initialize Object
2123        this.builtinObject = initConstructor("Object", ScriptFunction.class);
2124        final ScriptObject ObjectPrototype = getObjectPrototype();
2125        // Object.getPrototypeOf(Function.prototype) === Object.prototype
2126        anon.setInitialProto(ObjectPrototype);
2127
2128        // ES6 draft compliant __proto__ property of Object.prototype
2129        // accessors on Object.prototype for "__proto__"
2130        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2131        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2132        ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2133
2134        // Function valued properties of Function.prototype were not properly
2135        // initialized. Because, these were created before global.function and
2136        // global.object were not initialized.
2137        jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2138        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2139            final Object key = property.getKey();
2140            final Object value = builtinFunction.get(key);
2141
2142            if (value instanceof ScriptFunction && value != anon) {
2143                final ScriptFunction func = (ScriptFunction)value;
2144                func.setInitialProto(getFunctionPrototype());
2145                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2146                if (prototype != null) {
2147                    prototype.setInitialProto(ObjectPrototype);
2148                }
2149            }
2150        }
2151
2152        // For function valued properties of Object and Object.prototype, make
2153        // sure prototype's proto chain ends with Object.prototype
2154        for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2155            final Object key = property.getKey();
2156            final Object value = builtinObject.get(key);
2157
2158            if (value instanceof ScriptFunction) {
2159                final ScriptFunction func = (ScriptFunction)value;
2160                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2161                if (prototype != null) {
2162                    prototype.setInitialProto(ObjectPrototype);
2163                }
2164            }
2165        }
2166
2167        properties = getObjectPrototype().getMap().getProperties();
2168
2169        for (final jdk.nashorn.internal.runtime.Property property : properties) {
2170            final Object key   = property.getKey();
2171            if (key.equals("constructor")) {
2172                continue;
2173            }
2174
2175            final Object value = ObjectPrototype.get(key);
2176            if (value instanceof ScriptFunction) {
2177                final ScriptFunction func = (ScriptFunction)value;
2178                final ScriptObject prototype = ScriptFunction.getPrototype(func);
2179                if (prototype != null) {
2180                    prototype.setInitialProto(ObjectPrototype);
2181                }
2182            }
2183        }
2184
2185        tagBuiltinProperties("Object", builtinObject);
2186        tagBuiltinProperties("Function", builtinFunction);
2187        tagBuiltinProperties("Function", anon);
2188    }
2189
2190    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2191        return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2192    }
2193
2194    RegExpResult getLastRegExpResult() {
2195        return lastRegExpResult;
2196    }
2197
2198    void setLastRegExpResult(final RegExpResult regExpResult) {
2199        this.lastRegExpResult = regExpResult;
2200    }
2201
2202    @Override
2203    protected boolean isGlobal() {
2204        return true;
2205    }
2206}
2207