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.referenceError;
  30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  31 import static jdk.nashorn.internal.runtime.JSType.isString;
  32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  33 
  34 import java.io.IOException;
  35 import java.io.PrintWriter;
  36 import java.lang.invoke.MethodHandle;
  37 import java.lang.invoke.MethodHandles;
  38 import java.lang.invoke.MethodType;
  39 import java.lang.invoke.SwitchPoint;
  40 import java.lang.reflect.Field;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.List;
  44 import java.util.Map;
  45 import java.util.Objects;
  46 import java.util.concurrent.Callable;
  47 import java.util.concurrent.ConcurrentHashMap;
  48 import javax.script.ScriptContext;
  49 import javax.script.ScriptEngine;
  50 import jdk.internal.dynalink.CallSiteDescriptor;
  51 import jdk.internal.dynalink.linker.GuardedInvocation;
  52 import jdk.internal.dynalink.linker.LinkRequest;
  53 import jdk.nashorn.api.scripting.ClassFilter;
  54 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  55 import jdk.nashorn.internal.lookup.Lookup;
  56 import jdk.nashorn.internal.objects.annotations.Attribute;
  57 import jdk.nashorn.internal.objects.annotations.Getter;
  58 import jdk.nashorn.internal.objects.annotations.Property;
  59 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  60 import jdk.nashorn.internal.objects.annotations.Setter;
  61 import jdk.nashorn.internal.runtime.Context;
  62 import jdk.nashorn.internal.runtime.ECMAErrors;
  63 import jdk.nashorn.internal.runtime.FindProperty;
  64 import jdk.nashorn.internal.runtime.GlobalConstants;
  65 import jdk.nashorn.internal.runtime.GlobalFunctions;
  66 import jdk.nashorn.internal.runtime.JSType;
  67 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  68 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  69 import jdk.nashorn.internal.runtime.PropertyMap;
  70 import jdk.nashorn.internal.runtime.Scope;
  71 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  72 import jdk.nashorn.internal.runtime.ScriptFunction;
  73 import jdk.nashorn.internal.runtime.ScriptObject;
  74 import jdk.nashorn.internal.runtime.ScriptRuntime;
  75 import jdk.nashorn.internal.runtime.ScriptingFunctions;
  76 import jdk.nashorn.internal.runtime.Specialization;
  77 import jdk.nashorn.internal.runtime.arrays.ArrayData;
  78 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  79 import jdk.nashorn.internal.runtime.linker.InvokeByName;
  80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  81 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
  82 import jdk.nashorn.internal.scripts.JD;
  83 import jdk.nashorn.internal.scripts.JO;
  84 import jdk.nashorn.tools.ShellFunctions;
  85 
  86 /**
  87  * Representation of global scope.
  88  */
  89 @ScriptClass("Global")
  90 public final class Global extends ScriptObject implements Scope {
  91     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
  92     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
  93     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  94     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  95 
  96     // placeholder value for lazily initialized global objects
  97     private static final Object LAZY_SENTINEL = new Object();
  98 
  99     /**
 100      * Optimistic builtin names that require switchpoint invalidation
 101      * upon assignment. Overly conservative, but works for now, to avoid
 102      * any complicated scope checks and especially heavy weight guards
 103      * like
 104      *
 105      * <pre>
 106      *     public boolean setterGuard(final Object receiver) {
 107      *         final Global          global = Global.instance();
 108      *         final ScriptObject    sobj   = global.getFunctionPrototype();
 109      *         final Object          apply  = sobj.get("apply");
 110      *         return apply == receiver;
 111      *     }
 112      * </pre>
 113      *
 114      * Naturally, checking for builtin classes like NativeFunction is cheaper,
 115      * it's when you start adding property checks for said builtins you have
 116      * problems with guard speed.
 117      */
 118 
 119     /** Nashorn extension: arguments array */
 120     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 121     public Object arguments;
 122 
 123     /** ECMA 15.1.2.2 parseInt (string , radix) */
 124     @Property(attributes = Attribute.NOT_ENUMERABLE)
 125     public Object parseInt;
 126 
 127     /** ECMA 15.1.2.3 parseFloat (string) */
 128     @Property(attributes = Attribute.NOT_ENUMERABLE)
 129     public Object parseFloat;
 130 
 131     /** ECMA 15.1.2.4 isNaN (number) */
 132     @Property(attributes = Attribute.NOT_ENUMERABLE)
 133     public Object isNaN;
 134 
 135     /** ECMA 15.1.2.5 isFinite (number) */
 136     @Property(attributes = Attribute.NOT_ENUMERABLE)
 137     public Object isFinite;
 138 
 139     /** ECMA 15.1.3.3 encodeURI */
 140     @Property(attributes = Attribute.NOT_ENUMERABLE)
 141     public Object encodeURI;
 142 
 143     /** ECMA 15.1.3.4 encodeURIComponent */
 144     @Property(attributes = Attribute.NOT_ENUMERABLE)
 145     public Object encodeURIComponent;
 146 
 147     /** ECMA 15.1.3.1 decodeURI */
 148     @Property(attributes = Attribute.NOT_ENUMERABLE)
 149     public Object decodeURI;
 150 
 151     /** ECMA 15.1.3.2 decodeURIComponent */
 152     @Property(attributes = Attribute.NOT_ENUMERABLE)
 153     public Object decodeURIComponent;
 154 
 155     /** ECMA B.2.1 escape (string) */
 156     @Property(attributes = Attribute.NOT_ENUMERABLE)
 157     public Object escape;
 158 
 159     /** ECMA B.2.2 unescape (string) */
 160     @Property(attributes = Attribute.NOT_ENUMERABLE)
 161     public Object unescape;
 162 
 163     /** Nashorn extension: global.print */
 164     @Property(attributes = Attribute.NOT_ENUMERABLE)
 165     public Object print;
 166 
 167     /** Nashorn extension: global.load */
 168     @Property(attributes = Attribute.NOT_ENUMERABLE)
 169     public Object load;
 170 
 171     /** Nashorn extension: global.loadWithNewGlobal */
 172     @Property(attributes = Attribute.NOT_ENUMERABLE)
 173     public Object loadWithNewGlobal;
 174 
 175     /** Nashorn extension: global.exit */
 176     @Property(attributes = Attribute.NOT_ENUMERABLE)
 177     public Object exit;
 178 
 179     /** Nashorn extension: global.quit */
 180     @Property(attributes = Attribute.NOT_ENUMERABLE)
 181     public Object quit;
 182 
 183     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 184     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 185     public final double NaN = Double.NaN;
 186 
 187     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 188     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 189     public final double Infinity = Double.POSITIVE_INFINITY;
 190 
 191     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 192     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 193     public final Object undefined = UNDEFINED;
 194 
 195     /** ECMA 15.1.2.1 eval(x) */
 196     @Property(attributes = Attribute.NOT_ENUMERABLE)
 197     public Object eval;
 198 
 199     /** ECMA 15.1.4.1 Object constructor. */
 200     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 201     public volatile Object object;
 202 
 203     /** ECMA 15.1.4.2 Function constructor. */
 204     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 205     public volatile Object function;
 206 
 207     /** ECMA 15.1.4.3 Array constructor. */
 208     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 209     public volatile Object array;
 210 
 211     /** ECMA 15.1.4.4 String constructor */
 212     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 213     public volatile Object string;
 214 
 215     /** ECMA 15.1.4.5 Boolean constructor */
 216     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 217     public volatile Object _boolean;
 218 
 219     /** ECMA 15.1.4.6 - Number constructor */
 220     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 221     public volatile Object number;
 222 
 223     /** ECMA 15.1.4.7 Date constructor */
 224     @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 225     public static Object getDate(final Object self) {
 226         final Global global = Global.instanceFrom(self);
 227         if (global.date == LAZY_SENTINEL) {
 228             global.date = global.getBuiltinDate();
 229         }
 230         return global.date;
 231     }
 232 
 233     @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 234     public static void setDate(final Object self, final Object value) {
 235         final Global global = Global.instanceFrom(self);
 236         global.date = value;
 237     }
 238 
 239     private volatile Object date = LAZY_SENTINEL;
 240 
 241     /** ECMA 15.1.4.8 RegExp constructor */
 242     @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 243     public static Object getRegExp(final Object self) {
 244         final Global global = Global.instanceFrom(self);
 245         if (global.regexp == LAZY_SENTINEL) {
 246             global.regexp = global.getBuiltinRegExp();
 247         }
 248         return global.regexp;
 249     }
 250 
 251     @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 252     public static void setRegExp(final Object self, final Object value) {
 253         final Global global = Global.instanceFrom(self);
 254         global.regexp = value;
 255     }
 256 
 257     private volatile Object regexp = LAZY_SENTINEL;
 258 
 259     /** ECMA 15.12 - The JSON object */
 260     @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 261     public static Object getJSON(final Object self) {
 262         final Global global = Global.instanceFrom(self);
 263         if (global.json == LAZY_SENTINEL) {
 264             global.json = global.getBuiltinJSON();
 265         }
 266         return global.json;
 267     }
 268 
 269     @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 270     public static void setJSON(final Object self, final Object value) {
 271         final Global global = Global.instanceFrom(self);
 272         global.json = value;
 273     }
 274 
 275     private volatile Object json = LAZY_SENTINEL;
 276 
 277     /** Nashorn extension: global.JSAdapter */
 278     @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 279     public static Object getJSAdapter(final Object self) {
 280         final Global global = Global.instanceFrom(self);
 281         if (global.jsadapter == LAZY_SENTINEL) {
 282             global.jsadapter = global.getBuiltinJSAdapter();
 283         }
 284         return global.jsadapter;
 285     }
 286 
 287     @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 288     public static void setJSAdapter(final Object self, final Object value) {
 289         final Global global = Global.instanceFrom(self);
 290         global.jsadapter = value;
 291     }
 292 
 293     private volatile Object jsadapter = LAZY_SENTINEL;
 294 
 295     /** ECMA 15.8 - The Math object */
 296     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
 297     public volatile Object math;
 298 
 299     /** Error object */
 300     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
 301     public volatile Object error;
 302 
 303     /** EvalError object */
 304     @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 305     public static Object getEvalError(final Object self) {
 306         final Global global = Global.instanceFrom(self);
 307         if (global.evalError == LAZY_SENTINEL) {
 308             global.evalError = global.getBuiltinEvalError();
 309         }
 310         return global.evalError;
 311     }
 312 
 313     @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 314     public static void setEvalError(final Object self, final Object value) {
 315         final Global global = Global.instanceFrom(self);
 316         global.evalError = value;
 317     }
 318 
 319     private volatile Object evalError = LAZY_SENTINEL;
 320 
 321     /** RangeError object */
 322     @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 323     public static Object getRangeError(final Object self) {
 324         final Global global = Global.instanceFrom(self);
 325         if (global.rangeError == LAZY_SENTINEL) {
 326             global.rangeError = global.getBuiltinRangeError();
 327         }
 328         return global.rangeError;
 329     }
 330 
 331     @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 332     public static void setRangeError(final Object self, final Object value) {
 333         final Global global = Global.instanceFrom(self);
 334         global.rangeError = value;
 335     }
 336 
 337     private volatile Object rangeError = LAZY_SENTINEL;
 338 
 339     /** ReferenceError object */
 340     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
 341     public volatile Object referenceError;
 342 
 343     /** SyntaxError object */
 344     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
 345     public volatile Object syntaxError;
 346 
 347     /** TypeError object */
 348     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
 349     public volatile Object typeError;
 350 
 351     /** URIError object */
 352     @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 353     public static Object getURIError(final Object self) {
 354         final Global global = Global.instanceFrom(self);
 355         if (global.uriError == LAZY_SENTINEL) {
 356             global.uriError = global.getBuiltinURIError();
 357         }
 358         return global.uriError;
 359     }
 360 
 361     @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 362     public static void setURIError(final Object self, final Object value) {
 363         final Global global = Global.instanceFrom(self);
 364         global.uriError = value;
 365     }
 366 
 367     private volatile Object uriError = LAZY_SENTINEL;
 368 
 369     /** ArrayBuffer object */
 370     @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 371     public static Object getArrayBuffer(final Object self) {
 372         final Global global = Global.instanceFrom(self);
 373         if (global.arrayBuffer == LAZY_SENTINEL) {
 374             global.arrayBuffer = global.getBuiltinArrayBuffer();
 375         }
 376         return global.arrayBuffer;
 377     }
 378 
 379     @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 380     public static void setArrayBuffer(final Object self, final Object value) {
 381         final Global global = Global.instanceFrom(self);
 382         global.arrayBuffer = value;
 383     }
 384 
 385     private volatile Object arrayBuffer;
 386 
 387     /** DataView object */
 388     @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 389     public static Object getDataView(final Object self) {
 390         final Global global = Global.instanceFrom(self);
 391         if (global.dataView == LAZY_SENTINEL) {
 392             global.dataView = global.getBuiltinDataView();
 393         }
 394         return global.dataView;
 395     }
 396 
 397     @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 398     public static void setDataView(final Object self, final Object value) {
 399         final Global global = Global.instanceFrom(self);
 400         global.dataView = value;
 401     }
 402 
 403     private volatile Object dataView;
 404 
 405     /** TypedArray (int8) */
 406     @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 407     public static Object getInt8Array(final Object self) {
 408         final Global global = Global.instanceFrom(self);
 409         if (global.int8Array == LAZY_SENTINEL) {
 410             global.int8Array = global.getBuiltinInt8Array();
 411         }
 412         return global.int8Array;
 413     }
 414 
 415     @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 416     public static void setInt8Array(final Object self, final Object value) {
 417         final Global global = Global.instanceFrom(self);
 418         global.int8Array = value;
 419     }
 420 
 421     private volatile Object int8Array;
 422 
 423     /** TypedArray (uint8) */
 424     @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 425     public static Object getUint8Array(final Object self) {
 426         final Global global = Global.instanceFrom(self);
 427         if (global.uint8Array == LAZY_SENTINEL) {
 428             global.uint8Array = global.getBuiltinUint8Array();
 429         }
 430         return global.uint8Array;
 431     }
 432 
 433     @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 434     public static void setUint8Array(final Object self, final Object value) {
 435         final Global global = Global.instanceFrom(self);
 436         global.uint8Array = value;
 437     }
 438 
 439     private volatile Object uint8Array;
 440 
 441     /** TypedArray (uint8) - Clamped */
 442     @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 443     public static Object getUint8ClampedArray(final Object self) {
 444         final Global global = Global.instanceFrom(self);
 445         if (global.uint8ClampedArray == LAZY_SENTINEL) {
 446             global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
 447         }
 448         return global.uint8ClampedArray;
 449     }
 450 
 451     @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 452     public static void setUint8ClampedArray(final Object self, final Object value) {
 453         final Global global = Global.instanceFrom(self);
 454         global.uint8ClampedArray = value;
 455     }
 456 
 457     private volatile Object uint8ClampedArray;
 458 
 459     /** TypedArray (int16) */
 460     @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 461     public static Object getInt16Array(final Object self) {
 462         final Global global = Global.instanceFrom(self);
 463         if (global.int16Array == LAZY_SENTINEL) {
 464             global.int16Array = global.getBuiltinInt16Array();
 465         }
 466         return global.int16Array;
 467     }
 468 
 469     @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 470     public static void setInt16Array(final Object self, final Object value) {
 471         final Global global = Global.instanceFrom(self);
 472         global.int16Array = value;
 473     }
 474 
 475     private volatile Object int16Array;
 476 
 477     /** TypedArray (uint16) */
 478     @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 479     public static Object getUint16Array(final Object self) {
 480         final Global global = Global.instanceFrom(self);
 481         if (global.uint16Array == LAZY_SENTINEL) {
 482             global.uint16Array = global.getBuiltinUint16Array();
 483         }
 484         return global.uint16Array;
 485     }
 486 
 487     @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 488     public static void setUint16Array(final Object self, final Object value) {
 489         final Global global = Global.instanceFrom(self);
 490         global.uint16Array = value;
 491     }
 492 
 493     private volatile Object uint16Array;
 494 
 495     /** TypedArray (int32) */
 496     @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 497     public static Object getInt32Array(final Object self) {
 498         final Global global = Global.instanceFrom(self);
 499         if (global.int32Array == LAZY_SENTINEL) {
 500             global.int32Array = global.getBuiltinInt32Array();
 501         }
 502         return global.int32Array;
 503     }
 504 
 505     @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 506     public static void setInt32Array(final Object self, final Object value) {
 507         final Global global = Global.instanceFrom(self);
 508         global.int32Array = value;
 509     }
 510 
 511     private volatile Object int32Array;
 512 
 513     /** TypedArray (uint32) */
 514     @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 515     public static Object getUint32Array(final Object self) {
 516         final Global global = Global.instanceFrom(self);
 517         if (global.uint32Array == LAZY_SENTINEL) {
 518             global.uint32Array = global.getBuiltinUint32Array();
 519         }
 520         return global.uint32Array;
 521     }
 522 
 523     @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 524     public static void setUint32Array(final Object self, final Object value) {
 525         final Global global = Global.instanceFrom(self);
 526         global.uint32Array = value;
 527     }
 528 
 529     private volatile Object uint32Array;
 530 
 531     /** TypedArray (float32) */
 532     @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 533     public static Object getFloat32Array(final Object self) {
 534         final Global global = Global.instanceFrom(self);
 535         if (global.float32Array == LAZY_SENTINEL) {
 536             global.float32Array = global.getBuiltinFloat32Array();
 537         }
 538         return global.float32Array;
 539     }
 540 
 541     @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 542     public static void setFloat32Array(final Object self, final Object value) {
 543         final Global global = Global.instanceFrom(self);
 544         global.float32Array = value;
 545     }
 546 
 547     private volatile Object float32Array;
 548 
 549     /** TypedArray (float64) */
 550     @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 551     public static Object getFloat64Array(final Object self) {
 552         final Global global = Global.instanceFrom(self);
 553         if (global.float64Array == LAZY_SENTINEL) {
 554             global.float64Array = global.getBuiltinFloat64Array();
 555         }
 556         return global.float64Array;
 557     }
 558 
 559     @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 560     public static void setFloat64Array(final Object self, final Object value) {
 561         final Global global = Global.instanceFrom(self);
 562         global.float64Array = value;
 563     }
 564 
 565     private volatile Object float64Array;
 566 
 567     /** Nashorn extension: Java access - global.Packages */
 568     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 569     public volatile Object packages;
 570 
 571     /** Nashorn extension: Java access - global.com */
 572     @Property(attributes = Attribute.NOT_ENUMERABLE)
 573     public volatile Object com;
 574 
 575     /** Nashorn extension: Java access - global.edu */
 576     @Property(attributes = Attribute.NOT_ENUMERABLE)
 577     public volatile Object edu;
 578 
 579     /** Nashorn extension: Java access - global.java */
 580     @Property(attributes = Attribute.NOT_ENUMERABLE)
 581     public volatile Object java;
 582 
 583     /** Nashorn extension: Java access - global.javafx */
 584     @Property(attributes = Attribute.NOT_ENUMERABLE)
 585     public volatile Object javafx;
 586 
 587     /** Nashorn extension: Java access - global.javax */
 588     @Property(attributes = Attribute.NOT_ENUMERABLE)
 589     public volatile Object javax;
 590 
 591     /** Nashorn extension: Java access - global.org */
 592     @Property(attributes = Attribute.NOT_ENUMERABLE)
 593     public volatile Object org;
 594 
 595     /** Nashorn extension: Java access - global.javaImporter */
 596     @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 597     public static Object getJavaImporter(final Object self) {
 598         final Global global = Global.instanceFrom(self);
 599         if (global.javaImporter == LAZY_SENTINEL) {
 600             global.javaImporter = global.getBuiltinJavaImporter();
 601         }
 602         return global.javaImporter;
 603     }
 604 
 605     @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 606     public static void setJavaImporter(final Object self, final Object value) {
 607         final Global global = Global.instanceFrom(self);
 608         global.javaImporter = value;
 609     }
 610 
 611     private volatile Object javaImporter;
 612 
 613     /** Nashorn extension: global.Java Object constructor. */
 614     @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 615     public static Object getJavaApi(final Object self) {
 616         final Global global = Global.instanceFrom(self);
 617         if (global.javaApi == LAZY_SENTINEL) {
 618             global.javaApi = global.getBuiltinJavaApi();
 619         }
 620         return global.javaApi;
 621     }
 622 
 623     @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 624     public static void setJavaApi(final Object self, final Object value) {
 625         final Global global = Global.instanceFrom(self);
 626         global.javaApi = value;
 627     }
 628 
 629     private volatile Object javaApi;
 630 
 631     /** Nashorn extension: current script's file name */
 632     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 633     public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 634 
 635     /** Nashorn extension: current script's directory */
 636     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 637     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 638 
 639     /** Nashorn extension: current source line number being executed */
 640     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 641     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 642 
 643     private volatile NativeDate DEFAULT_DATE;
 644 
 645     /** Used as Date.prototype's default value */
 646     NativeDate getDefaultDate() {
 647         return DEFAULT_DATE;
 648     }
 649 
 650     private volatile NativeRegExp DEFAULT_REGEXP;
 651 
 652     /** Used as RegExp.prototype's default value */
 653     NativeRegExp getDefaultRegExp() {
 654         return DEFAULT_REGEXP;
 655     }
 656 
 657     /*
 658      * Built-in constructor objects: Even if user changes dynamic values of
 659      * "Object", "Array" etc., we still want to keep original values of these
 660      * constructors here. For example, we need to be able to create array,
 661      * regexp literals even after user overwrites global "Array" or "RegExp"
 662      * constructor - see also ECMA 262 spec. Annex D.
 663      */
 664     private ScriptFunction builtinFunction;
 665     private ScriptFunction builtinObject;
 666     private ScriptFunction builtinArray;
 667     private ScriptFunction builtinBoolean;
 668     private ScriptFunction builtinDate;
 669     private ScriptObject   builtinJSON;
 670     private ScriptFunction builtinJSAdapter;
 671     private ScriptObject   builtinMath;
 672     private ScriptFunction builtinNumber;
 673     private ScriptFunction builtinRegExp;
 674     private ScriptFunction builtinString;
 675     private ScriptFunction builtinError;
 676     private ScriptFunction builtinEval;
 677     private ScriptFunction builtinEvalError;
 678     private ScriptFunction builtinRangeError;
 679     private ScriptFunction builtinReferenceError;
 680     private ScriptFunction builtinSyntaxError;
 681     private ScriptFunction builtinTypeError;
 682     private ScriptFunction builtinURIError;
 683     private ScriptObject   builtinPackages;
 684     private ScriptObject   builtinCom;
 685     private ScriptObject   builtinEdu;
 686     private ScriptObject   builtinJava;
 687     private ScriptObject   builtinJavafx;
 688     private ScriptObject   builtinJavax;
 689     private ScriptObject   builtinOrg;
 690     private ScriptFunction builtinJavaImporter;
 691     private ScriptObject   builtinJavaApi;
 692     private ScriptFunction builtinArrayBuffer;
 693     private ScriptFunction builtinDataView;
 694     private ScriptFunction builtinInt8Array;
 695     private ScriptFunction builtinUint8Array;
 696     private ScriptFunction builtinUint8ClampedArray;
 697     private ScriptFunction builtinInt16Array;
 698     private ScriptFunction builtinUint16Array;
 699     private ScriptFunction builtinInt32Array;
 700     private ScriptFunction builtinUint32Array;
 701     private ScriptFunction builtinFloat32Array;
 702     private ScriptFunction builtinFloat64Array;
 703 
 704     /*
 705      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 706      */
 707     private ScriptFunction typeErrorThrower;
 708 
 709     // Flag to indicate that a split method issued a return statement
 710     private int splitState = -1;
 711 
 712     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 713     private RegExpResult lastRegExpResult;
 714 
 715     private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
 716     private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
 717     private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
 718     private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
 719     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
 720     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
 721     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
 722     private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
 723 
 724     // initialized by nasgen
 725     private static PropertyMap $nasgenmap$;
 726 
 727     // context to which this global belongs to
 728     private final Context context;
 729 
 730     // current ScriptContext to use - can be null.
 731     private ScriptContext scontext;
 732     // current ScriptEngine associated - can be null.
 733     private ScriptEngine engine;
 734 
 735     // ES6 global lexical scope.
 736     private final LexicalScope lexicalScope;
 737 
 738     // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
 739     private SwitchPoint lexicalScopeSwitchPoint;
 740 
 741     /**
 742      * Set the current script context
 743      * @param scontext script context
 744      */
 745     public void setScriptContext(final ScriptContext scontext) {
 746         this.scontext = scontext;
 747     }
 748 
 749     @Override
 750     protected Context getContext() {
 751         return context;
 752     }
 753 
 754     @Override
 755     protected boolean useDualFields() {
 756         return context.useDualFields();
 757     }
 758 
 759     // performs initialization checks for Global constructor and returns the
 760     // PropertyMap, if everything is fine.
 761     private static PropertyMap checkAndGetMap(final Context context) {
 762         // security check first
 763         final SecurityManager sm = System.getSecurityManager();
 764         if (sm != null) {
 765             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 766         }
 767 
 768         Objects.requireNonNull(context);
 769 
 770         return $nasgenmap$;
 771     }
 772 
 773     /**
 774      * Constructor
 775      *
 776      * @param context the context
 777      */
 778     public Global(final Context context) {
 779         super(checkAndGetMap(context));
 780         this.context = context;
 781         this.setIsScope();
 782         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
 783     }
 784 
 785     /**
 786      * Script access to "current" Global instance
 787      *
 788      * @return the global singleton
 789      */
 790     public static Global instance() {
 791         final Global global = Context.getGlobal();
 792         Objects.requireNonNull(global);
 793         return global;
 794     }
 795 
 796     private static Global instanceFrom(final Object self) {
 797         return self instanceof Global? (Global)self : instance();
 798     }
 799 
 800     /**
 801      * Check if we have a Global instance
 802      * @return true if one exists
 803      */
 804     public static boolean hasInstance() {
 805         return Context.getGlobal() != null;
 806     }
 807 
 808     /**
 809      * Script access to {@link ScriptEnvironment}
 810      *
 811      * @return the script environment
 812      */
 813     static ScriptEnvironment getEnv() {
 814         return instance().getContext().getEnv();
 815     }
 816 
 817     /**
 818      * Script access to {@link Context}
 819      *
 820      * @return the context
 821      */
 822     static Context getThisContext() {
 823         return instance().getContext();
 824     }
 825 
 826     // Runtime interface to Global
 827 
 828     /**
 829      * Is there a class filter in the current Context?
 830      * @return class filter
 831      */
 832     public ClassFilter getClassFilter() {
 833         return context.getClassFilter();
 834     }
 835 
 836     /**
 837      * Is this global of the given Context?
 838      * @param ctxt the context
 839      * @return true if this global belongs to the given Context
 840      */
 841     public boolean isOfContext(final Context ctxt) {
 842         return this.context == ctxt;
 843     }
 844 
 845     /**
 846      * Does this global belong to a strict Context?
 847      * @return true if this global belongs to a strict Context
 848      */
 849     public boolean isStrictContext() {
 850         return context.getEnv()._strict;
 851     }
 852 
 853     /**
 854      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
 855      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
 856      * of the global scope object.
 857      *
 858      * @param engine ScriptEngine to initialize
 859      */
 860     @SuppressWarnings("hiding")
 861     public void initBuiltinObjects(final ScriptEngine engine) {
 862         if (this.builtinObject != null) {
 863             // already initialized, just return
 864             return;
 865         }
 866 
 867         this.engine = engine;
 868         init(engine);
 869     }
 870 
 871     /**
 872      * Wrap a Java object as corresponding script object
 873      *
 874      * @param obj object to wrap
 875      * @return    wrapped object
 876      */
 877     public Object wrapAsObject(final Object obj) {
 878         if (obj instanceof Boolean) {
 879             return new NativeBoolean((Boolean)obj, this);
 880         } else if (obj instanceof Number) {
 881             return new NativeNumber(((Number)obj).doubleValue(), this);
 882         } else if (isString(obj)) {
 883             return new NativeString((CharSequence)obj, this);
 884         } else if (obj instanceof Object[]) { // extension
 885             return new NativeArray(ArrayData.allocate((Object[])obj), this);
 886         } else if (obj instanceof double[]) { // extension
 887             return new NativeArray(ArrayData.allocate((double[])obj), this);
 888         } else if (obj instanceof long[]) {
 889             return new NativeArray(ArrayData.allocate((long[])obj), this);
 890         } else if (obj instanceof int[]) {
 891             return new NativeArray(ArrayData.allocate((int[]) obj), this);
 892         } else if (obj instanceof ArrayData) {
 893             return new NativeArray((ArrayData) obj, this);
 894         } else {
 895             // FIXME: more special cases? Map? List?
 896             return obj;
 897         }
 898     }
 899 
 900     /**
 901      * Lookup helper for JS primitive types
 902      *
 903      * @param request the link request for the dynamic call site.
 904      * @param self     self reference
 905      *
 906      * @return guarded invocation
 907      */
 908     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
 909         if (isString(self)) {
 910             return NativeString.lookupPrimitive(request, self);
 911         } else if (self instanceof Number) {
 912             return NativeNumber.lookupPrimitive(request, self);
 913         } else if (self instanceof Boolean) {
 914             return NativeBoolean.lookupPrimitive(request, self);
 915         }
 916         throw new IllegalArgumentException("Unsupported primitive: " + self);
 917     }
 918 
 919     /**
 920      * Returns a method handle that creates a wrapper object for a JS primitive value.
 921      *
 922      * @param self receiver object
 923      * @return method handle to create wrapper objects for primitive receiver
 924      */
 925     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
 926         if (isString(self)) {
 927             return NativeString.WRAPFILTER;
 928         } else if (self instanceof Number) {
 929             return NativeNumber.WRAPFILTER;
 930         } else if (self instanceof Boolean) {
 931             return NativeBoolean.WRAPFILTER;
 932         }
 933         throw new IllegalArgumentException("Unsupported primitive: " + self);
 934     }
 935 
 936 
 937     /**
 938      * Create a new empty script object
 939      *
 940      * @return the new ScriptObject
 941      */
 942     public ScriptObject newObject() {
 943         return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
 944     }
 945 
 946     /**
 947      * Default value of given type
 948      *
 949      * @param sobj     script object
 950      * @param typeHint type hint
 951      *
 952      * @return default value
 953      */
 954     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
 955         // When the [[DefaultValue]] internal method of O is called with no hint,
 956         // then it behaves as if the hint were Number, unless O is a Date object
 957         // in which case it behaves as if the hint were String.
 958         Class<?> hint = typeHint;
 959         if (hint == null) {
 960             hint = Number.class;
 961         }
 962 
 963         try {
 964             if (hint == String.class) {
 965 
 966                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 967 
 968                 if (Bootstrap.isCallable(toString)) {
 969                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 970                     if (JSType.isPrimitive(value)) {
 971                         return value;
 972                     }
 973                 }
 974 
 975                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 976                 if (Bootstrap.isCallable(valueOf)) {
 977                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 978                     if (JSType.isPrimitive(value)) {
 979                         return value;
 980                     }
 981                 }
 982                 throw typeError(this, "cannot.get.default.string");
 983             }
 984 
 985             if (hint == Number.class) {
 986                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 987                 if (Bootstrap.isCallable(valueOf)) {
 988                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 989                     if (JSType.isPrimitive(value)) {
 990                         return value;
 991                     }
 992                 }
 993 
 994                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 995                 if (Bootstrap.isCallable(toString)) {
 996                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 997                     if (JSType.isPrimitive(value)) {
 998                         return value;
 999                     }
1000                 }
1001 
1002                 throw typeError(this, "cannot.get.default.number");
1003             }
1004         } catch (final RuntimeException | Error e) {
1005             throw e;
1006         } catch (final Throwable t) {
1007             throw new RuntimeException(t);
1008         }
1009 
1010         return UNDEFINED;
1011     }
1012 
1013     /**
1014      * Is the given ScriptObject an ECMAScript Error object?
1015      *
1016      * @param sobj the object being checked
1017      * @return true if sobj is an Error object
1018      */
1019     public boolean isError(final ScriptObject sobj) {
1020         final ScriptObject errorProto = getErrorPrototype();
1021         ScriptObject proto = sobj.getProto();
1022         while (proto != null) {
1023             if (proto == errorProto) {
1024                 return true;
1025             }
1026             proto = proto.getProto();
1027         }
1028         return false;
1029     }
1030 
1031     /**
1032      * Create a new ECMAScript Error object.
1033      *
1034      * @param msg error message
1035      * @return newly created Error object
1036      */
1037     public ScriptObject newError(final String msg) {
1038         return new NativeError(msg, this);
1039     }
1040 
1041     /**
1042      * Create a new ECMAScript EvalError object.
1043      *
1044      * @param msg error message
1045      * @return newly created EvalError object
1046      */
1047     public ScriptObject newEvalError(final String msg) {
1048         return new NativeEvalError(msg, this);
1049     }
1050 
1051     /**
1052      * Create a new ECMAScript RangeError object.
1053      *
1054      * @param msg error message
1055      * @return newly created RangeError object
1056      */
1057     public ScriptObject newRangeError(final String msg) {
1058         return new NativeRangeError(msg, this);
1059     }
1060 
1061     /**
1062      * Create a new ECMAScript ReferenceError object.
1063      *
1064      * @param msg error message
1065      * @return newly created ReferenceError object
1066      */
1067     public ScriptObject newReferenceError(final String msg) {
1068         return new NativeReferenceError(msg, this);
1069     }
1070 
1071     /**
1072      * Create a new ECMAScript SyntaxError object.
1073      *
1074      * @param msg error message
1075      * @return newly created SyntaxError object
1076      */
1077     public ScriptObject newSyntaxError(final String msg) {
1078         return new NativeSyntaxError(msg, this);
1079     }
1080 
1081     /**
1082      * Create a new ECMAScript TypeError object.
1083      *
1084      * @param msg error message
1085      * @return newly created TypeError object
1086      */
1087     public ScriptObject newTypeError(final String msg) {
1088         return new NativeTypeError(msg, this);
1089     }
1090 
1091     /**
1092      * Create a new ECMAScript URIError object.
1093      *
1094      * @param msg error message
1095      * @return newly created URIError object
1096      */
1097     public ScriptObject newURIError(final String msg) {
1098         return new NativeURIError(msg, this);
1099     }
1100 
1101     /**
1102      * Create a new ECMAScript GenericDescriptor object.
1103      *
1104      * @param configurable is the property configurable?
1105      * @param enumerable is the property enumerable?
1106      * @return newly created GenericDescriptor object
1107      */
1108     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1109         return new GenericPropertyDescriptor(configurable, enumerable, this);
1110     }
1111 
1112     /**
1113      * Create a new ECMAScript DatePropertyDescriptor object.
1114      *
1115      * @param value of the data property
1116      * @param configurable is the property configurable?
1117      * @param enumerable is the property enumerable?
1118      * @param writable is the property writable?
1119      * @return newly created DataPropertyDescriptor object
1120      */
1121     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1122         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1123     }
1124 
1125     /**
1126      * Create a new ECMAScript AccessorPropertyDescriptor object.
1127      *
1128      * @param get getter function of the user accessor property
1129      * @param set setter function of the user accessor property
1130      * @param configurable is the property configurable?
1131      * @param enumerable is the property enumerable?
1132      * @return newly created AccessorPropertyDescriptor object
1133      */
1134     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1135         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1136 
1137         if (get == null) {
1138             desc.delete(PropertyDescriptor.GET, false);
1139         }
1140 
1141         if (set == null) {
1142             desc.delete(PropertyDescriptor.SET, false);
1143         }
1144 
1145         return desc;
1146     }
1147 
1148     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1149         final T obj = map.get(key);
1150         if (obj != null) {
1151             return obj;
1152         }
1153 
1154         try {
1155             final T newObj = creator.call();
1156             final T existingObj = map.putIfAbsent(key, newObj);
1157             return existingObj != null ? existingObj : newObj;
1158         } catch (final Exception exp) {
1159             throw new RuntimeException(exp);
1160         }
1161     }
1162 
1163     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1164 
1165 
1166     /**
1167      * Get cached InvokeByName object for the given key
1168      * @param key key to be associated with InvokeByName object
1169      * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1170      * @return InvokeByName object associated with the key.
1171      */
1172     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1173         return getLazilyCreatedValue(key, creator, namedInvokers);
1174     }
1175 
1176     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1177 
1178     /**
1179      * Get cached dynamic method handle for the given key
1180      * @param key key to be associated with dynamic method handle
1181      * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1182      * @return dynamic method handle associated with the key.
1183      */
1184     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1185         return getLazilyCreatedValue(key, creator, dynamicInvokers);
1186     }
1187 
1188     /**
1189      * Hook to search missing variables in ScriptContext if available
1190      * @param self used to detect if scope call or not (this function is 'strict')
1191      * @param name name of the variable missing
1192      * @return value of the missing variable or undefined (or TypeError for scope search)
1193      */
1194     public static Object __noSuchProperty__(final Object self, final Object name) {
1195         final Global global = Global.instance();
1196         final ScriptContext sctxt = global.scontext;
1197         final String nameStr = name.toString();
1198 
1199         if (sctxt != null) {
1200             final int scope = sctxt.getAttributesScope(nameStr);
1201             if (scope != -1) {
1202                 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1203             }
1204         }
1205 
1206         switch (nameStr) {
1207         case "context":
1208             return sctxt;
1209         case "engine":
1210             return global.engine;
1211         default:
1212             break;
1213         }
1214 
1215         if (self == UNDEFINED) {
1216             // scope access and so throw ReferenceError
1217             throw referenceError(global, "not.defined", nameStr);
1218         }
1219 
1220         return UNDEFINED;
1221     }
1222 
1223     /**
1224      * This is the eval used when 'indirect' eval call is made.
1225      *
1226      * var global = this;
1227      * global.eval("print('hello')");
1228      *
1229      * @param self  eval scope
1230      * @param str   eval string
1231      *
1232      * @return the result of eval
1233      */
1234     public static Object eval(final Object self, final Object str) {
1235         return directEval(self, str, UNDEFINED, UNDEFINED, false);
1236     }
1237 
1238     /**
1239      * Direct eval
1240      *
1241      * @param self     The scope of eval passed as 'self'
1242      * @param str      Evaluated code
1243      * @param callThis "this" to be passed to the evaluated code
1244      * @param location location of the eval call
1245      * @param strict   is eval called a strict mode code?
1246      *
1247      * @return the return value of the eval
1248      *
1249      * This is directly invoked from generated when eval(code) is called in user code
1250      */
1251     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1252         if (!isString(str)) {
1253             return str;
1254         }
1255         final Global global = Global.instanceFrom(self);
1256         final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1257 
1258         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1259     }
1260 
1261     /**
1262      * Global print implementation - Nashorn extension
1263      *
1264      * @param self    scope
1265      * @param objects arguments to print
1266      *
1267      * @return result of print (undefined)
1268      */
1269     public static Object print(final Object self, final Object... objects) {
1270         return Global.instanceFrom(self).printImpl(false, objects);
1271     }
1272 
1273     /**
1274      * Global println implementation - Nashorn extension
1275      *
1276      * @param self    scope
1277      * @param objects arguments to print
1278      *
1279      * @return result of println (undefined)
1280      */
1281     public static Object println(final Object self, final Object... objects) {
1282         return Global.instanceFrom(self).printImpl(true, objects);
1283     }
1284 
1285     /**
1286      * Global load implementation - Nashorn extension
1287      *
1288      * @param self    scope
1289      * @param source  source to load
1290      *
1291      * @return result of load (undefined)
1292      *
1293      * @throws IOException if source could not be read
1294      */
1295     public static Object load(final Object self, final Object source) throws IOException {
1296         final Global global = Global.instanceFrom(self);
1297         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
1298         return global.getContext().load(scope, source);
1299     }
1300 
1301     /**
1302      * Global loadWithNewGlobal implementation - Nashorn extension
1303      *
1304      * @param self scope
1305      * @param args from plus (optional) arguments to be passed to the loaded script
1306      *
1307      * @return result of load (may be undefined)
1308      *
1309      * @throws IOException if source could not be read
1310      */
1311     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1312         final Global global = Global.instanceFrom(self);
1313         final int length = args.length;
1314         final boolean hasArgs = 0 < length;
1315         final Object from = hasArgs ? args[0] : UNDEFINED;
1316         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1317 
1318         return global.getContext().loadWithNewGlobal(from, arguments);
1319     }
1320 
1321     /**
1322      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1323      *
1324      * @param self  self reference
1325      * @param code  exit code
1326      *
1327      * @return undefined (will never be reached)
1328      */
1329     public static Object exit(final Object self, final Object code) {
1330         System.exit(JSType.toInt32(code));
1331         return UNDEFINED;
1332     }
1333 
1334     // builtin prototype accessors
1335 
1336     /**
1337      * Get the builtin Object prototype.
1338      * @return the object prototype.
1339      */
1340     public ScriptObject getObjectPrototype() {
1341         return ScriptFunction.getPrototype(builtinObject);
1342     }
1343 
1344     ScriptObject getFunctionPrototype() {
1345         return ScriptFunction.getPrototype(builtinFunction);
1346     }
1347 
1348     ScriptObject getArrayPrototype() {
1349         return ScriptFunction.getPrototype(builtinArray);
1350     }
1351 
1352     ScriptObject getBooleanPrototype() {
1353         return ScriptFunction.getPrototype(builtinBoolean);
1354     }
1355 
1356     ScriptObject getNumberPrototype() {
1357         return ScriptFunction.getPrototype(builtinNumber);
1358     }
1359 
1360     ScriptObject getDatePrototype() {
1361         return ScriptFunction.getPrototype(getBuiltinDate());
1362     }
1363 
1364     ScriptObject getRegExpPrototype() {
1365         return ScriptFunction.getPrototype(getBuiltinRegExp());
1366     }
1367 
1368     ScriptObject getStringPrototype() {
1369         return ScriptFunction.getPrototype(builtinString);
1370     }
1371 
1372     ScriptObject getErrorPrototype() {
1373         return ScriptFunction.getPrototype(builtinError);
1374     }
1375 
1376     ScriptObject getEvalErrorPrototype() {
1377         return ScriptFunction.getPrototype(getBuiltinEvalError());
1378     }
1379 
1380     ScriptObject getRangeErrorPrototype() {
1381         return ScriptFunction.getPrototype(getBuiltinRangeError());
1382     }
1383 
1384     ScriptObject getReferenceErrorPrototype() {
1385         return ScriptFunction.getPrototype(builtinReferenceError);
1386     }
1387 
1388     ScriptObject getSyntaxErrorPrototype() {
1389         return ScriptFunction.getPrototype(builtinSyntaxError);
1390     }
1391 
1392     ScriptObject getTypeErrorPrototype() {
1393         return ScriptFunction.getPrototype(builtinTypeError);
1394     }
1395 
1396     ScriptObject getURIErrorPrototype() {
1397         return ScriptFunction.getPrototype(getBuiltinURIError());
1398     }
1399 
1400     ScriptObject getJavaImporterPrototype() {
1401         return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1402     }
1403 
1404     ScriptObject getJSAdapterPrototype() {
1405         return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1406     }
1407 
1408     private synchronized ScriptFunction getBuiltinArrayBuffer() {
1409         if (this.builtinArrayBuffer == null) {
1410             this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1411         }
1412         return this.builtinArrayBuffer;
1413     }
1414 
1415     ScriptObject getArrayBufferPrototype() {
1416         return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1417     }
1418 
1419     private synchronized ScriptFunction getBuiltinDataView() {
1420         if (this.builtinDataView == null) {
1421             this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1422         }
1423         return this.builtinDataView;
1424     }
1425 
1426     ScriptObject getDataViewPrototype() {
1427         return ScriptFunction.getPrototype(getBuiltinDataView());
1428     }
1429 
1430     private synchronized ScriptFunction getBuiltinInt8Array() {
1431         if (this.builtinInt8Array == null) {
1432             this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1433         }
1434         return this.builtinInt8Array;
1435     }
1436 
1437     ScriptObject getInt8ArrayPrototype() {
1438         return ScriptFunction.getPrototype(getBuiltinInt8Array());
1439     }
1440 
1441     private synchronized ScriptFunction getBuiltinUint8Array() {
1442         if (this.builtinUint8Array == null) {
1443             this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1444         }
1445         return this.builtinUint8Array;
1446     }
1447 
1448     ScriptObject getUint8ArrayPrototype() {
1449         return ScriptFunction.getPrototype(getBuiltinUint8Array());
1450     }
1451 
1452     private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1453         if (this.builtinUint8ClampedArray == null) {
1454             this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1455         }
1456         return this.builtinUint8ClampedArray;
1457     }
1458 
1459     ScriptObject getUint8ClampedArrayPrototype() {
1460         return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1461     }
1462 
1463     private synchronized ScriptFunction getBuiltinInt16Array() {
1464         if (this.builtinInt16Array == null) {
1465             this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1466         }
1467         return this.builtinInt16Array;
1468     }
1469 
1470     ScriptObject getInt16ArrayPrototype() {
1471         return ScriptFunction.getPrototype(getBuiltinInt16Array());
1472     }
1473 
1474     private synchronized ScriptFunction getBuiltinUint16Array() {
1475         if (this.builtinUint16Array == null) {
1476             this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1477         }
1478         return this.builtinUint16Array;
1479     }
1480 
1481     ScriptObject getUint16ArrayPrototype() {
1482         return ScriptFunction.getPrototype(getBuiltinUint16Array());
1483     }
1484 
1485     private synchronized ScriptFunction getBuiltinInt32Array() {
1486         if (this.builtinInt32Array == null) {
1487             this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1488         }
1489         return this.builtinInt32Array;
1490     }
1491 
1492     ScriptObject getInt32ArrayPrototype() {
1493         return ScriptFunction.getPrototype(getBuiltinInt32Array());
1494     }
1495 
1496     private synchronized ScriptFunction getBuiltinUint32Array() {
1497         if (this.builtinUint32Array == null) {
1498             this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1499         }
1500         return this.builtinUint32Array;
1501     }
1502 
1503     ScriptObject getUint32ArrayPrototype() {
1504         return ScriptFunction.getPrototype(getBuiltinUint32Array());
1505     }
1506 
1507     private synchronized ScriptFunction getBuiltinFloat32Array() {
1508         if (this.builtinFloat32Array == null) {
1509             this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1510         }
1511         return this.builtinFloat32Array;
1512     }
1513 
1514     ScriptObject getFloat32ArrayPrototype() {
1515         return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1516     }
1517 
1518     private synchronized ScriptFunction getBuiltinFloat64Array() {
1519         if (this.builtinFloat64Array == null) {
1520             this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1521         }
1522         return this.builtinFloat64Array;
1523     }
1524 
1525     ScriptObject getFloat64ArrayPrototype() {
1526         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1527     }
1528 
1529     private ScriptFunction getBuiltinArray() {
1530         return builtinArray;
1531     }
1532 
1533     ScriptFunction getTypeErrorThrower() {
1534         return typeErrorThrower;
1535     }
1536 
1537     /**
1538      * Called from compiled script code to test if builtin has been overridden
1539      *
1540      * @return true if builtin array has not been overridden
1541      */
1542     public static boolean isBuiltinArray() {
1543         final Global instance = Global.instance();
1544         return instance.array == instance.getBuiltinArray();
1545     }
1546 
1547     private ScriptFunction getBuiltinBoolean() {
1548         return builtinBoolean;
1549     }
1550 
1551     /**
1552      * Called from compiled script code to test if builtin has been overridden
1553      *
1554      * @return true if builtin boolean has not been overridden
1555      */
1556     public static boolean isBuiltinBoolean() {
1557         final Global instance = Global.instance();
1558         return instance._boolean == instance.getBuiltinBoolean();
1559     }
1560 
1561     private synchronized ScriptFunction getBuiltinDate() {
1562         if (this.builtinDate == null) {
1563             this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1564             final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
1565             // initialize default date
1566             this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
1567         }
1568         return this.builtinDate;
1569     }
1570 
1571     /**
1572      * Called from compiled script code to test if builtin has been overridden
1573      *
1574      * @return true if builtin date has not been overridden
1575      */
1576     public static boolean isBuiltinDate() {
1577         final Global instance = Global.instance();
1578         return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
1579     }
1580 
1581     private ScriptFunction getBuiltinError() {
1582         return builtinError;
1583     }
1584 
1585     /**
1586      * Called from compiled script code to test if builtin has been overridden
1587      *
1588      * @return true if builtin error has not been overridden
1589      */
1590     public static boolean isBuiltinError() {
1591         final Global instance = Global.instance();
1592         return instance.error == instance.getBuiltinError();
1593     }
1594 
1595     private synchronized ScriptFunction getBuiltinEvalError() {
1596         if (this.builtinEvalError == null) {
1597             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
1598         }
1599         return this.builtinEvalError;
1600     }
1601 
1602     /**
1603      * Called from compiled script code to test if builtin has been overridden
1604      *
1605      * @return true if builtin eval error has not been overridden
1606      */
1607     public static boolean isBuiltinEvalError() {
1608         final Global instance = Global.instance();
1609         return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
1610     }
1611 
1612     private ScriptFunction getBuiltinFunction() {
1613         return builtinFunction;
1614     }
1615 
1616     /**
1617      * Called from compiled script code to test if builtin has been overridden
1618      *
1619      * @return true if builtin function has not been overridden
1620      */
1621     public static boolean isBuiltinFunction() {
1622         final Global instance = Global.instance();
1623         return instance.function == instance.getBuiltinFunction();
1624     }
1625 
1626     /**
1627      * Get the switchpoint used to check property changes for Function.prototype.apply
1628      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1629      */
1630     public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1631         return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1632     }
1633 
1634     private static boolean isBuiltinFunctionProperty(final String name) {
1635         final Global instance = Global.instance();
1636         final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1637         if (builtinFunction == null) {
1638             return false; //conservative for compile-only mode
1639         }
1640         final boolean isBuiltinFunction = instance.function == builtinFunction;
1641         return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1642     }
1643 
1644     /**
1645      * Check if the Function.prototype.apply has not been replaced
1646      * @return true if Function.prototype.apply has been replaced
1647      */
1648     public static boolean isBuiltinFunctionPrototypeApply() {
1649         return isBuiltinFunctionProperty("apply");
1650     }
1651 
1652     /**
1653      * Check if the Function.prototype.apply has not been replaced
1654      * @return true if Function.prototype.call has been replaced
1655      */
1656     public static boolean isBuiltinFunctionPrototypeCall() {
1657         return isBuiltinFunctionProperty("call");
1658     }
1659 
1660     private synchronized ScriptFunction getBuiltinJSAdapter() {
1661         if (this.builtinJSAdapter == null) {
1662             this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1663         }
1664         return builtinJSAdapter;
1665     }
1666 
1667     /**
1668      * Called from compiled script code to test if builtin has been overridden
1669      *
1670      * @return true if builtin JSAdapter has not been overridden
1671      */
1672     public static boolean isBuiltinJSAdapter() {
1673         final Global instance = Global.instance();
1674         return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
1675     }
1676 
1677     private synchronized ScriptObject getBuiltinJSON() {
1678         if (this.builtinJSON == null) {
1679             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1680         }
1681         return this.builtinJSON;
1682     }
1683 
1684     /**
1685      * Called from compiled script code to test if builtin has been overridden
1686      *
1687      * @return true if builtin JSON has has not been overridden
1688      */
1689     public static boolean isBuiltinJSON() {
1690         final Global instance = Global.instance();
1691         return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
1692     }
1693 
1694     private ScriptObject getBuiltinJava() {
1695         return builtinJava;
1696     }
1697 
1698     /**
1699      * Called from compiled script code to test if builtin has been overridden
1700      *
1701      * @return true if builtin Java has not been overridden
1702      */
1703     public static boolean isBuiltinJava() {
1704         final Global instance = Global.instance();
1705         return instance.java == instance.getBuiltinJava();
1706     }
1707 
1708     private ScriptObject getBuiltinJavax() {
1709         return builtinJavax;
1710     }
1711 
1712     /**
1713      * Called from compiled script code to test if builtin has been overridden
1714      *
1715      * @return true if builtin Javax has not been overridden
1716      */
1717     public static boolean isBuiltinJavax() {
1718         final Global instance = Global.instance();
1719         return instance.javax == instance.getBuiltinJavax();
1720     }
1721 
1722     private synchronized ScriptFunction getBuiltinJavaImporter() {
1723         if (this.builtinJavaImporter == null) {
1724             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1725         }
1726         return this.builtinJavaImporter;
1727     }
1728 
1729     private synchronized ScriptObject getBuiltinJavaApi() {
1730         if (this.builtinJavaApi == null) {
1731             this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1732         }
1733         return this.builtinJavaApi;
1734     }
1735 
1736     /**
1737      * Called from compiled script code to test if builtin has been overridden
1738      *
1739      * @return true if builtin Java importer has not been overridden
1740      */
1741     public static boolean isBuiltinJavaImporter() {
1742         final Global instance = Global.instance();
1743         return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
1744     }
1745 
1746     /**
1747      * Called from compiled script code to test if builtin has been overridden
1748      *
1749      * @return true if builtin math has not been overridden
1750      */
1751     public static boolean isBuiltinMath() {
1752         final Global instance = Global.instance();
1753         return instance.math == instance.builtinMath;
1754     }
1755 
1756     private ScriptFunction getBuiltinNumber() {
1757         return builtinNumber;
1758     }
1759 
1760     /**
1761      * Called from compiled script code to test if builtin has been overridden
1762      *
1763      * @return true if builtin number has not been overridden
1764      */
1765     public static boolean isBuiltinNumber() {
1766         final Global instance = Global.instance();
1767         return instance.number == instance.getBuiltinNumber();
1768     }
1769 
1770     private ScriptFunction getBuiltinObject() {
1771         return builtinObject;
1772     }
1773 
1774     /**
1775      * Called from compiled script code to test if builtin has been overridden
1776      *
1777      * @return true if builtin object has not been overridden
1778      */
1779     public static boolean isBuiltinObject() {
1780         final Global instance = Global.instance();
1781         return instance.object == instance.getBuiltinObject();
1782     }
1783 
1784     private ScriptObject getBuiltinPackages() {
1785         return builtinPackages;
1786     }
1787 
1788     /**
1789      * Called from compiled script code to test if builtin has been overridden
1790      *
1791      * @return true if builtin package has not been overridden
1792      */
1793     public static boolean isBuiltinPackages() {
1794         final Global instance = Global.instance();
1795         return instance.packages == instance.getBuiltinPackages();
1796     }
1797 
1798     private synchronized ScriptFunction getBuiltinRangeError() {
1799         if (this.builtinRangeError == null) {
1800             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
1801         }
1802         return builtinRangeError;
1803     }
1804 
1805     /**
1806      * Called from compiled script code to test if builtin has been overridden
1807      *
1808      * @return true if builtin range error has not been overridden
1809      */
1810     public static boolean isBuiltinRangeError() {
1811         final Global instance = Global.instance();
1812         return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
1813     }
1814 
1815     private synchronized ScriptFunction getBuiltinReferenceError() {
1816         return builtinReferenceError;
1817     }
1818 
1819     /**
1820      * Called from compiled script code to test if builtin has been overridden
1821      *
1822      * @return true if builtin reference error has not been overridden
1823      */
1824     public static boolean isBuiltinReferenceError() {
1825         final Global instance = Global.instance();
1826         return instance.referenceError == instance.getBuiltinReferenceError();
1827     }
1828 
1829     private synchronized ScriptFunction getBuiltinRegExp() {
1830         if (this.builtinRegExp == null) {
1831             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
1832             final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
1833             // initialize default regexp object
1834             this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
1835             // RegExp.prototype should behave like a RegExp object. So copy the
1836             // properties.
1837             regExpProto.addBoundProperties(DEFAULT_REGEXP);
1838         }
1839         return builtinRegExp;
1840     }
1841 
1842     /**
1843      * Called from compiled script code to test if builtin has been overridden
1844      *
1845      * @return true if builtin regexp has not been overridden
1846      */
1847     public static boolean isBuiltinRegExp() {
1848         final Global instance = Global.instance();
1849         return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
1850     }
1851 
1852     private ScriptFunction getBuiltinString() {
1853         return builtinString;
1854     }
1855 
1856     /**
1857      * Called from compiled script code to test if builtin has been overridden
1858      *
1859      * @return true if builtin Java has not been overridden
1860      */
1861     public static boolean isBuiltinString() {
1862         final Global instance = Global.instance();
1863         return instance.string == instance.getBuiltinString();
1864     }
1865 
1866     private ScriptFunction getBuiltinSyntaxError() {
1867         return builtinSyntaxError;
1868     }
1869 
1870     /**
1871      * Called from compiled script code to test if builtin has been overridden
1872      *
1873      * @return true if builtin syntax error has not been overridden
1874      */
1875     public static boolean isBuiltinSyntaxError() {
1876         final Global instance = Global.instance();
1877         return instance.syntaxError == instance.getBuiltinSyntaxError();
1878     }
1879 
1880     private ScriptFunction getBuiltinTypeError() {
1881         return builtinTypeError;
1882     }
1883 
1884     /**
1885      * Called from compiled script code to test if builtin has been overridden
1886      *
1887      * @return true if builtin type error has not been overridden
1888      */
1889     public static boolean isBuiltinTypeError() {
1890         final Global instance = Global.instance();
1891         return instance.typeError == instance.getBuiltinTypeError();
1892     }
1893 
1894     private synchronized ScriptFunction getBuiltinURIError() {
1895         if (this.builtinURIError == null) {
1896             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
1897         }
1898         return this.builtinURIError;
1899     }
1900 
1901     /**
1902      * Called from compiled script code to test if builtin has been overridden
1903      *
1904      * @return true if builtin URI error has not been overridden
1905      */
1906     public static boolean isBuiltinURIError() {
1907         final Global instance = Global.instance();
1908         return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
1909     }
1910 
1911     @Override
1912     public String getClassName() {
1913         return "global";
1914     }
1915 
1916     /**
1917      * Copy function used to clone NativeRegExp objects.
1918      *
1919      * @param regexp a NativeRegExp to clone
1920      *
1921      * @return copy of the given regexp object
1922      */
1923     public static Object regExpCopy(final Object regexp) {
1924         return new NativeRegExp((NativeRegExp)regexp);
1925     }
1926 
1927     /**
1928      * Convert given object to NativeRegExp type.
1929      *
1930      * @param obj object to be converted
1931      * @return NativeRegExp instance
1932      */
1933     public static NativeRegExp toRegExp(final Object obj) {
1934         if (obj instanceof NativeRegExp) {
1935             return (NativeRegExp)obj;
1936         }
1937         return new NativeRegExp(JSType.toString(obj));
1938     }
1939 
1940     /**
1941      * ECMA 9.9 ToObject implementation
1942      *
1943      * @param obj  an item for which to run ToObject
1944      * @return ToObject version of given item
1945      */
1946     public static Object toObject(final Object obj) {
1947         if (obj == null || obj == UNDEFINED) {
1948             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1949         }
1950 
1951         if (obj instanceof ScriptObject) {
1952             return obj;
1953         }
1954 
1955         return instance().wrapAsObject(obj);
1956     }
1957 
1958     /**
1959      * Allocate a new object array.
1960      *
1961      * @param initial object values.
1962      * @return the new array
1963      */
1964     public static NativeArray allocate(final Object[] initial) {
1965         ArrayData arrayData = ArrayData.allocate(initial);
1966 
1967         for (int index = 0; index < initial.length; index++) {
1968             final Object value = initial[index];
1969 
1970             if (value == ScriptRuntime.EMPTY) {
1971                 arrayData = arrayData.delete(index);
1972             }
1973         }
1974 
1975         return new NativeArray(arrayData);
1976     }
1977 
1978     /**
1979      * Allocate a new number array.
1980      *
1981      * @param initial number values.
1982      * @return the new array
1983      */
1984     public static NativeArray allocate(final double[] initial) {
1985         return new NativeArray(ArrayData.allocate(initial));
1986     }
1987 
1988     /**
1989      * Allocate a new long array.
1990      *
1991      * @param initial number values.
1992      * @return the new array
1993      */
1994     public static NativeArray allocate(final long[] initial) {
1995         return new NativeArray(ArrayData.allocate(initial));
1996     }
1997 
1998     /**
1999      * Allocate a new integer array.
2000      *
2001      * @param initial number values.
2002      * @return the new array
2003      */
2004     public static NativeArray allocate(final int[] initial) {
2005         return new NativeArray(ArrayData.allocate(initial));
2006     }
2007 
2008     /**
2009      * Allocate a new object array for arguments.
2010      *
2011      * @param arguments initial arguments passed.
2012      * @param callee reference to the function that uses arguments object
2013      * @param numParams actual number of declared parameters
2014      *
2015      * @return the new array
2016      */
2017     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2018         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2019     }
2020 
2021     /**
2022      * Called from generated to check if given function is the builtin 'eval'. If
2023      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2024      *
2025      * @param  fn function object that is checked
2026      * @return true if fn is the builtin eval
2027      */
2028     public static boolean isEval(final Object fn) {
2029         return fn == Global.instance().builtinEval;
2030     }
2031 
2032     /**
2033      * Called from generated to replace a location property placeholder with the actual location property value.
2034      *
2035      * @param  placeholder the value tested for being a placeholder for a location property
2036      * @param  locationProperty the actual value for the location property
2037      * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2038      */
2039     public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2040         return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2041     }
2042 
2043     /**
2044      * Called from runtime internals to check if the passed value is a location property placeholder.
2045      * @param  placeholder the value tested for being a placeholder for a location property
2046      * @return true if the value is a placeholder, false otherwise.
2047      */
2048     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2049         return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
2050     }
2051 
2052     /**
2053      * Create a new RegExp object.
2054      *
2055      * @param expression Regular expression.
2056      * @param options    Search options.
2057      *
2058      * @return New RegExp object.
2059      */
2060     public static Object newRegExp(final String expression, final String options) {
2061         if (options == null) {
2062             return new NativeRegExp(expression);
2063         }
2064         return new NativeRegExp(expression, options);
2065     }
2066 
2067     /**
2068      * Get the object prototype
2069      *
2070      * @return the object prototype
2071      */
2072     public static ScriptObject objectPrototype() {
2073         return Global.instance().getObjectPrototype();
2074     }
2075 
2076     /**
2077      * Create a new empty object instance.
2078      *
2079      * @return New empty object.
2080      */
2081     public static ScriptObject newEmptyInstance() {
2082         return Global.instance().newObject();
2083     }
2084 
2085     /**
2086      * Check if a given object is a ScriptObject, raises an exception if this is
2087      * not the case
2088      *
2089      * @param obj and object to check
2090      * @return the script object
2091      */
2092     public static ScriptObject checkObject(final Object obj) {
2093         if (!(obj instanceof ScriptObject)) {
2094             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2095         }
2096         return (ScriptObject)obj;
2097     }
2098 
2099     /**
2100      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2101      * if this object is null or undefined.
2102      *
2103      * @param obj an object to check
2104      */
2105     public static void checkObjectCoercible(final Object obj) {
2106         if (obj == null || obj == UNDEFINED) {
2107             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2108         }
2109     }
2110 
2111     /**
2112      * Get the current split state.
2113      *
2114      * @return current split state
2115      */
2116     @Override
2117     public int getSplitState() {
2118         return splitState;
2119     }
2120 
2121     /**
2122      * Set the current split state.
2123      *
2124      * @param state current split state
2125      */
2126     @Override
2127     public void setSplitState(final int state) {
2128         splitState = state;
2129     }
2130 
2131     /**
2132      * Return the ES6 global scope for lexically declared bindings.
2133      * @return the ES6 lexical global scope.
2134      */
2135     public final ScriptObject getLexicalScope() {
2136         assert context.getEnv()._es6;
2137         return lexicalScope;
2138     }
2139 
2140     @Override
2141     public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2142         PropertyMap ownMap = getMap();
2143         LexicalScope lexicalScope = null;
2144         PropertyMap lexicalMap = null;
2145         boolean hasLexicalDefinitions = false;
2146 
2147         if (context.getEnv()._es6) {
2148             lexicalScope = (LexicalScope) getLexicalScope();
2149             lexicalMap = lexicalScope.getMap();
2150 
2151             for (final jdk.nashorn.internal.runtime.Property property : properties) {
2152                 if (property.isLexicalBinding()) {
2153                     hasLexicalDefinitions = true;
2154                 }
2155                 // ES6 15.1.8 steps 6. and 7.
2156                 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2157                 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2158                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2159                 }
2160                 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2161                 if (lexicalProperty != null && !property.isConfigurable()) {
2162                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2163                 }
2164             }
2165         }
2166 
2167         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2168             if (property.isLexicalBinding()) {
2169                 assert lexicalScope != null;
2170                 lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
2171 
2172                 if (ownMap.findProperty(property.getKey()) != null) {
2173                     // If property exists in the global object invalidate any global constant call sites.
2174                     invalidateGlobalConstant(property.getKey());
2175                 }
2176             } else {
2177                 ownMap = addBoundProperty(ownMap, source, property);
2178             }
2179         }
2180 
2181         setMap(ownMap);
2182 
2183         if (hasLexicalDefinitions) {
2184             lexicalScope.setMap(lexicalMap);
2185             invalidateLexicalSwitchPoint();
2186         }
2187     }
2188 
2189     @Override
2190     public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2191         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2192         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2193 
2194         if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2195             if (lexicalScope.hasOwnProperty(name)) {
2196                 return lexicalScope.findGetMethod(desc, request, operator);
2197             }
2198         }
2199 
2200         final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
2201 
2202         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2203         // because those are invalidated per-key in the addBoundProperties method above.
2204         // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
2205         // assuming this only applies to global constants. If other non-inherited properties will
2206         // start using switchpoints some time in the future we'll have to revisit this.
2207         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2208             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2209         }
2210 
2211         return invocation;
2212     }
2213 
2214     @Override
2215     protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
2216         if (lexicalScope != null && start != this && start.isScope()) {
2217             final FindProperty find = lexicalScope.findProperty(key, false);
2218             if (find != null) {
2219                 return find;
2220             }
2221         }
2222         return super.findProperty(key, deep, start);
2223     }
2224 
2225     @Override
2226     public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2227         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2228 
2229         if (lexicalScope != null && isScope) {
2230             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2231             if (lexicalScope.hasOwnProperty(name)) {
2232                 return lexicalScope.findSetMethod(desc, request);
2233             }
2234         }
2235 
2236         final GuardedInvocation invocation = super.findSetMethod(desc, request);
2237 
2238         if (isScope && context.getEnv()._es6) {
2239             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2240         }
2241 
2242         return invocation;
2243     }
2244 
2245     /**
2246      * Adds jjs shell interactive mode builtin functions to global scope.
2247      */
2248     public void addShellBuiltins() {
2249         Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
2250         addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2251 
2252         value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
2253         addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2254     }
2255 
2256     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2257         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2258         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2259             switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2260         }
2261         return switchPoint;
2262     }
2263 
2264     private synchronized void invalidateLexicalSwitchPoint() {
2265         if (lexicalScopeSwitchPoint != null) {
2266             context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2267             SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2268         }
2269     }
2270 
2271 
2272     @SuppressWarnings("unused")
2273     private static Object lexicalScopeFilter(final Object self) {
2274         if (self instanceof Global) {
2275             return ((Global) self).getLexicalScope();
2276         }
2277         return self;
2278     }
2279 
2280     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2281         final T func = initConstructor(name, clazz);
2282         tagBuiltinProperties(name, func);
2283         return func;
2284     }
2285 
2286     @SuppressWarnings("hiding")
2287     private void init(final ScriptEngine engine) {
2288         assert Context.getGlobal() == this : "this global is not set as current";
2289 
2290         final ScriptEnvironment env = getContext().getEnv();
2291 
2292         // initialize Function and Object constructor
2293         initFunctionAndObject();
2294 
2295         // Now fix Global's own proto.
2296         this.setInitialProto(getObjectPrototype());
2297 
2298         // initialize global function properties
2299         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
2300 
2301         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
2302                     new Specialization[] {
2303                     new Specialization(GlobalFunctions.PARSEINT_Z),
2304                     new Specialization(GlobalFunctions.PARSEINT_I),
2305                     new Specialization(GlobalFunctions.PARSEINT_J),
2306                     new Specialization(GlobalFunctions.PARSEINT_OI),
2307                     new Specialization(GlobalFunctions.PARSEINT_O) });
2308         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2309         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
2310                    new Specialization[] {
2311                         new Specialization(GlobalFunctions.IS_NAN_I),
2312                         new Specialization(GlobalFunctions.IS_NAN_J),
2313                         new Specialization(GlobalFunctions.IS_NAN_D) });
2314         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2315         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
2316         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
2317         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
2318         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2319         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
2320         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2321         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
2322         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
2323         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
2324         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
2325         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2326         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
2327         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
2328 
2329         // built-in constructors
2330         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2331         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2332         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2333         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2334         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2335 
2336         // initialize String.prototype.length to 0
2337         // add String.prototype.length
2338         final ScriptObject stringPrototype = getStringPrototype();
2339         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2340 
2341         // set isArray flag on Array.prototype
2342         final ScriptObject arrayPrototype = getArrayPrototype();
2343         arrayPrototype.setIsArray();
2344 
2345         // Error stuff
2346         initErrorObjects();
2347 
2348         // java access
2349         if (! env._no_java) {
2350             this.javaApi = LAZY_SENTINEL;
2351             this.javaImporter = LAZY_SENTINEL;
2352             initJavaAccess();
2353         }
2354 
2355         if (! env._no_typed_arrays) {
2356             this.arrayBuffer       = LAZY_SENTINEL;
2357             this.dataView          = LAZY_SENTINEL;
2358             this.int8Array         = LAZY_SENTINEL;
2359             this.uint8Array        = LAZY_SENTINEL;
2360             this.uint8ClampedArray = LAZY_SENTINEL;
2361             this.int16Array        = LAZY_SENTINEL;
2362             this.uint16Array       = LAZY_SENTINEL;
2363             this.int32Array        = LAZY_SENTINEL;
2364             this.uint32Array       = LAZY_SENTINEL;
2365             this.float32Array      = LAZY_SENTINEL;
2366             this.float64Array      = LAZY_SENTINEL;
2367         }
2368 
2369         if (env._scripting) {
2370             initScripting(env);
2371         }
2372 
2373         if (Context.DEBUG) {
2374             boolean debugOkay;
2375             final SecurityManager sm = System.getSecurityManager();
2376             if (sm != null) {
2377                 try {
2378                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2379                     debugOkay = true;
2380                 } catch (final SecurityException ignored) {
2381                     // if no permission, don't initialize Debug object
2382                     debugOkay = false;
2383                 }
2384 
2385             } else {
2386                 debugOkay = true;
2387             }
2388 
2389             if (debugOkay) {
2390                 initDebug();
2391             }
2392         }
2393 
2394         copyBuiltins();
2395 
2396         // expose script (command line) arguments as "arguments" property of global
2397         arguments = wrapAsObject(env.getArguments().toArray());
2398         if (env._scripting) {
2399             // synonym for "arguments" in scripting mode
2400             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2401         }
2402 
2403         if (engine != null) {
2404             // default file name
2405             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2406             // __noSuchProperty__ hook for ScriptContext search of missing variables
2407             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2408             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2409         }
2410     }
2411 
2412     private void initErrorObjects() {
2413         // Error objects
2414         this.builtinError = initConstructor("Error", ScriptFunction.class);
2415         final ScriptObject errorProto = getErrorPrototype();
2416 
2417         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2418         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2419         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2420         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2421         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2422         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2423         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2424         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2425         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2426         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2427         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2428         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2429         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2430 
2431         // ECMA 15.11.4.2 Error.prototype.name
2432         // Error.prototype.name = "Error";
2433         errorProto.set(NativeError.NAME, "Error", 0);
2434         // ECMA 15.11.4.3 Error.prototype.message
2435         // Error.prototype.message = "";
2436         errorProto.set(NativeError.MESSAGE, "", 0);
2437 
2438         tagBuiltinProperties("Error", builtinError);
2439 
2440         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2441         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2442         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2443     }
2444 
2445     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2446         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2447         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2448         prototype.set(NativeError.NAME, name, 0);
2449         prototype.set(NativeError.MESSAGE, "", 0);
2450         prototype.setInitialProto(errorProto);
2451         tagBuiltinProperties(name, cons);
2452         return cons;
2453     }
2454 
2455     private void initJavaAccess() {
2456         final ScriptObject objectProto = getObjectPrototype();
2457         this.builtinPackages = new NativeJavaPackage("", objectProto);
2458         this.builtinCom = new NativeJavaPackage("com", objectProto);
2459         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2460         this.builtinJava = new NativeJavaPackage("java", objectProto);
2461         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2462         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2463         this.builtinOrg = new NativeJavaPackage("org", objectProto);
2464     }
2465 
2466     private void initScripting(final ScriptEnvironment scriptEnv) {
2467         Object value;
2468         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2469         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2470 
2471         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2472         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2473 
2474         final String execName = ScriptingFunctions.EXEC_NAME;
2475         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2476         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2477 
2478         // Nashorn extension: global.echo (scripting-mode-only)
2479         // alias for "print"
2480         value = get("print");
2481         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2482 
2483         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2484         final ScriptObject options = newObject();
2485         copyOptions(options, scriptEnv);
2486         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2487 
2488         // Nashorn extension: global.$ENV (scripting-mode-only)
2489         if (System.getSecurityManager() == null) {
2490             // do not fill $ENV if we have a security manager around
2491             // Retrieve current state of ENV variables.
2492             final ScriptObject env = newObject();
2493             env.putAll(System.getenv(), scriptEnv._strict);
2494             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2495         } else {
2496             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2497         }
2498 
2499         // add other special properties for exec support
2500         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2501         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2502         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2503     }
2504 
2505     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2506         for (final Field f : scriptEnv.getClass().getFields()) {
2507             try {
2508                 options.set(f.getName(), f.get(scriptEnv), 0);
2509             } catch (final IllegalArgumentException | IllegalAccessException exp) {
2510                 throw new RuntimeException(exp);
2511             }
2512         }
2513     }
2514 
2515     private void copyBuiltins() {
2516         this.array             = this.builtinArray;
2517         this._boolean          = this.builtinBoolean;
2518         this.error             = this.builtinError;
2519         this.function          = this.builtinFunction;
2520         this.com               = this.builtinCom;
2521         this.edu               = this.builtinEdu;
2522         this.java              = this.builtinJava;
2523         this.javafx            = this.builtinJavafx;
2524         this.javax             = this.builtinJavax;
2525         this.org               = this.builtinOrg;
2526         this.math              = this.builtinMath;
2527         this.number            = this.builtinNumber;
2528         this.object            = this.builtinObject;
2529         this.packages          = this.builtinPackages;
2530         this.referenceError    = this.builtinReferenceError;
2531         this.string            = this.builtinString;
2532         this.syntaxError       = this.builtinSyntaxError;
2533         this.typeError         = this.builtinTypeError;
2534     }
2535 
2536     private void initDebug() {
2537         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2538     }
2539 
2540     private Object printImpl(final boolean newLine, final Object... objects) {
2541         @SuppressWarnings("resource")
2542         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2543         final StringBuilder sb = new StringBuilder();
2544 
2545         for (final Object obj : objects) {
2546             if (sb.length() != 0) {
2547                 sb.append(' ');
2548             }
2549 
2550             sb.append(JSType.toString(obj));
2551         }
2552 
2553         // Print all at once to ensure thread friendly result.
2554         if (newLine) {
2555             out.println(sb.toString());
2556         } else {
2557             out.print(sb.toString());
2558         }
2559 
2560         out.flush();
2561 
2562         return UNDEFINED;
2563     }
2564 
2565     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2566         try {
2567             // Assuming class name pattern for built-in JS constructors.
2568             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2569 
2570             sb.append("Native");
2571             sb.append(name);
2572             sb.append("$Constructor");
2573 
2574             final Class<?> funcClass = Class.forName(sb.toString());
2575             final T res = clazz.cast(funcClass.newInstance());
2576 
2577             if (res instanceof ScriptFunction) {
2578                 // All global constructor prototypes are not-writable,
2579                 // not-enumerable and not-configurable.
2580                 final ScriptFunction func = (ScriptFunction)res;
2581                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2582             }
2583 
2584             if (res.getProto() == null) {
2585                 res.setInitialProto(getObjectPrototype());
2586             }
2587 
2588             res.setIsBuiltin();
2589 
2590             return res;
2591         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2592             throw new RuntimeException(e);
2593         }
2594     }
2595 
2596     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2597         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2598 
2599         list.addAll(Arrays.asList(func.getMap().getProperties()));
2600 
2601         if (func instanceof ScriptFunction) {
2602             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2603             if (proto != null) {
2604                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2605             }
2606         }
2607 
2608         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2609         if (prop != null) {
2610             list.add(prop);
2611         }
2612 
2613         return list;
2614     }
2615 
2616     /**
2617      * Given a builtin object, traverse its properties recursively and associate them with a name that
2618      * will be a key to their invalidation switchpoint.
2619      * @param name name for key
2620      * @param func builtin script object
2621      */
2622     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2623         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2624         if (sp == null) {
2625             sp = context.newBuiltinSwitchPoint(name);
2626         }
2627 
2628         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2629         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2630         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2631             prop.setBuiltinSwitchPoint(sp);
2632         }
2633     }
2634 
2635     // Function and Object constructors are inter-dependent. Also,
2636     // Function.prototype
2637     // functions are not properly initialized. We fix the references here.
2638     // NOTE: be careful if you want to re-order the operations here. You may
2639     // have
2640     // to play with object references carefully!!
2641     private void initFunctionAndObject() {
2642         // First-n-foremost is Function
2643 
2644         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2645 
2646         // create global anonymous function
2647         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2648         // need to copy over members of Function.prototype to anon function
2649         anon.addBoundProperties(getFunctionPrototype());
2650 
2651         // Function.prototype === Object.getPrototypeOf(Function) ===
2652         // <anon-function>
2653         builtinFunction.setInitialProto(anon);
2654         builtinFunction.setPrototype(anon);
2655         anon.set("constructor", builtinFunction, 0);
2656         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2657 
2658         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2659         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2660         typeErrorThrower.setPrototype(UNDEFINED);
2661         // Non-constructor built-in functions do not have "prototype" property
2662         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2663         typeErrorThrower.preventExtensions();
2664 
2665         // now initialize Object
2666         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2667         final ScriptObject ObjectPrototype = getObjectPrototype();
2668         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2669         anon.setInitialProto(ObjectPrototype);
2670 
2671         // ES6 draft compliant __proto__ property of Object.prototype
2672         // accessors on Object.prototype for "__proto__"
2673         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2674         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2675         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2676 
2677         // Function valued properties of Function.prototype were not properly
2678         // initialized. Because, these were created before global.function and
2679         // global.object were not initialized.
2680         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2681         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2682             final Object key = property.getKey();
2683             final Object value = builtinFunction.get(key);
2684 
2685             if (value instanceof ScriptFunction && value != anon) {
2686                 final ScriptFunction func = (ScriptFunction)value;
2687                 func.setInitialProto(getFunctionPrototype());
2688                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2689                 if (prototype != null) {
2690                     prototype.setInitialProto(ObjectPrototype);
2691                 }
2692             }
2693         }
2694 
2695         // For function valued properties of Object and Object.prototype, make
2696         // sure prototype's proto chain ends with Object.prototype
2697         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2698             final Object key = property.getKey();
2699             final Object value = builtinObject.get(key);
2700 
2701             if (value instanceof ScriptFunction) {
2702                 final ScriptFunction func = (ScriptFunction)value;
2703                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2704                 if (prototype != null) {
2705                     prototype.setInitialProto(ObjectPrototype);
2706                 }
2707             }
2708         }
2709 
2710         properties = getObjectPrototype().getMap().getProperties();
2711 
2712         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2713             final Object key   = property.getKey();
2714             if (key.equals("constructor")) {
2715                 continue;
2716             }
2717 
2718             final Object value = ObjectPrototype.get(key);
2719             if (value instanceof ScriptFunction) {
2720                 final ScriptFunction func = (ScriptFunction)value;
2721                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2722                 if (prototype != null) {
2723                     prototype.setInitialProto(ObjectPrototype);
2724                 }
2725             }
2726         }
2727 
2728         tagBuiltinProperties("Object", builtinObject);
2729         tagBuiltinProperties("Function", builtinFunction);
2730         tagBuiltinProperties("Function", anon);
2731     }
2732 
2733     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2734         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2735     }
2736 
2737     RegExpResult getLastRegExpResult() {
2738         return lastRegExpResult;
2739     }
2740 
2741     void setLastRegExpResult(final RegExpResult regExpResult) {
2742         this.lastRegExpResult = regExpResult;
2743     }
2744 
2745     @Override
2746     protected boolean isGlobal() {
2747         return true;
2748     }
2749 
2750     /**
2751      * A class representing the ES6 global lexical scope.
2752      */
2753     private static class LexicalScope extends ScriptObject {
2754 
2755         LexicalScope(final Global global) {
2756             super(global, PropertyMap.newMap());
2757         }
2758 
2759         @Override
2760         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2761             return filterInvocation(super.findGetMethod(desc, request, operator));
2762         }
2763 
2764         @Override
2765         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2766             return filterInvocation(super.findSetMethod(desc, request));
2767         }
2768 
2769         @Override
2770         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
2771             // We override this method just to make it callable by Global
2772             return super.addBoundProperty(propMap, source, property);
2773         }
2774 
2775         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
2776             final MethodType type = invocation.getInvocation().type();
2777             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
2778         }
2779     }
2780 
2781 }