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 
  81 /**
  82  * Representation of global scope.
  83  */
  84 @ScriptClass("Global")
  85 public final class Global extends ScriptObject implements Scope {
  86     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
  87     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
  88     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  89     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  90 
  91     /**
  92      * Optimistic builtin names that require switchpoint invalidation
  93      * upon assignment. Overly conservative, but works for now, to avoid
  94      * any complicated scope checks and especially heavy weight guards
  95      * like
  96      *
  97      * <pre>
  98      *     public boolean setterGuard(final Object receiver) {
  99      *         final Global          global = Global.instance();
 100      *         final ScriptObject    sobj   = global.getFunctionPrototype();
 101      *         final Object          apply  = sobj.get("apply");
 102      *         return apply == receiver;
 103      *     }
 104      * </pre>
 105      *
 106      * Naturally, checking for builtin classes like NativeFunction is cheaper,
 107      * it's when you start adding property checks for said builtins you have
 108      * problems with guard speed.
 109      */
 110 
 111     /** Nashorn extension: arguments array */
 112     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 113     public Object arguments;
 114 
 115     /** ECMA 15.1.2.2 parseInt (string , radix) */
 116     @Property(attributes = Attribute.NOT_ENUMERABLE)
 117     public Object parseInt;
 118 
 119     /** ECMA 15.1.2.3 parseFloat (string) */
 120     @Property(attributes = Attribute.NOT_ENUMERABLE)
 121     public Object parseFloat;
 122 
 123     /** ECMA 15.1.2.4 isNaN (number) */
 124     @Property(attributes = Attribute.NOT_ENUMERABLE)
 125     public Object isNaN;
 126 
 127     /** ECMA 15.1.2.5 isFinite (number) */
 128     @Property(attributes = Attribute.NOT_ENUMERABLE)
 129     public Object isFinite;
 130 
 131     /** ECMA 15.1.3.3 encodeURI */
 132     @Property(attributes = Attribute.NOT_ENUMERABLE)
 133     public Object encodeURI;
 134 
 135     /** ECMA 15.1.3.4 encodeURIComponent */
 136     @Property(attributes = Attribute.NOT_ENUMERABLE)
 137     public Object encodeURIComponent;
 138 
 139     /** ECMA 15.1.3.1 decodeURI */
 140     @Property(attributes = Attribute.NOT_ENUMERABLE)
 141     public Object decodeURI;
 142 
 143     /** ECMA 15.1.3.2 decodeURIComponent */
 144     @Property(attributes = Attribute.NOT_ENUMERABLE)
 145     public Object decodeURIComponent;
 146 
 147     /** ECMA B.2.1 escape (string) */
 148     @Property(attributes = Attribute.NOT_ENUMERABLE)
 149     public Object escape;
 150 
 151     /** ECMA B.2.2 unescape (string) */
 152     @Property(attributes = Attribute.NOT_ENUMERABLE)
 153     public Object unescape;
 154 
 155     /** Nashorn extension: global.print */
 156     @Property(attributes = Attribute.NOT_ENUMERABLE)
 157     public Object print;
 158 
 159     /** Nashorn extension: global.load */
 160     @Property(attributes = Attribute.NOT_ENUMERABLE)
 161     public Object load;
 162 
 163     /** Nashorn extension: global.loadWithNewGlobal */
 164     @Property(attributes = Attribute.NOT_ENUMERABLE)
 165     public Object loadWithNewGlobal;
 166 
 167     /** Nashorn extension: global.exit */
 168     @Property(attributes = Attribute.NOT_ENUMERABLE)
 169     public Object exit;
 170 
 171     /** Nashorn extension: global.quit */
 172     @Property(attributes = Attribute.NOT_ENUMERABLE)
 173     public Object quit;
 174 
 175     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 176     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 177     public final double NaN = Double.NaN;
 178 
 179     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 180     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 181     public final double Infinity = Double.POSITIVE_INFINITY;
 182 
 183     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 184     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 185     public final Object undefined = UNDEFINED;
 186 
 187     /** ECMA 15.1.2.1 eval(x) */
 188     @Property(attributes = Attribute.NOT_ENUMERABLE)
 189     public Object eval;
 190 
 191     /** ECMA 15.1.4.1 Object constructor. */
 192     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 193     public volatile Object object;
 194 
 195     /** ECMA 15.1.4.2 Function constructor. */
 196     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 197     public volatile Object function;
 198 
 199     /** ECMA 15.1.4.3 Array constructor. */
 200     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 201     public volatile Object array;
 202 
 203     /** ECMA 15.1.4.4 String constructor */
 204     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 205     public volatile Object string;
 206 
 207     /** ECMA 15.1.4.5 Boolean constructor */
 208     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 209     public volatile Object _boolean;
 210 
 211     /** ECMA 15.1.4.6 - Number constructor */
 212     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 213     public volatile Object number;
 214 
 215     /** ECMA 15.1.4.7 Date constructor */
 216     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 217     public volatile Object date;
 218 
 219     /** ECMA 15.1.4.8 RegExp constructor */
 220     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 221     public volatile Object regexp;
 222 
 223     /** ECMA 15.12 - The JSON object */
 224     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 225     public volatile Object json;
 226 
 227     /** Nashorn extension: global.JSAdapter */
 228     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 229     public volatile Object jsadapter;
 230 
 231     /** ECMA 15.8 - The Math object */
 232     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
 233     public volatile Object math;
 234 
 235     /** Error object */
 236     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
 237     public volatile Object error;
 238 
 239     /** EvalError object */
 240     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 241     public volatile Object evalError;
 242 
 243     /** RangeError object */
 244     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 245     public volatile Object rangeError;
 246 
 247     /** ReferenceError object */
 248     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
 249     public volatile Object referenceError;
 250 
 251     /** SyntaxError object */
 252     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
 253     public volatile Object syntaxError;
 254 
 255     /** TypeError object */
 256     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
 257     public volatile Object typeError;
 258 
 259     /** URIError object */
 260     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 261     public volatile Object uriError;
 262 
 263     /** ArrayBuffer object */
 264     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 265     public volatile Object arrayBuffer;
 266 
 267     /** DataView object */
 268     @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 269     public volatile Object dataView;
 270 
 271     /** TypedArray (int8) */
 272     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 273     public volatile Object int8Array;
 274 
 275     /** TypedArray (uint8) */
 276     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 277     public volatile Object uint8Array;
 278 
 279     /** TypedArray (uint8) - Clamped */
 280     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 281     public volatile Object uint8ClampedArray;
 282 
 283     /** TypedArray (int16) */
 284     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 285     public volatile Object int16Array;
 286 
 287     /** TypedArray (uint16) */
 288     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 289     public volatile Object uint16Array;
 290 
 291     /** TypedArray (int32) */
 292     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 293     public volatile Object int32Array;
 294 
 295     /** TypedArray (uint32) */
 296     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 297     public volatile Object uint32Array;
 298 
 299     /** TypedArray (float32) */
 300     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 301     public volatile Object float32Array;
 302 
 303     /** TypedArray (float64) */
 304     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 305     public volatile Object float64Array;
 306 
 307     /** Nashorn extension: Java access - global.Packages */
 308     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 309     public volatile Object packages;
 310 
 311     /** Nashorn extension: Java access - global.com */
 312     @Property(attributes = Attribute.NOT_ENUMERABLE)
 313     public volatile Object com;
 314 
 315     /** Nashorn extension: Java access - global.edu */
 316     @Property(attributes = Attribute.NOT_ENUMERABLE)
 317     public volatile Object edu;
 318 
 319     /** Nashorn extension: Java access - global.java */
 320     @Property(attributes = Attribute.NOT_ENUMERABLE)
 321     public volatile Object java;
 322 
 323     /** Nashorn extension: Java access - global.javafx */
 324     @Property(attributes = Attribute.NOT_ENUMERABLE)
 325     public volatile Object javafx;
 326 
 327     /** Nashorn extension: Java access - global.javax */
 328     @Property(attributes = Attribute.NOT_ENUMERABLE)
 329     public volatile Object javax;
 330 
 331     /** Nashorn extension: Java access - global.org */
 332     @Property(attributes = Attribute.NOT_ENUMERABLE)
 333     public volatile Object org;
 334 
 335     /** Nashorn extension: Java access - global.javaImporter */
 336     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 337     public volatile Object javaImporter;
 338 
 339     /** Nashorn extension: global.Java Object constructor. */
 340     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 341     public volatile Object javaApi;
 342 
 343     /** Nashorn extension: current script's file name */
 344     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 345     public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 346 
 347     /** Nashorn extension: current script's directory */
 348     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 349     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 350 
 351     /** Nashorn extension: current source line number being executed */
 352     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 353     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 354 
 355     /** Used as Date.prototype's default value */
 356     public NativeDate   DEFAULT_DATE;
 357 
 358     /** Used as RegExp.prototype's default value */
 359     public NativeRegExp DEFAULT_REGEXP;
 360 
 361     /*
 362      * Built-in constructor objects: Even if user changes dynamic values of
 363      * "Object", "Array" etc., we still want to keep original values of these
 364      * constructors here. For example, we need to be able to create array,
 365      * regexp literals even after user overwrites global "Array" or "RegExp"
 366      * constructor - see also ECMA 262 spec. Annex D.
 367      */
 368     private ScriptFunction builtinFunction;
 369     private ScriptFunction builtinObject;
 370     private ScriptFunction builtinArray;
 371     private ScriptFunction builtinBoolean;
 372     private ScriptFunction builtinDate;
 373     private ScriptObject   builtinJSON;
 374     private ScriptFunction builtinJSAdapter;
 375     private ScriptObject   builtinMath;
 376     private ScriptFunction builtinNumber;
 377     private ScriptFunction builtinRegExp;
 378     private ScriptFunction builtinString;
 379     private ScriptFunction builtinError;
 380     private ScriptFunction builtinEval;
 381     private ScriptFunction builtinEvalError;
 382     private ScriptFunction builtinRangeError;
 383     private ScriptFunction builtinReferenceError;
 384     private ScriptFunction builtinSyntaxError;
 385     private ScriptFunction builtinTypeError;
 386     private ScriptFunction builtinURIError;
 387     private ScriptObject   builtinPackages;
 388     private ScriptObject   builtinCom;
 389     private ScriptObject   builtinEdu;
 390     private ScriptObject   builtinJava;
 391     private ScriptObject   builtinJavafx;
 392     private ScriptObject   builtinJavax;
 393     private ScriptObject   builtinOrg;
 394     private ScriptFunction builtinJavaImporter;
 395     private ScriptObject   builtinJavaApi;
 396     private ScriptFunction builtinArrayBuffer;
 397     private ScriptFunction builtinDataView;
 398     private ScriptFunction builtinInt8Array;
 399     private ScriptFunction builtinUint8Array;
 400     private ScriptFunction builtinUint8ClampedArray;
 401     private ScriptFunction builtinInt16Array;
 402     private ScriptFunction builtinUint16Array;
 403     private ScriptFunction builtinInt32Array;
 404     private ScriptFunction builtinUint32Array;
 405     private ScriptFunction builtinFloat32Array;
 406     private ScriptFunction builtinFloat64Array;
 407 
 408     /*
 409      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 410      */
 411     private ScriptFunction typeErrorThrower;
 412 
 413     // Flag to indicate that a split method issued a return statement
 414     private int splitState = -1;
 415 
 416     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 417     private RegExpResult lastRegExpResult;
 418 
 419     private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
 420     private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
 421     private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
 422     private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
 423     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
 424     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
 425     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
 426     private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
 427 
 428     // initialized by nasgen
 429     private static PropertyMap $nasgenmap$;
 430 
 431     // context to which this global belongs to
 432     private final Context context;
 433 
 434     // current ScriptContext to use - can be null.
 435     private ScriptContext scontext;
 436     // current ScriptEngine associated - can be null.
 437     private ScriptEngine engine;
 438 
 439     // ES6 global lexical scope.
 440     private final LexicalScope lexicalScope;
 441 
 442     // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
 443     private SwitchPoint lexicalScopeSwitchPoint;
 444 
 445     /**
 446      * Set the current script context
 447      * @param scontext script context
 448      */
 449     public void setScriptContext(final ScriptContext scontext) {
 450         this.scontext = scontext;
 451     }
 452 
 453     @Override
 454     protected Context getContext() {
 455         return context;
 456     }
 457 
 458     // performs initialization checks for Global constructor and returns the
 459     // PropertyMap, if everything is fine.
 460     private static PropertyMap checkAndGetMap(final Context context) {
 461         // security check first
 462         final SecurityManager sm = System.getSecurityManager();
 463         if (sm != null) {
 464             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 465         }
 466 
 467         Objects.requireNonNull(context);
 468 
 469         return $nasgenmap$;
 470     }
 471 
 472     /**
 473      * Constructor
 474      *
 475      * @param context the context
 476      */
 477     public Global(final Context context) {
 478         super(checkAndGetMap(context));
 479         this.context = context;
 480         this.setIsScope();
 481         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
 482     }
 483 
 484     /**
 485      * Script access to "current" Global instance
 486      *
 487      * @return the global singleton
 488      */
 489     public static Global instance() {
 490         final Global global = Context.getGlobal();
 491         Objects.requireNonNull(global);
 492         return global;
 493     }
 494 
 495     private static Global instanceFrom(final Object self) {
 496         return self instanceof Global? (Global)self : instance();
 497     }
 498 
 499     /**
 500      * Check if we have a Global instance
 501      * @return true if one exists
 502      */
 503     public static boolean hasInstance() {
 504         return Context.getGlobal() != null;
 505     }
 506 
 507     /**
 508      * Script access to {@link ScriptEnvironment}
 509      *
 510      * @return the script environment
 511      */
 512     static ScriptEnvironment getEnv() {
 513         return instance().getContext().getEnv();
 514     }
 515 
 516     /**
 517      * Script access to {@link Context}
 518      *
 519      * @return the context
 520      */
 521     static Context getThisContext() {
 522         return instance().getContext();
 523     }
 524 
 525     // Runtime interface to Global
 526 
 527     /**
 528      * Is there a class filter in the current Context?
 529      * @return class filter
 530      */
 531     public ClassFilter getClassFilter() {
 532         return context.getClassFilter();
 533     }
 534 
 535     /**
 536      * Is this global of the given Context?
 537      * @param ctxt the context
 538      * @return true if this global belongs to the given Context
 539      */
 540     public boolean isOfContext(final Context ctxt) {
 541         return this.context == ctxt;
 542     }
 543 
 544     /**
 545      * Does this global belong to a strict Context?
 546      * @return true if this global belongs to a strict Context
 547      */
 548     public boolean isStrictContext() {
 549         return context.getEnv()._strict;
 550     }
 551 
 552     /**
 553      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
 554      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
 555      * of the global scope object.
 556      *
 557      * @param engine ScriptEngine to initialize
 558      */
 559     @SuppressWarnings("hiding")
 560     public void initBuiltinObjects(final ScriptEngine engine) {
 561         if (this.builtinObject != null) {
 562             // already initialized, just return
 563             return;
 564         }
 565 
 566         this.engine = engine;
 567         init(engine);
 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     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
1821         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
1822         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
1823             switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
1824         }
1825         return switchPoint;
1826     }
1827 
1828     private synchronized void invalidateLexicalSwitchPoint() {
1829         if (lexicalScopeSwitchPoint != null) {
1830             context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
1831             SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
1832         }
1833     }
1834 
1835 
1836     @SuppressWarnings("unused")
1837     private static Object lexicalScopeFilter(final Object self) {
1838         if (self instanceof Global) {
1839             return ((Global) self).getLexicalScope();
1840         }
1841         return self;
1842     }
1843 
1844     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
1845         final T func = initConstructor(name, clazz);
1846         tagBuiltinProperties(name, func);
1847         return func;
1848     }
1849 
1850     @SuppressWarnings("hiding")
1851     private void init(final ScriptEngine engine) {
1852         assert Context.getGlobal() == this : "this global is not set as current";
1853 
1854         final ScriptEnvironment env = getContext().getEnv();
1855 
1856         // initialize Function and Object constructor
1857         initFunctionAndObject();
1858 
1859         // Now fix Global's own proto.
1860         this.setInitialProto(getObjectPrototype());
1861 
1862         // initialize global function properties
1863         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1864 
1865         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
1866                     new Specialization[] {
1867                     new Specialization(GlobalFunctions.PARSEINT_Z),
1868                     new Specialization(GlobalFunctions.PARSEINT_I),
1869                     new Specialization(GlobalFunctions.PARSEINT_J),
1870                     new Specialization(GlobalFunctions.PARSEINT_OI),
1871                     new Specialization(GlobalFunctions.PARSEINT_O) });
1872         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1873         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
1874                    new Specialization[] {
1875                         new Specialization(GlobalFunctions.IS_NAN_I),
1876                         new Specialization(GlobalFunctions.IS_NAN_J),
1877                         new Specialization(GlobalFunctions.IS_NAN_D) });
1878         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1879         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1880         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1881         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1882         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1883         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1884         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1885         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1886         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1887         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1888         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1889         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
1890         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1891         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1892 
1893         // built-in constructors
1894         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
1895         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
1896         this.builtinDate      = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1897         this.builtinJSON      = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1898         this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1899         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
1900         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
1901         this.builtinRegExp    = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
1902         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
1903 
1904         // initialize String.prototype.length to 0
1905         // add String.prototype.length
1906         final ScriptObject stringPrototype = getStringPrototype();
1907         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1908 
1909         // set isArray flag on Array.prototype
1910         final ScriptObject arrayPrototype = getArrayPrototype();
1911         arrayPrototype.setIsArray();
1912 
1913         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1914 
1915         // initialize default regexp object
1916         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1917 
1918         // RegExp.prototype should behave like a RegExp object. So copy the
1919         // properties.
1920         final ScriptObject regExpProto = getRegExpPrototype();
1921         regExpProto.addBoundProperties(DEFAULT_REGEXP);
1922 
1923         // Error stuff
1924         initErrorObjects();
1925 
1926         // java access
1927         if (! env._no_java) {
1928             initJavaAccess();
1929         }
1930 
1931         if (! env._no_typed_arrays) {
1932             initTypedArray();
1933         }
1934 
1935         if (env._scripting) {
1936             initScripting(env);
1937         }
1938 
1939         if (Context.DEBUG) {
1940             boolean debugOkay;
1941             final SecurityManager sm = System.getSecurityManager();
1942             if (sm != null) {
1943                 try {
1944                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1945                     debugOkay = true;
1946                 } catch (final SecurityException ignored) {
1947                     // if no permission, don't initialize Debug object
1948                     debugOkay = false;
1949                 }
1950 
1951             } else {
1952                 debugOkay = true;
1953             }
1954 
1955             if (debugOkay) {
1956                 initDebug();
1957             }
1958         }
1959 
1960         copyBuiltins();
1961 
1962         // expose script (command line) arguments as "arguments" property of global
1963         arguments = wrapAsObject(env.getArguments().toArray());
1964         if (env._scripting) {
1965             // synonym for "arguments" in scripting mode
1966             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
1967         }
1968 
1969         if (engine != null) {
1970             // default file name
1971             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
1972             // __noSuchProperty__ hook for ScriptContext search of missing variables
1973             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
1974             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
1975         }
1976     }
1977 
1978     private void initErrorObjects() {
1979         // Error objects
1980         this.builtinError = initConstructor("Error", ScriptFunction.class);
1981         final ScriptObject errorProto = getErrorPrototype();
1982 
1983         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1984         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1985         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1986         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1987         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1988         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1989         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1990         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1991         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1992         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1993         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1994         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1995         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1996 
1997         // ECMA 15.11.4.2 Error.prototype.name
1998         // Error.prototype.name = "Error";
1999         errorProto.set(NativeError.NAME, "Error", 0);
2000         // ECMA 15.11.4.3 Error.prototype.message
2001         // Error.prototype.message = "";
2002         errorProto.set(NativeError.MESSAGE, "", 0);
2003 
2004         tagBuiltinProperties("Error", builtinError);
2005 
2006         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
2007         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
2008         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2009         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2010         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2011         this.builtinURIError = initErrorSubtype("URIError", errorProto);
2012     }
2013 
2014     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2015         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2016         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2017         prototype.set(NativeError.NAME, name, 0);
2018         prototype.set(NativeError.MESSAGE, "", 0);
2019         prototype.setInitialProto(errorProto);
2020         tagBuiltinProperties(name, cons);
2021         return cons;
2022     }
2023 
2024     private void initJavaAccess() {
2025         final ScriptObject objectProto = getObjectPrototype();
2026         this.builtinPackages = new NativeJavaPackage("", objectProto);
2027         this.builtinCom = new NativeJavaPackage("com", objectProto);
2028         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2029         this.builtinJava = new NativeJavaPackage("java", objectProto);
2030         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2031         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2032         this.builtinOrg = new NativeJavaPackage("org", objectProto);
2033         this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
2034         this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
2035     }
2036 
2037     private void initScripting(final ScriptEnvironment scriptEnv) {
2038         Object value;
2039         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2040         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2041 
2042         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2043         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2044 
2045         final String execName = ScriptingFunctions.EXEC_NAME;
2046         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2047         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2048 
2049         // Nashorn extension: global.echo (scripting-mode-only)
2050         // alias for "print"
2051         value = get("print");
2052         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2053 
2054         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2055         final ScriptObject options = newObject();
2056         copyOptions(options, scriptEnv);
2057         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2058 
2059         // Nashorn extension: global.$ENV (scripting-mode-only)
2060         if (System.getSecurityManager() == null) {
2061             // do not fill $ENV if we have a security manager around
2062             // Retrieve current state of ENV variables.
2063             final ScriptObject env = newObject();
2064             env.putAll(System.getenv(), scriptEnv._strict);
2065             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2066         } else {
2067             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2068         }
2069 
2070         // add other special properties for exec support
2071         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2072         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2073         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2074     }
2075 
2076     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2077         for (final Field f : scriptEnv.getClass().getFields()) {
2078             try {
2079                 options.set(f.getName(), f.get(scriptEnv), 0);
2080             } catch (final IllegalArgumentException | IllegalAccessException exp) {
2081                 throw new RuntimeException(exp);
2082             }
2083         }
2084     }
2085 
2086     private void initTypedArray() {
2087         this.builtinArrayBuffer       = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
2088         this.builtinDataView          = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
2089         this.builtinInt8Array         = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
2090         this.builtinUint8Array        = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
2091         this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
2092         this.builtinInt16Array        = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
2093         this.builtinUint16Array       = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
2094         this.builtinInt32Array        = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
2095         this.builtinUint32Array       = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
2096         this.builtinFloat32Array      = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
2097         this.builtinFloat64Array      = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
2098 
2099     }
2100 
2101     private void copyBuiltins() {
2102         this.array             = this.builtinArray;
2103         this._boolean          = this.builtinBoolean;
2104         this.date              = this.builtinDate;
2105         this.error             = this.builtinError;
2106         this.evalError         = this.builtinEvalError;
2107         this.function          = this.builtinFunction;
2108         this.jsadapter         = this.builtinJSAdapter;
2109         this.json              = this.builtinJSON;
2110         this.com               = this.builtinCom;
2111         this.edu               = this.builtinEdu;
2112         this.java              = this.builtinJava;
2113         this.javafx            = this.builtinJavafx;
2114         this.javax             = this.builtinJavax;
2115         this.org               = this.builtinOrg;
2116         this.javaImporter      = this.builtinJavaImporter;
2117         this.javaApi           = this.builtinJavaApi;
2118         this.math              = this.builtinMath;
2119         this.number            = this.builtinNumber;
2120         this.object            = this.builtinObject;
2121         this.packages          = this.builtinPackages;
2122         this.rangeError        = this.builtinRangeError;
2123         this.referenceError    = this.builtinReferenceError;
2124         this.regexp            = this.builtinRegExp;
2125         this.string            = this.builtinString;
2126         this.syntaxError       = this.builtinSyntaxError;
2127         this.typeError         = this.builtinTypeError;
2128         this.uriError          = this.builtinURIError;
2129         this.arrayBuffer       = this.builtinArrayBuffer;
2130         this.dataView          = this.builtinDataView;
2131         this.int8Array         = this.builtinInt8Array;
2132         this.uint8Array        = this.builtinUint8Array;
2133         this.uint8ClampedArray = this.builtinUint8ClampedArray;
2134         this.int16Array        = this.builtinInt16Array;
2135         this.uint16Array       = this.builtinUint16Array;
2136         this.int32Array        = this.builtinInt32Array;
2137         this.uint32Array       = this.builtinUint32Array;
2138         this.float32Array      = this.builtinFloat32Array;
2139         this.float64Array      = this.builtinFloat64Array;
2140     }
2141 
2142     private void initDebug() {
2143         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2144     }
2145 
2146     private Object printImpl(final boolean newLine, final Object... objects) {
2147         @SuppressWarnings("resource")
2148         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2149         final StringBuilder sb = new StringBuilder();
2150 
2151         for (final Object obj : objects) {
2152             if (sb.length() != 0) {
2153                 sb.append(' ');
2154             }
2155 
2156             sb.append(JSType.toString(obj));
2157         }
2158 
2159         // Print all at once to ensure thread friendly result.
2160         if (newLine) {
2161             out.println(sb.toString());
2162         } else {
2163             out.print(sb.toString());
2164         }
2165 
2166         out.flush();
2167 
2168         return UNDEFINED;
2169     }
2170 
2171     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2172         try {
2173             // Assuming class name pattern for built-in JS constructors.
2174             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2175 
2176             sb.append("Native");
2177             sb.append(name);
2178             sb.append("$Constructor");
2179 
2180             final Class<?> funcClass = Class.forName(sb.toString());
2181             final T res = clazz.cast(funcClass.newInstance());
2182 
2183             if (res instanceof ScriptFunction) {
2184                 // All global constructor prototypes are not-writable,
2185                 // not-enumerable and not-configurable.
2186                 final ScriptFunction func = (ScriptFunction)res;
2187                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2188             }
2189 
2190             if (res.getProto() == null) {
2191                 res.setInitialProto(getObjectPrototype());
2192             }
2193 
2194             res.setIsBuiltin();
2195 
2196             return res;
2197         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2198             throw new RuntimeException(e);
2199         }
2200     }
2201 
2202     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2203         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2204 
2205         list.addAll(Arrays.asList(func.getMap().getProperties()));
2206 
2207         if (func instanceof ScriptFunction) {
2208             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2209             if (proto != null) {
2210                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2211             }
2212         }
2213 
2214         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2215         if (prop != null) {
2216             list.add(prop);
2217         }
2218 
2219         return list;
2220     }
2221 
2222     /**
2223      * Given a builtin object, traverse its properties recursively and associate them with a name that
2224      * will be a key to their invalidation switchpoint.
2225      * @param name name for key
2226      * @param func builtin script object
2227      */
2228     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2229         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2230         if (sp == null) {
2231             sp = context.newBuiltinSwitchPoint(name);
2232         }
2233 
2234         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2235         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2236         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2237             prop.setBuiltinSwitchPoint(sp);
2238         }
2239     }
2240 
2241     // Function and Object constructors are inter-dependent. Also,
2242     // Function.prototype
2243     // functions are not properly initialized. We fix the references here.
2244     // NOTE: be careful if you want to re-order the operations here. You may
2245     // have
2246     // to play with object references carefully!!
2247     private void initFunctionAndObject() {
2248         // First-n-foremost is Function
2249 
2250         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2251 
2252         // create global anonymous function
2253         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2254         // need to copy over members of Function.prototype to anon function
2255         anon.addBoundProperties(getFunctionPrototype());
2256 
2257         // Function.prototype === Object.getPrototypeOf(Function) ===
2258         // <anon-function>
2259         builtinFunction.setInitialProto(anon);
2260         builtinFunction.setPrototype(anon);
2261         anon.set("constructor", builtinFunction, 0);
2262         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2263 
2264         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2265         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2266         typeErrorThrower.setPrototype(UNDEFINED);
2267         // Non-constructor built-in functions do not have "prototype" property
2268         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2269         typeErrorThrower.preventExtensions();
2270 
2271         // now initialize Object
2272         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2273         final ScriptObject ObjectPrototype = getObjectPrototype();
2274         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2275         anon.setInitialProto(ObjectPrototype);
2276 
2277         // ES6 draft compliant __proto__ property of Object.prototype
2278         // accessors on Object.prototype for "__proto__"
2279         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2280         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2281         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2282 
2283         // Function valued properties of Function.prototype were not properly
2284         // initialized. Because, these were created before global.function and
2285         // global.object were not initialized.
2286         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2287         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2288             final Object key = property.getKey();
2289             final Object value = builtinFunction.get(key);
2290 
2291             if (value instanceof ScriptFunction && value != anon) {
2292                 final ScriptFunction func = (ScriptFunction)value;
2293                 func.setInitialProto(getFunctionPrototype());
2294                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2295                 if (prototype != null) {
2296                     prototype.setInitialProto(ObjectPrototype);
2297                 }
2298             }
2299         }
2300 
2301         // For function valued properties of Object and Object.prototype, make
2302         // sure prototype's proto chain ends with Object.prototype
2303         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2304             final Object key = property.getKey();
2305             final Object value = builtinObject.get(key);
2306 
2307             if (value instanceof ScriptFunction) {
2308                 final ScriptFunction func = (ScriptFunction)value;
2309                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2310                 if (prototype != null) {
2311                     prototype.setInitialProto(ObjectPrototype);
2312                 }
2313             }
2314         }
2315 
2316         properties = getObjectPrototype().getMap().getProperties();
2317 
2318         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2319             final Object key   = property.getKey();
2320             if (key.equals("constructor")) {
2321                 continue;
2322             }
2323 
2324             final Object value = ObjectPrototype.get(key);
2325             if (value instanceof ScriptFunction) {
2326                 final ScriptFunction func = (ScriptFunction)value;
2327                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2328                 if (prototype != null) {
2329                     prototype.setInitialProto(ObjectPrototype);
2330                 }
2331             }
2332         }
2333 
2334         tagBuiltinProperties("Object", builtinObject);
2335         tagBuiltinProperties("Function", builtinFunction);
2336         tagBuiltinProperties("Function", anon);
2337     }
2338 
2339     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2340         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2341     }
2342 
2343     RegExpResult getLastRegExpResult() {
2344         return lastRegExpResult;
2345     }
2346 
2347     void setLastRegExpResult(final RegExpResult regExpResult) {
2348         this.lastRegExpResult = regExpResult;
2349     }
2350 
2351     @Override
2352     protected boolean isGlobal() {
2353         return true;
2354     }
2355 
2356     /**
2357      * A class representing the ES6 global lexical scope.
2358      */
2359     private static class LexicalScope extends ScriptObject {
2360 
2361         LexicalScope(final ScriptObject proto) {
2362             super(proto, PropertyMap.newMap());
2363         }
2364 
2365         @Override
2366         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2367             return filterInvocation(super.findGetMethod(desc, request, operator));
2368         }
2369 
2370         @Override
2371         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2372             return filterInvocation(super.findSetMethod(desc, request));
2373         }
2374 
2375         @Override
2376         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
2377             // We override this method just to make it callable by Global
2378             return super.addBoundProperty(propMap, source, property);
2379         }
2380 
2381         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
2382             final MethodType type = invocation.getInvocation().type();
2383             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
2384         }
2385     }
2386 
2387 }