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