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     // performs initialization checks for Global constructor and returns the
 416     // PropertyMap, if everything is fine.
 417     private static PropertyMap checkAndGetMap(final Context context) {
 418         // security check first
 419         final SecurityManager sm = System.getSecurityManager();
 420         if (sm != null) {
 421             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 422         }
 423 
 424         // null check on context
 425         context.getClass();
 426 
 427         /*
 428          * Duplicate global's map and use it. This way the initial Map filled
 429          * by nasgen (referenced from static field in this class) is retained
 430          * 'as is' (as that one is process wide singleton.
 431          */
 432         return $nasgenmap$.duplicate();
 433     }
 434 
 435     /**
 436      * Constructor
 437      *
 438      * @param context the context
 439      */
 440     public Global(final Context context) {
 441         super(checkAndGetMap(context));
 442         this.setContext(context);
 443         this.setIsScope();
 444 
 445         final int cacheSize = context.getEnv()._class_cache_size;
 446         if (cacheSize > 0) {
 447             classCache = new ClassCache(cacheSize);
 448         }
 449     }
 450 
 451     /**
 452      * Script access to "current" Global instance
 453      *
 454      * @return the global singleton
 455      */
 456     public static Global instance() {
 457         ScriptObject global = Context.getGlobal();
 458         if (! (global instanceof Global)) {
 459             throw new IllegalStateException("no current global instance");
 460         }
 461         return (Global)global;
 462     }
 463 
 464     /**
 465      * Script access to {@link ScriptEnvironment}
 466      *
 467      * @return the script environment
 468      */
 469     static ScriptEnvironment getEnv() {
 470         return instance().getContext().getEnv();
 471     }
 472 
 473     /**
 474      * Script access to {@link Context}
 475      *
 476      * @return the context
 477      */
 478     static Context getThisContext() {
 479         return instance().getContext();
 480     }
 481 
 482     // GlobalObject interface implementation
 483 
 484     @Override










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