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