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