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