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