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