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