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