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