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




2333         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);

2334         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2335 
2336         // initialize String.prototype.length to 0
2337         // add String.prototype.length
2338         final ScriptObject stringPrototype = getStringPrototype();
2339         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2340 
2341         // set isArray flag on Array.prototype
2342         final ScriptObject arrayPrototype = getArrayPrototype();
2343         arrayPrototype.setIsArray();
2344 










2345         // Error stuff
2346         initErrorObjects();
2347 
2348         // java access
2349         if (! env._no_java) {
2350             this.javaApi = LAZY_SENTINEL;
2351             this.javaImporter = LAZY_SENTINEL;
2352             initJavaAccess();
2353         }
2354 
2355         if (! env._no_typed_arrays) {
2356             this.arrayBuffer       = LAZY_SENTINEL;
2357             this.dataView          = LAZY_SENTINEL;
2358             this.int8Array         = LAZY_SENTINEL;
2359             this.uint8Array        = LAZY_SENTINEL;
2360             this.uint8ClampedArray = LAZY_SENTINEL;
2361             this.int16Array        = LAZY_SENTINEL;
2362             this.uint16Array       = LAZY_SENTINEL;
2363             this.int32Array        = LAZY_SENTINEL;
2364             this.uint32Array       = LAZY_SENTINEL;
2365             this.float32Array      = LAZY_SENTINEL;
2366             this.float64Array      = LAZY_SENTINEL;
2367         }
2368 
2369         if (env._scripting) {
2370             initScripting(env);
2371         }
2372 
2373         if (Context.DEBUG) {
2374             boolean debugOkay;
2375             final SecurityManager sm = System.getSecurityManager();
2376             if (sm != null) {
2377                 try {
2378                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2379                     debugOkay = true;
2380                 } catch (final SecurityException ignored) {
2381                     // if no permission, don't initialize Debug object
2382                     debugOkay = false;
2383                 }
2384 
2385             } else {
2386                 debugOkay = true;
2387             }
2388 
2389             if (debugOkay) {
2390                 initDebug();
2391             }
2392         }
2393 
2394         copyBuiltins();
2395 
2396         // expose script (command line) arguments as "arguments" property of global
2397         arguments = wrapAsObject(env.getArguments().toArray());
2398         if (env._scripting) {
2399             // synonym for "arguments" in scripting mode
2400             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2401         }
2402 
2403         if (eng != null) {
2404             // default file name
2405             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2406             // __noSuchProperty__ hook for ScriptContext search of missing variables
2407             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2408             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2409         }
2410     }
2411 
2412     private void initErrorObjects() {
2413         // Error objects
2414         this.builtinError = initConstructor("Error", ScriptFunction.class);
2415         final ScriptObject errorProto = getErrorPrototype();
2416 
2417         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2418         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2419         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2420         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2421         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2422         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2423         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2424         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2425         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2426         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2427         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2428         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2429         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2430 
2431         // ECMA 15.11.4.2 Error.prototype.name
2432         // Error.prototype.name = "Error";
2433         errorProto.set(NativeError.NAME, "Error", 0);
2434         // ECMA 15.11.4.3 Error.prototype.message
2435         // Error.prototype.message = "";
2436         errorProto.set(NativeError.MESSAGE, "", 0);
2437 
2438         tagBuiltinProperties("Error", builtinError);
2439 


2440         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2441         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2442         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);

2443     }
2444 
2445     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2446         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2447         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2448         prototype.set(NativeError.NAME, name, 0);
2449         prototype.set(NativeError.MESSAGE, "", 0);
2450         prototype.setInitialProto(errorProto);
2451         tagBuiltinProperties(name, cons);
2452         return cons;
2453     }
2454 
2455     private void initJavaAccess() {
2456         final ScriptObject objectProto = getObjectPrototype();
2457         this.builtinPackages = new NativeJavaPackage("", objectProto);
2458         this.builtinCom = new NativeJavaPackage("com", objectProto);
2459         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2460         this.builtinJava = new NativeJavaPackage("java", objectProto);
2461         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2462         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2463         this.builtinOrg = new NativeJavaPackage("org", objectProto);


2464     }
2465 
2466     private void initScripting(final ScriptEnvironment scriptEnv) {
2467         Object value;
2468         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2469         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2470 
2471         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2472         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2473 
2474         final String execName = ScriptingFunctions.EXEC_NAME;
2475         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2476         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2477 
2478         // Nashorn extension: global.echo (scripting-mode-only)
2479         // alias for "print"
2480         value = get("print");
2481         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2482 
2483         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2484         final ScriptObject options = newObject();
2485         copyOptions(options, scriptEnv);
2486         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2487 
2488         // Nashorn extension: global.$ENV (scripting-mode-only)
2489         if (System.getSecurityManager() == null) {
2490             // do not fill $ENV if we have a security manager around
2491             // Retrieve current state of ENV variables.
2492             final ScriptObject env = newObject();
2493             env.putAll(System.getenv(), scriptEnv._strict);
2494             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2495         } else {
2496             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2497         }
2498 
2499         // add other special properties for exec support
2500         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2501         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2502         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2503     }
2504 
2505     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2506         for (final Field f : scriptEnv.getClass().getFields()) {
2507             try {
2508                 options.set(f.getName(), f.get(scriptEnv), 0);
2509             } catch (final IllegalArgumentException | IllegalAccessException exp) {
2510                 throw new RuntimeException(exp);
2511             }
2512         }
2513     }
2514 















