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