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