2515     private void copyBuiltins() {
2516         this.array             = this.builtinArray;
2517         this._boolean          = this.builtinBoolean;

2518         this.error             = this.builtinError;

2519         this.function          = this.builtinFunction;


2520         this.com               = this.builtinCom;
2521         this.edu               = this.builtinEdu;
2522         this.java              = this.builtinJava;
2523         this.javafx            = this.builtinJavafx;
2524         this.javax             = this.builtinJavax;
2525         this.org               = this.builtinOrg;



2526         this.number            = this.builtinNumber;
2527         this.object            = this.builtinObject;
2528         this.packages          = this.builtinPackages;

2529         this.referenceError    = this.builtinReferenceError;

2530         this.string            = this.builtinString;
2531         this.syntaxError       = this.builtinSyntaxError;
2532         this.typeError         = this.builtinTypeError;












2533     }
2534 
2535     private void initDebug() {
2536         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2537     }
2538 
2539     private Object printImpl(final boolean newLine, final Object... objects) {
2540         @SuppressWarnings("resource")
2541         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2542         final StringBuilder sb = new StringBuilder();
2543 
2544         for (final Object obj : objects) {
2545             if (sb.length() != 0) {
2546                 sb.append(' ');
2547             }
2548 
2549             sb.append(JSType.toString(obj));
2550         }
2551 
2552         // Print all at once to ensure thread friendly result.
2553         if (newLine) {
2554             out.println(sb.toString());
2555         } else {
2556             out.print(sb.toString());
2557         }
2558 
2559         out.flush();
2560 
2561         return UNDEFINED;
2562     }
2563 
2564     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2565         try {
2566             // Assuming class name pattern for built-in JS constructors.
2567             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2568 
2569             sb.append("Native");
2570             sb.append(name);
2571             sb.append("$Constructor");
2572 
2573             final Class<?> funcClass = Class.forName(sb.toString());
2574             final T res = clazz.cast(funcClass.newInstance());
2575 
2576             if (res instanceof ScriptFunction) {
2577                 // All global constructor prototypes are not-writable,
2578                 // not-enumerable and not-configurable.
2579                 final ScriptFunction func = (ScriptFunction)res;
2580                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2581             }
2582 
2583             if (res.getProto() == null) {
2584                 res.setInitialProto(getObjectPrototype());
2585             }
2586 
2587             res.setIsBuiltin();
2588 
2589             return res;
2590         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2591             throw new RuntimeException(e);
2592         }
2593     }
2594 
2595     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2596         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2597 
2598         list.addAll(Arrays.asList(func.getMap().getProperties()));
2599 
2600         if (func instanceof ScriptFunction) {
2601             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2602             if (proto != null) {
2603                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2604             }
2605         }
2606 
2607         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2608         if (prop != null) {
2609             list.add(prop);
2610         }
2611 
2612         return list;
2613     }
2614 
2615     /**
2616      * Given a builtin object, traverse its properties recursively and associate them with a name that
2617      * will be a key to their invalidation switchpoint.
2618      * @param name name for key
2619      * @param func builtin script object
2620      */
2621     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2622         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2623         if (sp == null) {
2624             sp = context.newBuiltinSwitchPoint(name);
2625         }
2626 
2627         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2628         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2629         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2630             prop.setBuiltinSwitchPoint(sp);
2631         }
2632     }
2633 
2634     // Function and Object constructors are inter-dependent. Also,
2635     // Function.prototype
2636     // functions are not properly initialized. We fix the references here.
2637     // NOTE: be careful if you want to re-order the operations here. You may
2638     // have
2639     // to play with object references carefully!!
2640     private void initFunctionAndObject() {
2641         // First-n-foremost is Function
2642 
2643         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2644 
2645         // create global anonymous function
2646         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2647         // need to copy over members of Function.prototype to anon function
2648         anon.addBoundProperties(getFunctionPrototype());
2649 
2650         // Function.prototype === Object.getPrototypeOf(Function) ===
2651         // <anon-function>
2652         builtinFunction.setInitialProto(anon);
2653         builtinFunction.setPrototype(anon);
2654         anon.set("constructor", builtinFunction, 0);
2655         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2656 
2657         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2658         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2659         typeErrorThrower.setPrototype(UNDEFINED);
2660         // Non-constructor built-in functions do not have "prototype" property
2661         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2662         typeErrorThrower.preventExtensions();
2663 
2664         // now initialize Object
2665         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2666         final ScriptObject ObjectPrototype = getObjectPrototype();
2667         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2668         anon.setInitialProto(ObjectPrototype);
2669 
2670         // ES6 draft compliant __proto__ property of Object.prototype
2671         // accessors on Object.prototype for "__proto__"
2672         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2673         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2674         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2675 
2676         // Function valued properties of Function.prototype were not properly
2677         // initialized. Because, these were created before global.function and
2678         // global.object were not initialized.
2679         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2680         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2681             final Object key = property.getKey();
2682             final Object value = builtinFunction.get(key);
2683 
2684             if (value instanceof ScriptFunction && value != anon) {
2685                 final ScriptFunction func = (ScriptFunction)value;
2686                 func.setInitialProto(getFunctionPrototype());
2687                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2688                 if (prototype != null) {
2689                     prototype.setInitialProto(ObjectPrototype);
2690                 }
2691             }
2692         }
2693 
2694         // For function valued properties of Object and Object.prototype, make
2695         // sure prototype's proto chain ends with Object.prototype
2696         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2697             final Object key = property.getKey();
2698             final Object value = builtinObject.get(key);
2699 
2700             if (value instanceof ScriptFunction) {
2701                 final ScriptFunction func = (ScriptFunction)value;
2702                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2703                 if (prototype != null) {
2704                     prototype.setInitialProto(ObjectPrototype);
2705                 }
2706             }
2707         }
2708 
2709         properties = getObjectPrototype().getMap().getProperties();
2710 
2711         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2712             final Object key   = property.getKey();
2713             if (key.equals("constructor")) {
2714                 continue;
2715             }
2716 
2717             final Object value = ObjectPrototype.get(key);
2718             if (value instanceof ScriptFunction) {
2719                 final ScriptFunction func = (ScriptFunction)value;
2720                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2721                 if (prototype != null) {
2722                     prototype.setInitialProto(ObjectPrototype);
2723                 }
2724             }
2725         }
2726 
2727         tagBuiltinProperties("Object", builtinObject);
2728         tagBuiltinProperties("Function", builtinFunction);
2729         tagBuiltinProperties("Function", anon);
2730     }
2731 
2732     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2733         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2734     }
2735 
2736     RegExpResult getLastRegExpResult() {
2737         return lastRegExpResult;
2738     }
2739 
2740     void setLastRegExpResult(final RegExpResult regExpResult) {
2741         this.lastRegExpResult = regExpResult;
2742     }
2743 
2744     @Override
2745     protected boolean isGlobal() {
2746         return true;
2747     }
2748 
2749     /**
2750      * A class representing the ES6 global lexical scope.
2751      */
2752     private static class LexicalScope extends ScriptObject {
2753 
2754         LexicalScope(final ScriptObject proto) {
2755             super(proto, PropertyMap.newMap());
2756         }
2757 
2758         @Override
2759         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2760             return filterInvocation(super.findGetMethod(desc, request, operator));
2761         }
2762 
2763         @Override
2764         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2765             return filterInvocation(super.findSetMethod(desc, request));
2766         }
2767 
2768         @Override
2769         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
2770             // We override this method just to make it callable by Global
2771             return super.addBoundProperty(propMap, source, property);
2772         }
2773 
2774         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
2775             final MethodType type = invocation.getInvocation().type();
2776             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
2777         }
2778     }
2779 
2780 }
--- EOF ---