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