1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.objects;
  27 
  28 import static jdk.nashorn.internal.lookup.Lookup.MH;
  29 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  31 import static jdk.nashorn.internal.runtime.JSType.isString;
  32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  33 
  34 import java.io.IOException;
  35 import java.io.PrintWriter;
  36 import java.lang.invoke.MethodHandle;
  37 import java.lang.invoke.MethodHandles;
  38 import java.lang.invoke.MethodType;
  39 import java.lang.invoke.SwitchPoint;
  40 import java.lang.reflect.Field;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.List;
  44 import java.util.Map;
  45 import java.util.Objects;
  46 import java.util.concurrent.Callable;
  47 import java.util.concurrent.ConcurrentHashMap;
  48 import javax.script.ScriptContext;
  49 import javax.script.ScriptEngine;
  50 import jdk.internal.dynalink.CallSiteDescriptor;
  51 import jdk.internal.dynalink.linker.GuardedInvocation;
  52 import jdk.internal.dynalink.linker.LinkRequest;
  53 import jdk.nashorn.api.scripting.ClassFilter;
  54 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  55 import jdk.nashorn.internal.lookup.Lookup;
  56 import jdk.nashorn.internal.objects.annotations.Attribute;
  57 import jdk.nashorn.internal.objects.annotations.Getter;
  58 import jdk.nashorn.internal.objects.annotations.Property;
  59 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  60 import jdk.nashorn.internal.objects.annotations.Setter;
  61 import jdk.nashorn.internal.runtime.Context;
  62 import jdk.nashorn.internal.runtime.ECMAErrors;
  63 import jdk.nashorn.internal.runtime.FindProperty;
  64 import jdk.nashorn.internal.runtime.GlobalConstants;
  65 import jdk.nashorn.internal.runtime.GlobalFunctions;
  66 import jdk.nashorn.internal.runtime.JSType;
  67 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  68 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  69 import jdk.nashorn.internal.runtime.PropertyMap;
  70 import jdk.nashorn.internal.runtime.Scope;
  71 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  72 import jdk.nashorn.internal.runtime.ScriptFunction;
  73 import jdk.nashorn.internal.runtime.ScriptObject;
  74 import jdk.nashorn.internal.runtime.ScriptRuntime;
  75 import jdk.nashorn.internal.runtime.ScriptingFunctions;
  76 import jdk.nashorn.internal.runtime.Specialization;
  77 import jdk.nashorn.internal.runtime.arrays.ArrayData;
  78 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  79 import jdk.nashorn.internal.runtime.linker.InvokeByName;
  80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  81 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
  82 import jdk.nashorn.internal.scripts.JD;
  83 import jdk.nashorn.internal.scripts.JO;
  84 import jdk.nashorn.tools.ShellFunctions;
  85 
  86 /**
  87  * Representation of global scope.
  88  */
  89 @ScriptClass("Global")
  90 public final class Global extends ScriptObject implements Scope {
  91     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
  92     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
  93     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  94     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  95 
  96     // placeholder value for lazily initialized global objects
  97     private static final Object LAZY_SENTINEL = new Object();
  98 
  99     /**
 100      * Optimistic builtin names that require switchpoint invalidation
 101      * upon assignment. Overly conservative, but works for now, to avoid
 102      * any complicated scope checks and especially heavy weight guards
 103      * like
 104      *
 105      * <pre>
 106      *     public boolean setterGuard(final Object receiver) {
 107      *         final Global          global = Global.instance();
 108      *         final ScriptObject    sobj   = global.getFunctionPrototype();
 109      *         final Object          apply  = sobj.get("apply");
 110      *         return apply == receiver;
 111      *     }
 112      * </pre>
 113      *
 114      * Naturally, checking for builtin classes like NativeFunction is cheaper,
 115      * it's when you start adding property checks for said builtins you have
 116      * problems with guard speed.
 117      */
 118 
 119     /** Nashorn extension: arguments array */
 120     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 121     public Object arguments;
 122 
 123     /** ECMA 15.1.2.2 parseInt (string , radix) */
 124     @Property(attributes = Attribute.NOT_ENUMERABLE)
 125     public Object parseInt;
 126 
 127     /** ECMA 15.1.2.3 parseFloat (string) */
 128     @Property(attributes = Attribute.NOT_ENUMERABLE)
 129     public Object parseFloat;
 130 
 131     /** ECMA 15.1.2.4 isNaN (number) */
 132     @Property(attributes = Attribute.NOT_ENUMERABLE)
 133     public Object isNaN;
 134 
 135     /** ECMA 15.1.2.5 isFinite (number) */
 136     @Property(attributes = Attribute.NOT_ENUMERABLE)
 137     public Object isFinite;
 138 
 139     /** ECMA 15.1.3.3 encodeURI */
 140     @Property(attributes = Attribute.NOT_ENUMERABLE)
 141     public Object encodeURI;
 142 
 143     /** ECMA 15.1.3.4 encodeURIComponent */
 144     @Property(attributes = Attribute.NOT_ENUMERABLE)
 145     public Object encodeURIComponent;
 146 
 147     /** ECMA 15.1.3.1 decodeURI */
 148     @Property(attributes = Attribute.NOT_ENUMERABLE)
 149     public Object decodeURI;
 150 
 151     /** ECMA 15.1.3.2 decodeURIComponent */
 152     @Property(attributes = Attribute.NOT_ENUMERABLE)
 153     public Object decodeURIComponent;
 154 
 155     /** ECMA B.2.1 escape (string) */
 156     @Property(attributes = Attribute.NOT_ENUMERABLE)
 157     public Object escape;
 158 
 159     /** ECMA B.2.2 unescape (string) */
 160     @Property(attributes = Attribute.NOT_ENUMERABLE)
 161     public Object unescape;
 162 
 163     /** Nashorn extension: global.print */
 164     @Property(attributes = Attribute.NOT_ENUMERABLE)
 165     public Object print;
 166 
 167     /** Nashorn extension: global.load */
 168     @Property(attributes = Attribute.NOT_ENUMERABLE)
 169     public Object load;
 170 
 171     /** Nashorn extension: global.loadWithNewGlobal */
 172     @Property(attributes = Attribute.NOT_ENUMERABLE)
 173     public Object loadWithNewGlobal;
 174 
 175     /** Nashorn extension: global.exit */
 176     @Property(attributes = Attribute.NOT_ENUMERABLE)
 177     public Object exit;
 178 
 179     /** Nashorn extension: global.quit */
 180     @Property(attributes = Attribute.NOT_ENUMERABLE)
 181     public Object quit;
 182 
 183     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 184     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 185     public final double NaN = Double.NaN;
 186 
 187     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 188     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 189     public final double Infinity = Double.POSITIVE_INFINITY;
 190 
 191     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 192     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 193     public final Object undefined = UNDEFINED;
 194 
 195     /** ECMA 15.1.2.1 eval(x) */
 196     @Property(attributes = Attribute.NOT_ENUMERABLE)
 197     public Object eval;
 198 
 199     /** ECMA 15.1.4.1 Object constructor. */
 200     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 201     public volatile Object object;
 202 
 203     /** ECMA 15.1.4.2 Function constructor. */
 204     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 205     public volatile Object function;
 206 
 207     /** ECMA 15.1.4.3 Array constructor. */
 208     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 209     public volatile Object array;
 210 
 211     /** ECMA 15.1.4.4 String constructor */
 212     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 213     public volatile Object string;
 214 
 215     /** ECMA 15.1.4.5 Boolean constructor */
 216     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 217     public volatile Object _boolean;
 218 
 219     /** ECMA 15.1.4.6 - Number constructor */
 220     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 221     public volatile Object number;
 222 
 223     /**
 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 final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 834 
 835     /** Nashorn extension: current script's directory */
 836     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 837     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 838 
 839     /** Nashorn extension: current source line number being executed */
 840     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 841     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 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     // Flag to indicate that a split method issued a return statement
 910     private int splitState = -1;
 911 
 912     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 913     private RegExpResult lastRegExpResult;
 914 
 915     private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
 916     private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
 917     private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
 918     private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
 919     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
 920     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
 921     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
 922     private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
 923 
 924     // initialized by nasgen
 925     private static PropertyMap $nasgenmap$;
 926 
 927     // context to which this global belongs to
 928     private final Context context;
 929 
 930     // current ScriptContext to use - can be null.
 931     private ThreadLocal<ScriptContext> scontext;
 932     // current ScriptEngine associated - can be null.
 933     private ScriptEngine engine;
 934     // initial ScriptContext - can be null
 935     private volatile ScriptContext initscontext;
 936 
 937     // ES6 global lexical scope.
 938     private final LexicalScope lexicalScope;
 939 
 940     // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
 941     private SwitchPoint lexicalScopeSwitchPoint;
 942 
 943     /**
 944      * Set the current script context
 945      * @param ctxt script context
 946      */
 947     public void setScriptContext(final ScriptContext ctxt) {
 948         assert scontext != null;
 949         scontext.set(ctxt);
 950     }
 951 
 952     /**
 953      * Get the current script context
 954      * @return current script context
 955      */
 956     public ScriptContext getScriptContext() {
 957         assert scontext != null;
 958         return scontext.get();
 959     }
 960 
 961     private ScriptContext currentContext() {
 962         final ScriptContext sc = scontext != null? scontext.get() : null;
 963         return sc == null? initscontext : sc;
 964     }
 965 
 966     @Override
 967     protected Context getContext() {
 968         return context;
 969     }
 970 
 971     @Override
 972     protected boolean useDualFields() {
 973         return context.useDualFields();
 974     }
 975 
 976     // performs initialization checks for Global constructor and returns the
 977     // PropertyMap, if everything is fine.
 978     private static PropertyMap checkAndGetMap(final Context context) {
 979         // security check first
 980         final SecurityManager sm = System.getSecurityManager();
 981         if (sm != null) {
 982             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 983         }
 984 
 985         Objects.requireNonNull(context);
 986 
 987         return $nasgenmap$;
 988     }
 989 
 990     /**
 991      * Constructor
 992      *
 993      * @param context the context
 994      */
 995     public Global(final Context context) {
 996         super(checkAndGetMap(context));
 997         this.context = context;
 998         this.setIsScope();
 999         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
1000     }
1001 
1002     /**
1003      * Script access to "current" Global instance
1004      *
1005      * @return the global singleton
1006      */
1007     public static Global instance() {
1008         return Objects.requireNonNull(Context.getGlobal());
1009     }
1010 
1011     private static Global instanceFrom(final Object self) {
1012         return self instanceof Global? (Global)self : instance();
1013     }
1014 
1015     /**
1016      * Check if we have a Global instance
1017      * @return true if one exists
1018      */
1019     public static boolean hasInstance() {
1020         return Context.getGlobal() != null;
1021     }
1022 
1023     /**
1024      * Script access to {@link ScriptEnvironment}
1025      *
1026      * @return the script environment
1027      */
1028     static ScriptEnvironment getEnv() {
1029         return instance().getContext().getEnv();
1030     }
1031 
1032     /**
1033      * Script access to {@link Context}
1034      *
1035      * @return the context
1036      */
1037     static Context getThisContext() {
1038         return instance().getContext();
1039     }
1040 
1041     // Runtime interface to Global
1042 
1043     /**
1044      * Is there a class filter in the current Context?
1045      * @return class filter
1046      */
1047     public ClassFilter getClassFilter() {
1048         return context.getClassFilter();
1049     }
1050 
1051     /**
1052      * Is this global of the given Context?
1053      * @param ctxt the context
1054      * @return true if this global belongs to the given Context
1055      */
1056     public boolean isOfContext(final Context ctxt) {
1057         return this.context == ctxt;
1058     }
1059 
1060     /**
1061      * Does this global belong to a strict Context?
1062      * @return true if this global belongs to a strict Context
1063      */
1064     public boolean isStrictContext() {
1065         return context.getEnv()._strict;
1066     }
1067 
1068     /**
1069      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
1070      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
1071      * of the global scope object.
1072      *
1073      * @param eng ScriptEngine to initialize
1074      * @param ctxt ScriptContext to initialize
1075      */
1076     public void initBuiltinObjects(final ScriptEngine eng, final ScriptContext ctxt) {
1077         if (this.builtinObject != null) {
1078             // already initialized, just return
1079             return;
1080         }
1081 
1082         this.engine = eng;
1083         this.initscontext = ctxt;
1084         if (this.engine != null) {
1085             this.scontext = new ThreadLocal<>();
1086         }
1087         init(eng);
1088     }
1089 
1090     /**
1091      * Wrap a Java object as corresponding script object
1092      *
1093      * @param obj object to wrap
1094      * @return    wrapped object
1095      */
1096     public Object wrapAsObject(final Object obj) {
1097         if (obj instanceof Boolean) {
1098             return new NativeBoolean((Boolean)obj, this);
1099         } else if (obj instanceof Number) {
1100             return new NativeNumber(((Number)obj).doubleValue(), this);
1101         } else if (isString(obj)) {
1102             return new NativeString((CharSequence)obj, this);
1103         } else if (obj instanceof Object[]) { // extension
1104             return new NativeArray(ArrayData.allocate((Object[])obj), this);
1105         } else if (obj instanceof double[]) { // extension
1106             return new NativeArray(ArrayData.allocate((double[])obj), this);
1107         } else if (obj instanceof long[]) {
1108             return new NativeArray(ArrayData.allocate((long[])obj), this);
1109         } else if (obj instanceof int[]) {
1110             return new NativeArray(ArrayData.allocate((int[]) obj), this);
1111         } else if (obj instanceof ArrayData) {
1112             return new NativeArray((ArrayData) obj, this);
1113         } else {
1114             // FIXME: more special cases? Map? List?
1115             return obj;
1116         }
1117     }
1118 
1119     /**
1120      * Lookup helper for JS primitive types
1121      *
1122      * @param request the link request for the dynamic call site.
1123      * @param self     self reference
1124      *
1125      * @return guarded invocation
1126      */
1127     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
1128         if (isString(self)) {
1129             return NativeString.lookupPrimitive(request, self);
1130         } else if (self instanceof Number) {
1131             return NativeNumber.lookupPrimitive(request, self);
1132         } else if (self instanceof Boolean) {
1133             return NativeBoolean.lookupPrimitive(request, self);
1134         }
1135         throw new IllegalArgumentException("Unsupported primitive: " + self);
1136     }
1137 
1138     /**
1139      * Returns a method handle that creates a wrapper object for a JS primitive value.
1140      *
1141      * @param self receiver object
1142      * @return method handle to create wrapper objects for primitive receiver
1143      */
1144     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
1145         if (isString(self)) {
1146             return NativeString.WRAPFILTER;
1147         } else if (self instanceof Number) {
1148             return NativeNumber.WRAPFILTER;
1149         } else if (self instanceof Boolean) {
1150             return NativeBoolean.WRAPFILTER;
1151         }
1152         throw new IllegalArgumentException("Unsupported primitive: " + self);
1153     }
1154 
1155 
1156     /**
1157      * Create a new empty script object
1158      *
1159      * @return the new ScriptObject
1160      */
1161     public ScriptObject newObject() {
1162         return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
1163     }
1164 
1165     /**
1166      * Default value of given type
1167      *
1168      * @param sobj     script object
1169      * @param typeHint type hint
1170      *
1171      * @return default value
1172      */
1173     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
1174         // When the [[DefaultValue]] internal method of O is called with no hint,
1175         // then it behaves as if the hint were Number, unless O is a Date object
1176         // in which case it behaves as if the hint were String.
1177         Class<?> hint = typeHint;
1178         if (hint == null) {
1179             hint = Number.class;
1180         }
1181 
1182         try {
1183             if (hint == String.class) {
1184 
1185                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1186 
1187                 if (Bootstrap.isCallable(toString)) {
1188                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1189                     if (JSType.isPrimitive(value)) {
1190                         return value;
1191                     }
1192                 }
1193 
1194                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1195                 if (Bootstrap.isCallable(valueOf)) {
1196                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1197                     if (JSType.isPrimitive(value)) {
1198                         return value;
1199                     }
1200                 }
1201                 throw typeError(this, "cannot.get.default.string");
1202             }
1203 
1204             if (hint == Number.class) {
1205                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
1206                 if (Bootstrap.isCallable(valueOf)) {
1207                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
1208                     if (JSType.isPrimitive(value)) {
1209                         return value;
1210                     }
1211                 }
1212 
1213                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
1214                 if (Bootstrap.isCallable(toString)) {
1215                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
1216                     if (JSType.isPrimitive(value)) {
1217                         return value;
1218                     }
1219                 }
1220 
1221                 throw typeError(this, "cannot.get.default.number");
1222             }
1223         } catch (final RuntimeException | Error e) {
1224             throw e;
1225         } catch (final Throwable t) {
1226             throw new RuntimeException(t);
1227         }
1228 
1229         return UNDEFINED;
1230     }
1231 
1232     /**
1233      * Is the given ScriptObject an ECMAScript Error object?
1234      *
1235      * @param sobj the object being checked
1236      * @return true if sobj is an Error object
1237      */
1238     public boolean isError(final ScriptObject sobj) {
1239         final ScriptObject errorProto = getErrorPrototype();
1240         ScriptObject proto = sobj.getProto();
1241         while (proto != null) {
1242             if (proto == errorProto) {
1243                 return true;
1244             }
1245             proto = proto.getProto();
1246         }
1247         return false;
1248     }
1249 
1250     /**
1251      * Create a new ECMAScript Error object.
1252      *
1253      * @param msg error message
1254      * @return newly created Error object
1255      */
1256     public ScriptObject newError(final String msg) {
1257         return new NativeError(msg, this);
1258     }
1259 
1260     /**
1261      * Create a new ECMAScript EvalError object.
1262      *
1263      * @param msg error message
1264      * @return newly created EvalError object
1265      */
1266     public ScriptObject newEvalError(final String msg) {
1267         return new NativeEvalError(msg, this);
1268     }
1269 
1270     /**
1271      * Create a new ECMAScript RangeError object.
1272      *
1273      * @param msg error message
1274      * @return newly created RangeError object
1275      */
1276     public ScriptObject newRangeError(final String msg) {
1277         return new NativeRangeError(msg, this);
1278     }
1279 
1280     /**
1281      * Create a new ECMAScript ReferenceError object.
1282      *
1283      * @param msg error message
1284      * @return newly created ReferenceError object
1285      */
1286     public ScriptObject newReferenceError(final String msg) {
1287         return new NativeReferenceError(msg, this);
1288     }
1289 
1290     /**
1291      * Create a new ECMAScript SyntaxError object.
1292      *
1293      * @param msg error message
1294      * @return newly created SyntaxError object
1295      */
1296     public ScriptObject newSyntaxError(final String msg) {
1297         return new NativeSyntaxError(msg, this);
1298     }
1299 
1300     /**
1301      * Create a new ECMAScript TypeError object.
1302      *
1303      * @param msg error message
1304      * @return newly created TypeError object
1305      */
1306     public ScriptObject newTypeError(final String msg) {
1307         return new NativeTypeError(msg, this);
1308     }
1309 
1310     /**
1311      * Create a new ECMAScript URIError object.
1312      *
1313      * @param msg error message
1314      * @return newly created URIError object
1315      */
1316     public ScriptObject newURIError(final String msg) {
1317         return new NativeURIError(msg, this);
1318     }
1319 
1320     /**
1321      * Create a new ECMAScript GenericDescriptor object.
1322      *
1323      * @param configurable is the property configurable?
1324      * @param enumerable is the property enumerable?
1325      * @return newly created GenericDescriptor object
1326      */
1327     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1328         return new GenericPropertyDescriptor(configurable, enumerable, this);
1329     }
1330 
1331     /**
1332      * Create a new ECMAScript DatePropertyDescriptor object.
1333      *
1334      * @param value of the data property
1335      * @param configurable is the property configurable?
1336      * @param enumerable is the property enumerable?
1337      * @param writable is the property writable?
1338      * @return newly created DataPropertyDescriptor object
1339      */
1340     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1341         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1342     }
1343 
1344     /**
1345      * Create a new ECMAScript AccessorPropertyDescriptor object.
1346      *
1347      * @param get getter function of the user accessor property
1348      * @param set setter function of the user accessor property
1349      * @param configurable is the property configurable?
1350      * @param enumerable is the property enumerable?
1351      * @return newly created AccessorPropertyDescriptor object
1352      */
1353     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1354         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1355 
1356         if (get == null) {
1357             desc.delete(PropertyDescriptor.GET, false);
1358         }
1359 
1360         if (set == null) {
1361             desc.delete(PropertyDescriptor.SET, false);
1362         }
1363 
1364         return desc;
1365     }
1366 
1367     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1368         final T obj = map.get(key);
1369         if (obj != null) {
1370             return obj;
1371         }
1372 
1373         try {
1374             final T newObj = creator.call();
1375             final T existingObj = map.putIfAbsent(key, newObj);
1376             return existingObj != null ? existingObj : newObj;
1377         } catch (final Exception exp) {
1378             throw new RuntimeException(exp);
1379         }
1380     }
1381 
1382     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1383 
1384 
1385     /**
1386      * Get cached InvokeByName object for the given key
1387      * @param key key to be associated with InvokeByName object
1388      * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1389      * @return InvokeByName object associated with the key.
1390      */
1391     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1392         return getLazilyCreatedValue(key, creator, namedInvokers);
1393     }
1394 
1395     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1396 
1397     /**
1398      * Get cached dynamic method handle for the given key
1399      * @param key key to be associated with dynamic method handle
1400      * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1401      * @return dynamic method handle associated with the key.
1402      */
1403     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1404         return getLazilyCreatedValue(key, creator, dynamicInvokers);
1405     }
1406 
1407     /**
1408      * Hook to search missing variables in ScriptContext if available
1409      * @param self used to detect if scope call or not (this function is 'strict')
1410      * @param name name of the variable missing
1411      * @return value of the missing variable or undefined (or TypeError for scope search)
1412      */
1413     public static Object __noSuchProperty__(final Object self, final Object name) {
1414         final Global global = Global.instance();
1415         final ScriptContext sctxt = global.currentContext();
1416         final String nameStr = name.toString();
1417 
1418         if (sctxt != null) {
1419             final int scope = sctxt.getAttributesScope(nameStr);
1420             if (scope != -1) {
1421                 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1422             }
1423         }
1424 
1425         switch (nameStr) {
1426         case "context":
1427             return sctxt;
1428         case "engine":
1429             return global.engine;
1430         default:
1431             break;
1432         }
1433 
1434         if (self == UNDEFINED) {
1435             // scope access and so throw ReferenceError
1436             throw referenceError(global, "not.defined", nameStr);
1437         }
1438 
1439         return UNDEFINED;
1440     }
1441 
1442     /**
1443      * This is the eval used when 'indirect' eval call is made.
1444      *
1445      * var global = this;
1446      * global.eval("print('hello')");
1447      *
1448      * @param self  eval scope
1449      * @param str   eval string
1450      *
1451      * @return the result of eval
1452      */
1453     public static Object eval(final Object self, final Object str) {
1454         return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false);
1455     }
1456 
1457     /**
1458      * Direct eval
1459      *
1460      * @param self     The scope of eval passed as 'self'
1461      * @param str      Evaluated code
1462      * @param callThis "this" to be passed to the evaluated code
1463      * @param location location of the eval call
1464      * @param strict   is eval called from a strict mode code?
1465      *
1466      * @return the return value of the eval
1467      *
1468      * This is directly invoked from generated when eval(code) is called in user code
1469      */
1470     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1471         if (!isString(str)) {
1472             return str;
1473         }
1474         final Global global = Global.instanceFrom(self);
1475         final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1476 
1477         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1478     }
1479 
1480     /**
1481      * Global print implementation - Nashorn extension
1482      *
1483      * @param self    scope
1484      * @param objects arguments to print
1485      *
1486      * @return result of print (undefined)
1487      */
1488     public static Object print(final Object self, final Object... objects) {
1489         return Global.instanceFrom(self).printImpl(false, objects);
1490     }
1491 
1492     /**
1493      * Global println implementation - Nashorn extension
1494      *
1495      * @param self    scope
1496      * @param objects arguments to print
1497      *
1498      * @return result of println (undefined)
1499      */
1500     public static Object println(final Object self, final Object... objects) {
1501         return Global.instanceFrom(self).printImpl(true, objects);
1502     }
1503 
1504     /**
1505      * Global load implementation - Nashorn extension.
1506      *
1507      * <p>
1508      * load builtin loads the given script. Script source can be a URL or a File
1509      * or a script object with name and script properties. Evaluated code gets
1510      * global object "this" and uses global object as scope for evaluation.
1511      * </p>
1512      * <p>
1513      * If self is undefined or null or global, then global object is used
1514      * as scope as well as "this" for the evaluated code. If self is any other
1515      * object, then it is indirect load call. With indirect load call, the
1516      * properties of scope are available to evaluated script as variables. Also,
1517      * global scope properties are accessible. Any var, function definition in
1518      * evaluated script goes into an object that is not accessible to user scripts.
1519      * </p>
1520      * Thus the indirect load call is equivalent to the following:
1521      * <pre>
1522      * <code>
1523      * (function (scope, source) {
1524      *    with(scope) {
1525      *        eval(&lt;script_from_source&gt;);
1526      *    }
1527      * })(self, source);
1528      * </code>
1529      * </pre>
1530      *
1531      * @param self    scope to use for the script evaluation
1532      * @param source  script source
1533      *
1534      * @return result of load (may be undefined)
1535      *
1536      * @throws IOException if source could not be read
1537      */
1538     public static Object load(final Object self, final Object source) throws IOException {
1539         final Global global = Global.instanceFrom(self);
1540         return global.getContext().load(self, source);
1541     }
1542 
1543     /**
1544      * Global loadWithNewGlobal implementation - Nashorn extension.
1545      *
1546      * loadWithNewGlobal builtin loads the given script from a URL or a File
1547      * or a script object with name and script properties. Evaluated code gets
1548      * new global object "this" and uses that new global object as scope for evaluation.
1549      *
1550      * @param self self This value is ignored by this function
1551      * @param args optional arguments to be passed to the loaded script
1552      *
1553      * @return result of load (may be undefined)
1554      *
1555      * @throws IOException if source could not be read
1556      */
1557     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1558         final Global global = Global.instanceFrom(self);
1559         final int length = args.length;
1560         final boolean hasArgs = 0 < length;
1561         final Object from = hasArgs ? args[0] : UNDEFINED;
1562         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1563 
1564         return global.getContext().loadWithNewGlobal(from, arguments);
1565     }
1566 
1567     /**
1568      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1569      *
1570      * @param self  self reference
1571      * @param code  exit code
1572      *
1573      * @return undefined (will never be reached)
1574      */
1575     public static Object exit(final Object self, final Object code) {
1576         System.exit(JSType.toInt32(code));
1577         return UNDEFINED;
1578     }
1579 
1580     // builtin prototype accessors
1581 
1582     /**
1583      * Get the builtin Object prototype.
1584      * @return the object prototype.
1585      */
1586     public ScriptObject getObjectPrototype() {
1587         return ScriptFunction.getPrototype(builtinObject);
1588     }
1589 
1590     ScriptObject getFunctionPrototype() {
1591         return ScriptFunction.getPrototype(builtinFunction);
1592     }
1593 
1594     ScriptObject getArrayPrototype() {
1595         return ScriptFunction.getPrototype(builtinArray);
1596     }
1597 
1598     ScriptObject getBooleanPrototype() {
1599         return ScriptFunction.getPrototype(builtinBoolean);
1600     }
1601 
1602     ScriptObject getNumberPrototype() {
1603         return ScriptFunction.getPrototype(builtinNumber);
1604     }
1605 
1606     ScriptObject getDatePrototype() {
1607         return ScriptFunction.getPrototype(getBuiltinDate());
1608     }
1609 
1610     ScriptObject getRegExpPrototype() {
1611         return ScriptFunction.getPrototype(getBuiltinRegExp());
1612     }
1613 
1614     ScriptObject getStringPrototype() {
1615         return ScriptFunction.getPrototype(builtinString);
1616     }
1617 
1618     ScriptObject getErrorPrototype() {
1619         return ScriptFunction.getPrototype(builtinError);
1620     }
1621 
1622     ScriptObject getEvalErrorPrototype() {
1623         return ScriptFunction.getPrototype(getBuiltinEvalError());
1624     }
1625 
1626     ScriptObject getRangeErrorPrototype() {
1627         return ScriptFunction.getPrototype(getBuiltinRangeError());
1628     }
1629 
1630     ScriptObject getReferenceErrorPrototype() {
1631         return ScriptFunction.getPrototype(builtinReferenceError);
1632     }
1633 
1634     ScriptObject getSyntaxErrorPrototype() {
1635         return ScriptFunction.getPrototype(builtinSyntaxError);
1636     }
1637 
1638     ScriptObject getTypeErrorPrototype() {
1639         return ScriptFunction.getPrototype(builtinTypeError);
1640     }
1641 
1642     ScriptObject getURIErrorPrototype() {
1643         return ScriptFunction.getPrototype(getBuiltinURIError());
1644     }
1645 
1646     ScriptObject getJavaImporterPrototype() {
1647         return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1648     }
1649 
1650     ScriptObject getJSAdapterPrototype() {
1651         return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1652     }
1653 
1654     private synchronized ScriptFunction getBuiltinArrayBuffer() {
1655         if (this.builtinArrayBuffer == null) {
1656             this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1657         }
1658         return this.builtinArrayBuffer;
1659     }
1660 
1661     ScriptObject getArrayBufferPrototype() {
1662         return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1663     }
1664 
1665     private synchronized ScriptFunction getBuiltinDataView() {
1666         if (this.builtinDataView == null) {
1667             this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1668         }
1669         return this.builtinDataView;
1670     }
1671 
1672     ScriptObject getDataViewPrototype() {
1673         return ScriptFunction.getPrototype(getBuiltinDataView());
1674     }
1675 
1676     private synchronized ScriptFunction getBuiltinInt8Array() {
1677         if (this.builtinInt8Array == null) {
1678             this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1679         }
1680         return this.builtinInt8Array;
1681     }
1682 
1683     ScriptObject getInt8ArrayPrototype() {
1684         return ScriptFunction.getPrototype(getBuiltinInt8Array());
1685     }
1686 
1687     private synchronized ScriptFunction getBuiltinUint8Array() {
1688         if (this.builtinUint8Array == null) {
1689             this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1690         }
1691         return this.builtinUint8Array;
1692     }
1693 
1694     ScriptObject getUint8ArrayPrototype() {
1695         return ScriptFunction.getPrototype(getBuiltinUint8Array());
1696     }
1697 
1698     private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1699         if (this.builtinUint8ClampedArray == null) {
1700             this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1701         }
1702         return this.builtinUint8ClampedArray;
1703     }
1704 
1705     ScriptObject getUint8ClampedArrayPrototype() {
1706         return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1707     }
1708 
1709     private synchronized ScriptFunction getBuiltinInt16Array() {
1710         if (this.builtinInt16Array == null) {
1711             this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1712         }
1713         return this.builtinInt16Array;
1714     }
1715 
1716     ScriptObject getInt16ArrayPrototype() {
1717         return ScriptFunction.getPrototype(getBuiltinInt16Array());
1718     }
1719 
1720     private synchronized ScriptFunction getBuiltinUint16Array() {
1721         if (this.builtinUint16Array == null) {
1722             this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1723         }
1724         return this.builtinUint16Array;
1725     }
1726 
1727     ScriptObject getUint16ArrayPrototype() {
1728         return ScriptFunction.getPrototype(getBuiltinUint16Array());
1729     }
1730 
1731     private synchronized ScriptFunction getBuiltinInt32Array() {
1732         if (this.builtinInt32Array == null) {
1733             this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1734         }
1735         return this.builtinInt32Array;
1736     }
1737 
1738     ScriptObject getInt32ArrayPrototype() {
1739         return ScriptFunction.getPrototype(getBuiltinInt32Array());
1740     }
1741 
1742     private synchronized ScriptFunction getBuiltinUint32Array() {
1743         if (this.builtinUint32Array == null) {
1744             this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1745         }
1746         return this.builtinUint32Array;
1747     }
1748 
1749     ScriptObject getUint32ArrayPrototype() {
1750         return ScriptFunction.getPrototype(getBuiltinUint32Array());
1751     }
1752 
1753     private synchronized ScriptFunction getBuiltinFloat32Array() {
1754         if (this.builtinFloat32Array == null) {
1755             this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1756         }
1757         return this.builtinFloat32Array;
1758     }
1759 
1760     ScriptObject getFloat32ArrayPrototype() {
1761         return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1762     }
1763 
1764     private synchronized ScriptFunction getBuiltinFloat64Array() {
1765         if (this.builtinFloat64Array == null) {
1766             this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1767         }
1768         return this.builtinFloat64Array;
1769     }
1770 
1771     ScriptObject getFloat64ArrayPrototype() {
1772         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1773     }
1774 
1775     private ScriptFunction getBuiltinArray() {
1776         return builtinArray;
1777     }
1778 
1779     ScriptFunction getTypeErrorThrower() {
1780         return typeErrorThrower;
1781     }
1782 
1783     /**
1784      * Called from compiled script code to test if builtin has been overridden
1785      *
1786      * @return true if builtin array has not been overridden
1787      */
1788     public static boolean isBuiltinArray() {
1789         final Global instance = Global.instance();
1790         return instance.array == instance.getBuiltinArray();
1791     }
1792 
1793     private ScriptFunction getBuiltinBoolean() {
1794         return builtinBoolean;
1795     }
1796 
1797     /**
1798      * Called from compiled script code to test if builtin has been overridden
1799      *
1800      * @return true if builtin boolean has not been overridden
1801      */
1802     public static boolean isBuiltinBoolean() {
1803         final Global instance = Global.instance();
1804         return instance._boolean == instance.getBuiltinBoolean();
1805     }
1806 
1807     private synchronized ScriptFunction getBuiltinDate() {
1808         if (this.builtinDate == null) {
1809             this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1810             final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
1811             // initialize default date
1812             this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
1813         }
1814         return this.builtinDate;
1815     }
1816 
1817     /**
1818      * Called from compiled script code to test if builtin has been overridden
1819      *
1820      * @return true if builtin date has not been overridden
1821      */
1822     public static boolean isBuiltinDate() {
1823         final Global instance = Global.instance();
1824         return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
1825     }
1826 
1827     private ScriptFunction getBuiltinError() {
1828         return builtinError;
1829     }
1830 
1831     /**
1832      * Called from compiled script code to test if builtin has been overridden
1833      *
1834      * @return true if builtin error has not been overridden
1835      */
1836     public static boolean isBuiltinError() {
1837         final Global instance = Global.instance();
1838         return instance.error == instance.getBuiltinError();
1839     }
1840 
1841     private synchronized ScriptFunction getBuiltinEvalError() {
1842         if (this.builtinEvalError == null) {
1843             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
1844         }
1845         return this.builtinEvalError;
1846     }
1847 
1848     /**
1849      * Called from compiled script code to test if builtin has been overridden
1850      *
1851      * @return true if builtin eval error has not been overridden
1852      */
1853     public static boolean isBuiltinEvalError() {
1854         final Global instance = Global.instance();
1855         return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
1856     }
1857 
1858     private ScriptFunction getBuiltinFunction() {
1859         return builtinFunction;
1860     }
1861 
1862     /**
1863      * Called from compiled script code to test if builtin has been overridden
1864      *
1865      * @return true if builtin function has not been overridden
1866      */
1867     public static boolean isBuiltinFunction() {
1868         final Global instance = Global.instance();
1869         return instance.function == instance.getBuiltinFunction();
1870     }
1871 
1872     /**
1873      * Get the switchpoint used to check property changes for Function.prototype.apply
1874      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1875      */
1876     public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1877         return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1878     }
1879 
1880     private static boolean isBuiltinFunctionProperty(final String name) {
1881         final Global instance = Global.instance();
1882         final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1883         if (builtinFunction == null) {
1884             return false; //conservative for compile-only mode
1885         }
1886         final boolean isBuiltinFunction = instance.function == builtinFunction;
1887         return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1888     }
1889 
1890     /**
1891      * Check if the Function.prototype.apply has not been replaced
1892      * @return true if Function.prototype.apply has been replaced
1893      */
1894     public static boolean isBuiltinFunctionPrototypeApply() {
1895         return isBuiltinFunctionProperty("apply");
1896     }
1897 
1898     /**
1899      * Check if the Function.prototype.apply has not been replaced
1900      * @return true if Function.prototype.call has been replaced
1901      */
1902     public static boolean isBuiltinFunctionPrototypeCall() {
1903         return isBuiltinFunctionProperty("call");
1904     }
1905 
1906     private synchronized ScriptFunction getBuiltinJSAdapter() {
1907         if (this.builtinJSAdapter == null) {
1908             this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1909         }
1910         return builtinJSAdapter;
1911     }
1912 
1913     /**
1914      * Called from compiled script code to test if builtin has been overridden
1915      *
1916      * @return true if builtin JSAdapter has not been overridden
1917      */
1918     public static boolean isBuiltinJSAdapter() {
1919         final Global instance = Global.instance();
1920         return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
1921     }
1922 
1923     private synchronized ScriptObject getBuiltinJSON() {
1924         if (this.builtinJSON == null) {
1925             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1926         }
1927         return this.builtinJSON;
1928     }
1929 
1930     /**
1931      * Called from compiled script code to test if builtin has been overridden
1932      *
1933      * @return true if builtin JSON has has not been overridden
1934      */
1935     public static boolean isBuiltinJSON() {
1936         final Global instance = Global.instance();
1937         return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
1938     }
1939 
1940     private ScriptObject getBuiltinJava() {
1941         return builtinJava;
1942     }
1943 
1944     /**
1945      * Called from compiled script code to test if builtin has been overridden
1946      *
1947      * @return true if builtin Java has not been overridden
1948      */
1949     public static boolean isBuiltinJava() {
1950         final Global instance = Global.instance();
1951         return instance.java == instance.getBuiltinJava();
1952     }
1953 
1954     private ScriptObject getBuiltinJavax() {
1955         return builtinJavax;
1956     }
1957 
1958     /**
1959      * Called from compiled script code to test if builtin has been overridden
1960      *
1961      * @return true if builtin Javax has not been overridden
1962      */
1963     public static boolean isBuiltinJavax() {
1964         final Global instance = Global.instance();
1965         return instance.javax == instance.getBuiltinJavax();
1966     }
1967 
1968     private synchronized ScriptFunction getBuiltinJavaImporter() {
1969         if (this.builtinJavaImporter == null) {
1970             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1971         }
1972         return this.builtinJavaImporter;
1973     }
1974 
1975     private synchronized ScriptObject getBuiltinJavaApi() {
1976         if (this.builtinJavaApi == null) {
1977             this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1978         }
1979         return this.builtinJavaApi;
1980     }
1981 
1982     /**
1983      * Called from compiled script code to test if builtin has been overridden
1984      *
1985      * @return true if builtin Java importer has not been overridden
1986      */
1987     public static boolean isBuiltinJavaImporter() {
1988         final Global instance = Global.instance();
1989         return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
1990     }
1991 
1992     /**
1993      * Called from compiled script code to test if builtin has been overridden
1994      *
1995      * @return true if builtin math has not been overridden
1996      */
1997     public static boolean isBuiltinMath() {
1998         final Global instance = Global.instance();
1999         return instance.math == instance.builtinMath;
2000     }
2001 
2002     private ScriptFunction getBuiltinNumber() {
2003         return builtinNumber;
2004     }
2005 
2006     /**
2007      * Called from compiled script code to test if builtin has been overridden
2008      *
2009      * @return true if builtin number has not been overridden
2010      */
2011     public static boolean isBuiltinNumber() {
2012         final Global instance = Global.instance();
2013         return instance.number == instance.getBuiltinNumber();
2014     }
2015 
2016     private ScriptFunction getBuiltinObject() {
2017         return builtinObject;
2018     }
2019 
2020     /**
2021      * Called from compiled script code to test if builtin has been overridden
2022      *
2023      * @return true if builtin object has not been overridden
2024      */
2025     public static boolean isBuiltinObject() {
2026         final Global instance = Global.instance();
2027         return instance.object == instance.getBuiltinObject();
2028     }
2029 
2030     private ScriptObject getBuiltinPackages() {
2031         return builtinPackages;
2032     }
2033 
2034     /**
2035      * Called from compiled script code to test if builtin has been overridden
2036      *
2037      * @return true if builtin package has not been overridden
2038      */
2039     public static boolean isBuiltinPackages() {
2040         final Global instance = Global.instance();
2041         return instance.packages == instance.getBuiltinPackages();
2042     }
2043 
2044     private synchronized ScriptFunction getBuiltinRangeError() {
2045         if (this.builtinRangeError == null) {
2046             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
2047         }
2048         return builtinRangeError;
2049     }
2050 
2051     /**
2052      * Called from compiled script code to test if builtin has been overridden
2053      *
2054      * @return true if builtin range error has not been overridden
2055      */
2056     public static boolean isBuiltinRangeError() {
2057         final Global instance = Global.instance();
2058         return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
2059     }
2060 
2061     private synchronized ScriptFunction getBuiltinReferenceError() {
2062         return builtinReferenceError;
2063     }
2064 
2065     /**
2066      * Called from compiled script code to test if builtin has been overridden
2067      *
2068      * @return true if builtin reference error has not been overridden
2069      */
2070     public static boolean isBuiltinReferenceError() {
2071         final Global instance = Global.instance();
2072         return instance.referenceError == instance.getBuiltinReferenceError();
2073     }
2074 
2075     private synchronized ScriptFunction getBuiltinRegExp() {
2076         if (this.builtinRegExp == null) {
2077             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
2078             final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
2079             // initialize default regexp object
2080             this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
2081             // RegExp.prototype should behave like a RegExp object. So copy the
2082             // properties.
2083             regExpProto.addBoundProperties(DEFAULT_REGEXP);
2084         }
2085         return builtinRegExp;
2086     }
2087 
2088     /**
2089      * Called from compiled script code to test if builtin has been overridden
2090      *
2091      * @return true if builtin regexp has not been overridden
2092      */
2093     public static boolean isBuiltinRegExp() {
2094         final Global instance = Global.instance();
2095         return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
2096     }
2097 
2098     private ScriptFunction getBuiltinString() {
2099         return builtinString;
2100     }
2101 
2102     /**
2103      * Called from compiled script code to test if builtin has been overridden
2104      *
2105      * @return true if builtin Java has not been overridden
2106      */
2107     public static boolean isBuiltinString() {
2108         final Global instance = Global.instance();
2109         return instance.string == instance.getBuiltinString();
2110     }
2111 
2112     private ScriptFunction getBuiltinSyntaxError() {
2113         return builtinSyntaxError;
2114     }
2115 
2116     /**
2117      * Called from compiled script code to test if builtin has been overridden
2118      *
2119      * @return true if builtin syntax error has not been overridden
2120      */
2121     public static boolean isBuiltinSyntaxError() {
2122         final Global instance = Global.instance();
2123         return instance.syntaxError == instance.getBuiltinSyntaxError();
2124     }
2125 
2126     private ScriptFunction getBuiltinTypeError() {
2127         return builtinTypeError;
2128     }
2129 
2130     /**
2131      * Called from compiled script code to test if builtin has been overridden
2132      *
2133      * @return true if builtin type error has not been overridden
2134      */
2135     public static boolean isBuiltinTypeError() {
2136         final Global instance = Global.instance();
2137         return instance.typeError == instance.getBuiltinTypeError();
2138     }
2139 
2140     private synchronized ScriptFunction getBuiltinURIError() {
2141         if (this.builtinURIError == null) {
2142             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
2143         }
2144         return this.builtinURIError;
2145     }
2146 
2147     /**
2148      * Called from compiled script code to test if builtin has been overridden
2149      *
2150      * @return true if builtin URI error has not been overridden
2151      */
2152     public static boolean isBuiltinURIError() {
2153         final Global instance = Global.instance();
2154         return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
2155     }
2156 
2157     @Override
2158     public String getClassName() {
2159         return "global";
2160     }
2161 
2162     /**
2163      * Copy function used to clone NativeRegExp objects.
2164      *
2165      * @param regexp a NativeRegExp to clone
2166      *
2167      * @return copy of the given regexp object
2168      */
2169     public static Object regExpCopy(final Object regexp) {
2170         return new NativeRegExp((NativeRegExp)regexp);
2171     }
2172 
2173     /**
2174      * Convert given object to NativeRegExp type.
2175      *
2176      * @param obj object to be converted
2177      * @return NativeRegExp instance
2178      */
2179     public static NativeRegExp toRegExp(final Object obj) {
2180         if (obj instanceof NativeRegExp) {
2181             return (NativeRegExp)obj;
2182         }
2183         return new NativeRegExp(JSType.toString(obj));
2184     }
2185 
2186     /**
2187      * ECMA 9.9 ToObject implementation
2188      *
2189      * @param obj  an item for which to run ToObject
2190      * @return ToObject version of given item
2191      */
2192     public static Object toObject(final Object obj) {
2193         if (obj == null || obj == UNDEFINED) {
2194             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2195         }
2196 
2197         if (obj instanceof ScriptObject) {
2198             return obj;
2199         }
2200 
2201         return instance().wrapAsObject(obj);
2202     }
2203 
2204     /**
2205      * Allocate a new object array.
2206      *
2207      * @param initial object values.
2208      * @return the new array
2209      */
2210     public static NativeArray allocate(final Object[] initial) {
2211         ArrayData arrayData = ArrayData.allocate(initial);
2212 
2213         for (int index = 0; index < initial.length; index++) {
2214             final Object value = initial[index];
2215 
2216             if (value == ScriptRuntime.EMPTY) {
2217                 arrayData = arrayData.delete(index);
2218             }
2219         }
2220 
2221         return new NativeArray(arrayData);
2222     }
2223 
2224     /**
2225      * Allocate a new number array.
2226      *
2227      * @param initial number values.
2228      * @return the new array
2229      */
2230     public static NativeArray allocate(final double[] initial) {
2231         return new NativeArray(ArrayData.allocate(initial));
2232     }
2233 
2234     /**
2235      * Allocate a new long array.
2236      *
2237      * @param initial number values.
2238      * @return the new array
2239      */
2240     public static NativeArray allocate(final long[] initial) {
2241         return new NativeArray(ArrayData.allocate(initial));
2242     }
2243 
2244     /**
2245      * Allocate a new integer array.
2246      *
2247      * @param initial number values.
2248      * @return the new array
2249      */
2250     public static NativeArray allocate(final int[] initial) {
2251         return new NativeArray(ArrayData.allocate(initial));
2252     }
2253 
2254     /**
2255      * Allocate a new object array for arguments.
2256      *
2257      * @param arguments initial arguments passed.
2258      * @param callee reference to the function that uses arguments object
2259      * @param numParams actual number of declared parameters
2260      *
2261      * @return the new array
2262      */
2263     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2264         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2265     }
2266 
2267     /**
2268      * Called from generated to check if given function is the builtin 'eval'. If
2269      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2270      *
2271      * @param  fn function object that is checked
2272      * @return true if fn is the builtin eval
2273      */
2274     public static boolean isEval(final Object fn) {
2275         return fn == Global.instance().builtinEval;
2276     }
2277 
2278     /**
2279      * Called from generated to replace a location property placeholder with the actual location property value.
2280      *
2281      * @param  placeholder the value tested for being a placeholder for a location property
2282      * @param  locationProperty the actual value for the location property
2283      * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2284      */
2285     public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2286         return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2287     }
2288 
2289     /**
2290      * Called from runtime internals to check if the passed value is a location property placeholder.
2291      * @param  placeholder the value tested for being a placeholder for a location property
2292      * @return true if the value is a placeholder, false otherwise.
2293      */
2294     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2295         return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
2296     }
2297 
2298     /**
2299      * Create a new RegExp object.
2300      *
2301      * @param expression Regular expression.
2302      * @param options    Search options.
2303      *
2304      * @return New RegExp object.
2305      */
2306     public static Object newRegExp(final String expression, final String options) {
2307         if (options == null) {
2308             return new NativeRegExp(expression);
2309         }
2310         return new NativeRegExp(expression, options);
2311     }
2312 
2313     /**
2314      * Get the object prototype
2315      *
2316      * @return the object prototype
2317      */
2318     public static ScriptObject objectPrototype() {
2319         return Global.instance().getObjectPrototype();
2320     }
2321 
2322     /**
2323      * Create a new empty object instance.
2324      *
2325      * @return New empty object.
2326      */
2327     public static ScriptObject newEmptyInstance() {
2328         return Global.instance().newObject();
2329     }
2330 
2331     /**
2332      * Check if a given object is a ScriptObject, raises an exception if this is
2333      * not the case
2334      *
2335      * @param obj and object to check
2336      * @return the script object
2337      */
2338     public static ScriptObject checkObject(final Object obj) {
2339         if (!(obj instanceof ScriptObject)) {
2340             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2341         }
2342         return (ScriptObject)obj;
2343     }
2344 
2345     /**
2346      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2347      * if this object is null or undefined.
2348      *
2349      * @param obj an object to check
2350      */
2351     public static void checkObjectCoercible(final Object obj) {
2352         if (obj == null || obj == UNDEFINED) {
2353             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2354         }
2355     }
2356 
2357     /**
2358      * Get the current split state.
2359      *
2360      * @return current split state
2361      */
2362     @Override
2363     public int getSplitState() {
2364         return splitState;
2365     }
2366 
2367     /**
2368      * Set the current split state.
2369      *
2370      * @param state current split state
2371      */
2372     @Override
2373     public void setSplitState(final int state) {
2374         splitState = state;
2375     }
2376 
2377     /**
2378      * Return the ES6 global scope for lexically declared bindings.
2379      * @return the ES6 lexical global scope.
2380      */
2381     public final ScriptObject getLexicalScope() {
2382         assert context.getEnv()._es6;
2383         return lexicalScope;
2384     }
2385 
2386     @Override
2387     public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2388         PropertyMap ownMap = getMap();
2389         LexicalScope lexScope = null;
2390         PropertyMap lexicalMap = null;
2391         boolean hasLexicalDefinitions = false;
2392 
2393         if (context.getEnv()._es6) {
2394             lexScope = (LexicalScope) getLexicalScope();
2395             lexicalMap = lexScope.getMap();
2396 
2397             for (final jdk.nashorn.internal.runtime.Property property : properties) {
2398                 if (property.isLexicalBinding()) {
2399                     hasLexicalDefinitions = true;
2400                 }
2401                 // ES6 15.1.8 steps 6. and 7.
2402                 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2403                 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2404                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2405                 }
2406                 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2407                 if (lexicalProperty != null && !property.isConfigurable()) {
2408                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2409                 }
2410             }
2411         }
2412 
2413         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2414             if (property.isLexicalBinding()) {
2415                 assert lexScope != null;
2416                 lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property);
2417 
2418                 if (ownMap.findProperty(property.getKey()) != null) {
2419                     // If property exists in the global object invalidate any global constant call sites.
2420                     invalidateGlobalConstant(property.getKey());
2421                 }
2422             } else {
2423                 ownMap = addBoundProperty(ownMap, source, property);
2424             }
2425         }
2426 
2427         setMap(ownMap);
2428 
2429         if (hasLexicalDefinitions) {
2430             assert lexScope != null;
2431             lexScope.setMap(lexicalMap);
2432             invalidateLexicalSwitchPoint();
2433         }
2434     }
2435 
2436     @Override
2437     public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2438         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2439         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2440 
2441         if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2442             if (lexicalScope.hasOwnProperty(name)) {
2443                 return lexicalScope.findGetMethod(desc, request, operator);
2444             }
2445         }
2446 
2447         final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
2448 
2449         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2450         // because those are invalidated per-key in the addBoundProperties method above.
2451         // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
2452         // assuming this only applies to global constants. If other non-inherited properties will
2453         // start using switchpoints some time in the future we'll have to revisit this.
2454         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2455             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2456         }
2457 
2458         return invocation;
2459     }
2460 
2461     @Override
2462     protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
2463         if (lexicalScope != null && start != this && start.isScope()) {
2464             final FindProperty find = lexicalScope.findProperty(key, false);
2465             if (find != null) {
2466                 return find;
2467             }
2468         }
2469         return super.findProperty(key, deep, start);
2470     }
2471 
2472     @Override
2473     public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2474         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2475 
2476         if (lexicalScope != null && isScope) {
2477             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2478             if (lexicalScope.hasOwnProperty(name)) {
2479                 return lexicalScope.findSetMethod(desc, request);
2480             }
2481         }
2482 
2483         final GuardedInvocation invocation = super.findSetMethod(desc, request);
2484 
2485         if (isScope && context.getEnv()._es6) {
2486             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2487         }
2488 
2489         return invocation;
2490     }
2491 
2492     /**
2493      * Adds jjs shell interactive mode builtin functions to global scope.
2494      */
2495     public void addShellBuiltins() {
2496         Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
2497         addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2498 
2499         value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
2500         addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2501     }
2502 
2503     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2504         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2505         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2506             switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2507         }
2508         return switchPoint;
2509     }
2510 
2511     private synchronized void invalidateLexicalSwitchPoint() {
2512         if (lexicalScopeSwitchPoint != null) {
2513             context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2514             SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2515         }
2516     }
2517 
2518 
2519     @SuppressWarnings("unused")
2520     private static Object lexicalScopeFilter(final Object self) {
2521         if (self instanceof Global) {
2522             return ((Global) self).getLexicalScope();
2523         }
2524         return self;
2525     }
2526 
2527     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2528         final T func = initConstructor(name, clazz);
2529         tagBuiltinProperties(name, func);
2530         return func;
2531     }
2532 
2533     private void init(final ScriptEngine eng) {
2534         assert Context.getGlobal() == this : "this global is not set as current";
2535 
2536         final ScriptEnvironment env = getContext().getEnv();
2537 
2538         // initialize Function and Object constructor
2539         initFunctionAndObject();
2540 
2541         // Now fix Global's own proto.
2542         this.setInitialProto(getObjectPrototype());
2543 
2544         // initialize global function properties
2545         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
2546 
2547         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
2548                     new Specialization[] {
2549                     new Specialization(GlobalFunctions.PARSEINT_Z),
2550                     new Specialization(GlobalFunctions.PARSEINT_I),
2551                     new Specialization(GlobalFunctions.PARSEINT_J),
2552                     new Specialization(GlobalFunctions.PARSEINT_OI),
2553                     new Specialization(GlobalFunctions.PARSEINT_O) });
2554         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2555         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
2556                    new Specialization[] {
2557                         new Specialization(GlobalFunctions.IS_NAN_I),
2558                         new Specialization(GlobalFunctions.IS_NAN_J),
2559                         new Specialization(GlobalFunctions.IS_NAN_D) });
2560         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2561         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
2562         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
2563         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
2564         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2565         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
2566         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2567         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
2568         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
2569         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
2570         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
2571         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2572         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
2573         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
2574 
2575         // built-in constructors
2576         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2577         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2578         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2579         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2580         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2581 
2582         // initialize String.prototype.length to 0
2583         // add String.prototype.length
2584         final ScriptObject stringPrototype = getStringPrototype();
2585         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2586 
2587         // set isArray flag on Array.prototype
2588         final ScriptObject arrayPrototype = getArrayPrototype();
2589         arrayPrototype.setIsArray();
2590 
2591         // Error stuff
2592         initErrorObjects();
2593 
2594         // java access
2595         if (! env._no_java) {
2596             this.javaApi = LAZY_SENTINEL;
2597             this.javaImporter = LAZY_SENTINEL;
2598             initJavaAccess();
2599         }
2600 
2601         if (! env._no_typed_arrays) {
2602             this.arrayBuffer       = LAZY_SENTINEL;
2603             this.dataView          = LAZY_SENTINEL;
2604             this.int8Array         = LAZY_SENTINEL;
2605             this.uint8Array        = LAZY_SENTINEL;
2606             this.uint8ClampedArray = LAZY_SENTINEL;
2607             this.int16Array        = LAZY_SENTINEL;
2608             this.uint16Array       = LAZY_SENTINEL;
2609             this.int32Array        = LAZY_SENTINEL;
2610             this.uint32Array       = LAZY_SENTINEL;
2611             this.float32Array      = LAZY_SENTINEL;
2612             this.float64Array      = LAZY_SENTINEL;
2613         }
2614 
2615         if (env._scripting) {
2616             initScripting(env);
2617         }
2618 
2619         if (Context.DEBUG) {
2620             boolean debugOkay;
2621             final SecurityManager sm = System.getSecurityManager();
2622             if (sm != null) {
2623                 try {
2624                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2625                     debugOkay = true;
2626                 } catch (final SecurityException ignored) {
2627                     // if no permission, don't initialize Debug object
2628                     debugOkay = false;
2629                 }
2630 
2631             } else {
2632                 debugOkay = true;
2633             }
2634 
2635             if (debugOkay) {
2636                 initDebug();
2637             }
2638         }
2639 
2640         copyBuiltins();
2641 
2642         // expose script (command line) arguments as "arguments" property of global
2643         arguments = wrapAsObject(env.getArguments().toArray());
2644         if (env._scripting) {
2645             // synonym for "arguments" in scripting mode
2646             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2647         }
2648 
2649         if (eng != null) {
2650             // default file name
2651             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2652             // __noSuchProperty__ hook for ScriptContext search of missing variables
2653             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2654             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2655         }
2656     }
2657 
2658     private void initErrorObjects() {
2659         // Error objects
2660         this.builtinError = initConstructor("Error", ScriptFunction.class);
2661         final ScriptObject errorProto = getErrorPrototype();
2662 
2663         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2664         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2665         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2666         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2667         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2668         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2669         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2670         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2671         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2672         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2673         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2674         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2675         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2676 
2677         // ECMA 15.11.4.2 Error.prototype.name
2678         // Error.prototype.name = "Error";
2679         errorProto.set(NativeError.NAME, "Error", 0);
2680         // ECMA 15.11.4.3 Error.prototype.message
2681         // Error.prototype.message = "";
2682         errorProto.set(NativeError.MESSAGE, "", 0);
2683 
2684         tagBuiltinProperties("Error", builtinError);
2685 
2686         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2687         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2688         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2689     }
2690 
2691     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2692         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2693         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2694         prototype.set(NativeError.NAME, name, 0);
2695         prototype.set(NativeError.MESSAGE, "", 0);
2696         prototype.setInitialProto(errorProto);
2697         tagBuiltinProperties(name, cons);
2698         return cons;
2699     }
2700 
2701     private void initJavaAccess() {
2702         final ScriptObject objectProto = getObjectPrototype();
2703         this.builtinPackages = new NativeJavaPackage("", objectProto);
2704         this.builtinCom = new NativeJavaPackage("com", objectProto);
2705         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2706         this.builtinJava = new NativeJavaPackage("java", objectProto);
2707         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2708         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2709         this.builtinOrg = new NativeJavaPackage("org", objectProto);
2710     }
2711 
2712     private void initScripting(final ScriptEnvironment scriptEnv) {
2713         Object value;
2714         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2715         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2716 
2717         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2718         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2719 
2720         final String execName = ScriptingFunctions.EXEC_NAME;
2721         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2722         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2723 
2724         // Nashorn extension: global.echo (scripting-mode-only)
2725         // alias for "print"
2726         value = get("print");
2727         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2728 
2729         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2730         final ScriptObject options = newObject();
2731         copyOptions(options, scriptEnv);
2732         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2733 
2734         // Nashorn extension: global.$ENV (scripting-mode-only)
2735         if (System.getSecurityManager() == null) {
2736             // do not fill $ENV if we have a security manager around
2737             // Retrieve current state of ENV variables.
2738             final ScriptObject env = newObject();
2739             env.putAll(System.getenv(), scriptEnv._strict);
2740 
2741             // Some platforms, e.g., Windows, do not define the PWD environment
2742             // variable, so that the $ENV.PWD property needs to be explicitly
2743             // set.
2744             if (!env.containsKey(ScriptingFunctions.PWD_NAME)) {
2745                 env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
2746             }
2747 
2748             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2749         } else {
2750             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2751         }
2752 
2753         // add other special properties for exec support
2754         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2755         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2756         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2757     }
2758 
2759     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2760         for (final Field f : scriptEnv.getClass().getFields()) {
2761             try {
2762                 options.set(f.getName(), f.get(scriptEnv), 0);
2763             } catch (final IllegalArgumentException | IllegalAccessException exp) {
2764                 throw new RuntimeException(exp);
2765             }
2766         }
2767     }
2768 
2769     private void copyBuiltins() {
2770         this.array             = this.builtinArray;
2771         this._boolean          = this.builtinBoolean;
2772         this.error             = this.builtinError;
2773         this.function          = this.builtinFunction;
2774         this.com               = this.builtinCom;
2775         this.edu               = this.builtinEdu;
2776         this.java              = this.builtinJava;
2777         this.javafx            = this.builtinJavafx;
2778         this.javax             = this.builtinJavax;
2779         this.org               = this.builtinOrg;
2780         this.math              = this.builtinMath;
2781         this.number            = this.builtinNumber;
2782         this.object            = this.builtinObject;
2783         this.packages          = this.builtinPackages;
2784         this.referenceError    = this.builtinReferenceError;
2785         this.string            = this.builtinString;
2786         this.syntaxError       = this.builtinSyntaxError;
2787         this.typeError         = this.builtinTypeError;
2788     }
2789 
2790     private void initDebug() {
2791         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2792     }
2793 
2794     private Object printImpl(final boolean newLine, final Object... objects) {
2795         final ScriptContext sc = currentContext();
2796         @SuppressWarnings("resource")
2797         final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
2798         final StringBuilder sb = new StringBuilder();
2799 
2800         for (final Object obj : objects) {
2801             if (sb.length() != 0) {
2802                 sb.append(' ');
2803             }
2804 
2805             sb.append(JSType.toString(obj));
2806         }
2807 
2808         // Print all at once to ensure thread friendly result.
2809         if (newLine) {
2810             out.println(sb.toString());
2811         } else {
2812             out.print(sb.toString());
2813         }
2814 
2815         out.flush();
2816 
2817         return UNDEFINED;
2818     }
2819 
2820     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2821         try {
2822             // Assuming class name pattern for built-in JS constructors.
2823             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2824 
2825             sb.append("Native");
2826             sb.append(name);
2827             sb.append("$Constructor");
2828 
2829             final Class<?> funcClass = Class.forName(sb.toString());
2830             final T res = clazz.cast(funcClass.newInstance());
2831 
2832             if (res instanceof ScriptFunction) {
2833                 // All global constructor prototypes are not-writable,
2834                 // not-enumerable and not-configurable.
2835                 final ScriptFunction func = (ScriptFunction)res;
2836                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2837             }
2838 
2839             if (res.getProto() == null) {
2840                 res.setInitialProto(getObjectPrototype());
2841             }
2842 
2843             res.setIsBuiltin();
2844 
2845             return res;
2846         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2847             throw new RuntimeException(e);
2848         }
2849     }
2850 
2851     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2852         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2853 
2854         list.addAll(Arrays.asList(func.getMap().getProperties()));
2855 
2856         if (func instanceof ScriptFunction) {
2857             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2858             if (proto != null) {
2859                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2860             }
2861         }
2862 
2863         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2864         if (prop != null) {
2865             list.add(prop);
2866         }
2867 
2868         return list;
2869     }
2870 
2871     /**
2872      * Given a builtin object, traverse its properties recursively and associate them with a name that
2873      * will be a key to their invalidation switchpoint.
2874      * @param name name for key
2875      * @param func builtin script object
2876      */
2877     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2878         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2879         if (sp == null) {
2880             sp = context.newBuiltinSwitchPoint(name);
2881         }
2882 
2883         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2884         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2885         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2886             prop.setBuiltinSwitchPoint(sp);
2887         }
2888     }
2889 
2890     // Function and Object constructors are inter-dependent. Also,
2891     // Function.prototype
2892     // functions are not properly initialized. We fix the references here.
2893     // NOTE: be careful if you want to re-order the operations here. You may
2894     // have
2895     // to play with object references carefully!!
2896     private void initFunctionAndObject() {
2897         // First-n-foremost is Function
2898 
2899         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2900 
2901         // create global anonymous function
2902         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2903         // need to copy over members of Function.prototype to anon function
2904         anon.addBoundProperties(getFunctionPrototype());
2905 
2906         // Function.prototype === Object.getPrototypeOf(Function) ===
2907         // <anon-function>
2908         builtinFunction.setInitialProto(anon);
2909         builtinFunction.setPrototype(anon);
2910         anon.set("constructor", builtinFunction, 0);
2911         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2912 
2913         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2914         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2915         typeErrorThrower.setPrototype(UNDEFINED);
2916         // Non-constructor built-in functions do not have "prototype" property
2917         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2918         typeErrorThrower.preventExtensions();
2919 
2920         // now initialize Object
2921         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2922         final ScriptObject ObjectPrototype = getObjectPrototype();
2923         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2924         anon.setInitialProto(ObjectPrototype);
2925 
2926         // ES6 draft compliant __proto__ property of Object.prototype
2927         // accessors on Object.prototype for "__proto__"
2928         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2929         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2930         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2931 
2932         // Function valued properties of Function.prototype were not properly
2933         // initialized. Because, these were created before global.function and
2934         // global.object were not initialized.
2935         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2936         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2937             final Object key = property.getKey();
2938             final Object value = builtinFunction.get(key);
2939 
2940             if (value instanceof ScriptFunction && value != anon) {
2941                 final ScriptFunction func = (ScriptFunction)value;
2942                 func.setInitialProto(getFunctionPrototype());
2943                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2944                 if (prototype != null) {
2945                     prototype.setInitialProto(ObjectPrototype);
2946                 }
2947             }
2948         }
2949 
2950         // For function valued properties of Object and Object.prototype, make
2951         // sure prototype's proto chain ends with Object.prototype
2952         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2953             final Object key = property.getKey();
2954             final Object value = builtinObject.get(key);
2955 
2956             if (value instanceof ScriptFunction) {
2957                 final ScriptFunction func = (ScriptFunction)value;
2958                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2959                 if (prototype != null) {
2960                     prototype.setInitialProto(ObjectPrototype);
2961                 }
2962             }
2963         }
2964 
2965         properties = getObjectPrototype().getMap().getProperties();
2966 
2967         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2968             final Object key   = property.getKey();
2969             if (key.equals("constructor")) {
2970                 continue;
2971             }
2972 
2973             final Object value = ObjectPrototype.get(key);
2974             if (value instanceof ScriptFunction) {
2975                 final ScriptFunction func = (ScriptFunction)value;
2976                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2977                 if (prototype != null) {
2978                     prototype.setInitialProto(ObjectPrototype);
2979                 }
2980             }
2981         }
2982 
2983         tagBuiltinProperties("Object", builtinObject);
2984         tagBuiltinProperties("Function", builtinFunction);
2985         tagBuiltinProperties("Function", anon);
2986     }
2987 
2988     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2989         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2990     }
2991 
2992     RegExpResult getLastRegExpResult() {
2993         return lastRegExpResult;
2994     }
2995 
2996     void setLastRegExpResult(final RegExpResult regExpResult) {
2997         this.lastRegExpResult = regExpResult;
2998     }
2999 
3000     @Override
3001     protected boolean isGlobal() {
3002         return true;
3003     }
3004 
3005     /**
3006      * A class representing the ES6 global lexical scope.
3007      */
3008     private static class LexicalScope extends ScriptObject {
3009 
3010         LexicalScope(final Global global) {
3011             super(global, PropertyMap.newMap());
3012         }
3013 
3014         @Override
3015         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
3016             return filterInvocation(super.findGetMethod(desc, request, operator));
3017         }
3018 
3019         @Override
3020         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
3021             return filterInvocation(super.findSetMethod(desc, request));
3022         }
3023 
3024         @Override
3025         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
3026             // We override this method just to make it callable by Global
3027             return super.addBoundProperty(propMap, source, property);
3028         }
3029 
3030         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
3031             final MethodType type = invocation.getInvocation().type();
3032             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
3033         }
3034     }
3035 
3036 }