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.SwitchPoint;
  38 import java.lang.reflect.Field;
  39 import java.util.ArrayList;
  40 import java.util.Arrays;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.concurrent.Callable;
  44 import java.util.concurrent.ConcurrentHashMap;
  45 import javax.script.ScriptContext;
  46 import javax.script.ScriptEngine;

  47 import jdk.internal.dynalink.linker.GuardedInvocation;
  48 import jdk.internal.dynalink.linker.LinkRequest;
  49 import jdk.nashorn.api.scripting.ClassFilter;
  50 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  51 import jdk.nashorn.internal.lookup.Lookup;
  52 import jdk.nashorn.internal.objects.annotations.Attribute;
  53 import jdk.nashorn.internal.objects.annotations.Property;
  54 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  55 import jdk.nashorn.internal.runtime.ConsString;
  56 import jdk.nashorn.internal.runtime.Context;


  57 import jdk.nashorn.internal.runtime.GlobalFunctions;
  58 import jdk.nashorn.internal.runtime.JSType;
  59 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  60 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  61 import jdk.nashorn.internal.runtime.PropertyMap;
  62 import jdk.nashorn.internal.runtime.Scope;
  63 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  64 import jdk.nashorn.internal.runtime.ScriptFunction;
  65 import jdk.nashorn.internal.runtime.ScriptObject;
  66 import jdk.nashorn.internal.runtime.ScriptRuntime;
  67 import jdk.nashorn.internal.runtime.ScriptingFunctions;
  68 import jdk.nashorn.internal.runtime.Specialization;
  69 import jdk.nashorn.internal.runtime.arrays.ArrayData;
  70 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  71 import jdk.nashorn.internal.runtime.linker.InvokeByName;

  72 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
  73 import jdk.nashorn.internal.scripts.JO;
  74 
  75 /**
  76  * Representation of global scope.
  77  */
  78 @ScriptClass("Global")
  79 public final class Global extends ScriptObject implements Scope {
  80     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
  81     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
  82     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  83     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  84 
  85     /**
  86      * Optimistic builtin names that require switchpoint invalidation
  87      * upon assignment. Overly conservative, but works for now, to avoid
  88      * any complicated scope checks and especially heavy weight guards
  89      * like
  90      *
  91      * <pre>
  92      *     public boolean setterGuard(final Object receiver) {
  93      *         final Global          global = Global.instance();
  94      *         final ScriptObject    sobj   = global.getFunctionPrototype();
  95      *         final Object          apply  = sobj.get("apply");
  96      *         return apply == receiver;
  97      *     }
  98      * </pre>
  99      *
 100      * Naturally, checking for builtin classes like NativeFunction is cheaper,
 101      * it's when you start adding property checks for said builtins you have
 102      * problems with guard speed.
 103      */
 104 
 105     /** Nashorn extension: arguments array */
 106     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 107     public Object arguments;
 108 
 109     /** ECMA 15.1.2.2 parseInt (string , radix) */
 110     @Property(attributes = Attribute.NOT_ENUMERABLE)
 111     public Object parseInt;
 112 
 113     /** ECMA 15.1.2.3 parseFloat (string) */
 114     @Property(attributes = Attribute.NOT_ENUMERABLE)
 115     public Object parseFloat;
 116 
 117     /** ECMA 15.1.2.4 isNaN (number) */
 118     @Property(attributes = Attribute.NOT_ENUMERABLE)
 119     public Object isNaN;
 120 
 121     /** ECMA 15.1.2.5 isFinite (number) */
 122     @Property(attributes = Attribute.NOT_ENUMERABLE)
 123     public Object isFinite;
 124 
 125     /** ECMA 15.1.3.3 encodeURI */
 126     @Property(attributes = Attribute.NOT_ENUMERABLE)
 127     public Object encodeURI;
 128 
 129     /** ECMA 15.1.3.4 encodeURIComponent */
 130     @Property(attributes = Attribute.NOT_ENUMERABLE)
 131     public Object encodeURIComponent;
 132 
 133     /** ECMA 15.1.3.1 decodeURI */
 134     @Property(attributes = Attribute.NOT_ENUMERABLE)
 135     public Object decodeURI;
 136 
 137     /** ECMA 15.1.3.2 decodeURIComponent */
 138     @Property(attributes = Attribute.NOT_ENUMERABLE)
 139     public Object decodeURIComponent;
 140 
 141     /** ECMA B.2.1 escape (string) */
 142     @Property(attributes = Attribute.NOT_ENUMERABLE)
 143     public Object escape;
 144 
 145     /** ECMA B.2.2 unescape (string) */
 146     @Property(attributes = Attribute.NOT_ENUMERABLE)
 147     public Object unescape;
 148 
 149     /** Nashorn extension: global.print */
 150     @Property(attributes = Attribute.NOT_ENUMERABLE)
 151     public Object print;
 152 
 153     /** Nashorn extension: global.load */
 154     @Property(attributes = Attribute.NOT_ENUMERABLE)
 155     public Object load;
 156 
 157     /** Nashorn extension: global.loadWithNewGlobal */
 158     @Property(attributes = Attribute.NOT_ENUMERABLE)
 159     public Object loadWithNewGlobal;
 160 
 161     /** Nashorn extension: global.exit */
 162     @Property(attributes = Attribute.NOT_ENUMERABLE)
 163     public Object exit;
 164 
 165     /** Nashorn extension: global.quit */
 166     @Property(attributes = Attribute.NOT_ENUMERABLE)
 167     public Object quit;
 168 
 169     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 170     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 171     public final double NaN = Double.NaN;
 172 
 173     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 174     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 175     public final double Infinity = Double.POSITIVE_INFINITY;
 176 
 177     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 178     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 179     public final Object undefined = UNDEFINED;
 180 
 181     /** ECMA 15.1.2.1 eval(x) */
 182     @Property(attributes = Attribute.NOT_ENUMERABLE)
 183     public Object eval;
 184 
 185     /** ECMA 15.1.4.1 Object constructor. */
 186     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 187     public volatile Object object;
 188 
 189     /** ECMA 15.1.4.2 Function constructor. */
 190     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 191     public volatile Object function;
 192 
 193     /** ECMA 15.1.4.3 Array constructor. */
 194     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 195     public volatile Object array;
 196 
 197     /** ECMA 15.1.4.4 String constructor */
 198     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 199     public volatile Object string;
 200 
 201     /** ECMA 15.1.4.5 Boolean constructor */
 202     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 203     public volatile Object _boolean;
 204 
 205     /** ECMA 15.1.4.6 - Number constructor */
 206     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 207     public volatile Object number;
 208 
 209     /** ECMA 15.1.4.7 Date constructor */
 210     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 211     public volatile Object date;
 212 
 213     /** ECMA 15.1.4.8 RegExp constructor */
 214     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 215     public volatile Object regexp;
 216 
 217     /** ECMA 15.12 - The JSON object */
 218     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 219     public volatile Object json;
 220 
 221     /** Nashorn extension: global.JSAdapter */
 222     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 223     public volatile Object jsadapter;
 224 
 225     /** ECMA 15.8 - The Math object */
 226     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
 227     public volatile Object math;
 228 
 229     /** Error object */
 230     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
 231     public volatile Object error;
 232 
 233     /** EvalError object */
 234     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 235     public volatile Object evalError;
 236 
 237     /** RangeError object */
 238     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 239     public volatile Object rangeError;
 240 
 241     /** ReferenceError object */
 242     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
 243     public volatile Object referenceError;
 244 
 245     /** SyntaxError object */
 246     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
 247     public volatile Object syntaxError;
 248 
 249     /** TypeError object */
 250     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
 251     public volatile Object typeError;
 252 
 253     /** URIError object */
 254     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 255     public volatile Object uriError;
 256 
 257     /** ArrayBuffer object */
 258     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 259     public volatile Object arrayBuffer;
 260 
 261     /** DataView object */
 262     @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 263     public volatile Object dataView;
 264 
 265     /** TypedArray (int8) */
 266     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 267     public volatile Object int8Array;
 268 
 269     /** TypedArray (uint8) */
 270     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 271     public volatile Object uint8Array;
 272 
 273     /** TypedArray (uint8) - Clamped */
 274     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 275     public volatile Object uint8ClampedArray;
 276 
 277     /** TypedArray (int16) */
 278     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 279     public volatile Object int16Array;
 280 
 281     /** TypedArray (uint16) */
 282     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 283     public volatile Object uint16Array;
 284 
 285     /** TypedArray (int32) */
 286     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 287     public volatile Object int32Array;
 288 
 289     /** TypedArray (uint32) */
 290     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 291     public volatile Object uint32Array;
 292 
 293     /** TypedArray (float32) */
 294     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 295     public volatile Object float32Array;
 296 
 297     /** TypedArray (float64) */
 298     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 299     public volatile Object float64Array;
 300 
 301     /** Nashorn extension: Java access - global.Packages */
 302     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 303     public volatile Object packages;
 304 
 305     /** Nashorn extension: Java access - global.com */
 306     @Property(attributes = Attribute.NOT_ENUMERABLE)
 307     public volatile Object com;
 308 
 309     /** Nashorn extension: Java access - global.edu */
 310     @Property(attributes = Attribute.NOT_ENUMERABLE)
 311     public volatile Object edu;
 312 
 313     /** Nashorn extension: Java access - global.java */
 314     @Property(attributes = Attribute.NOT_ENUMERABLE)
 315     public volatile Object java;
 316 
 317     /** Nashorn extension: Java access - global.javafx */
 318     @Property(attributes = Attribute.NOT_ENUMERABLE)
 319     public volatile Object javafx;
 320 
 321     /** Nashorn extension: Java access - global.javax */
 322     @Property(attributes = Attribute.NOT_ENUMERABLE)
 323     public volatile Object javax;
 324 
 325     /** Nashorn extension: Java access - global.org */
 326     @Property(attributes = Attribute.NOT_ENUMERABLE)
 327     public volatile Object org;
 328 
 329     /** Nashorn extension: Java access - global.javaImporter */
 330     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 331     public volatile Object javaImporter;
 332 
 333     /** Nashorn extension: global.Java Object constructor. */
 334     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 335     public volatile Object javaApi;
 336 
 337     /** Nashorn extension: current script's file name */
 338     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 339     public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 340 
 341     /** Nashorn extension: current script's directory */
 342     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 343     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 344 
 345     /** Nashorn extension: current source line number being executed */
 346     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 347     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 348 
 349     /** Used as Date.prototype's default value */
 350     public NativeDate   DEFAULT_DATE;
 351 
 352     /** Used as RegExp.prototype's default value */
 353     public NativeRegExp DEFAULT_REGEXP;
 354 
 355     /*
 356      * Built-in constructor objects: Even if user changes dynamic values of
 357      * "Object", "Array" etc., we still want to keep original values of these
 358      * constructors here. For example, we need to be able to create array,
 359      * regexp literals even after user overwrites global "Array" or "RegExp"
 360      * constructor - see also ECMA 262 spec. Annex D.
 361      */
 362     private ScriptFunction builtinFunction;
 363     private ScriptFunction builtinObject;
 364     private ScriptFunction builtinArray;
 365     private ScriptFunction builtinBoolean;
 366     private ScriptFunction builtinDate;
 367     private ScriptObject   builtinJSON;
 368     private ScriptFunction builtinJSAdapter;
 369     private ScriptObject   builtinMath;
 370     private ScriptFunction builtinNumber;
 371     private ScriptFunction builtinRegExp;
 372     private ScriptFunction builtinString;
 373     private ScriptFunction builtinError;
 374     private ScriptFunction builtinEval;
 375     private ScriptFunction builtinEvalError;
 376     private ScriptFunction builtinRangeError;
 377     private ScriptFunction builtinReferenceError;
 378     private ScriptFunction builtinSyntaxError;
 379     private ScriptFunction builtinTypeError;
 380     private ScriptFunction builtinURIError;
 381     private ScriptObject   builtinPackages;
 382     private ScriptObject   builtinCom;
 383     private ScriptObject   builtinEdu;
 384     private ScriptObject   builtinJava;
 385     private ScriptObject   builtinJavafx;
 386     private ScriptObject   builtinJavax;
 387     private ScriptObject   builtinOrg;
 388     private ScriptFunction builtinJavaImporter;
 389     private ScriptObject   builtinJavaApi;
 390     private ScriptFunction builtinArrayBuffer;
 391     private ScriptFunction builtinDataView;
 392     private ScriptFunction builtinInt8Array;
 393     private ScriptFunction builtinUint8Array;
 394     private ScriptFunction builtinUint8ClampedArray;
 395     private ScriptFunction builtinInt16Array;
 396     private ScriptFunction builtinUint16Array;
 397     private ScriptFunction builtinInt32Array;
 398     private ScriptFunction builtinUint32Array;
 399     private ScriptFunction builtinFloat32Array;
 400     private ScriptFunction builtinFloat64Array;
 401 
 402     /*
 403      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 404      */
 405     private ScriptFunction typeErrorThrower;
 406 
 407     // Flag to indicate that a split method issued a return statement
 408     private int splitState = -1;
 409 
 410     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 411     private RegExpResult lastRegExpResult;
 412 
 413     private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
 414     private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
 415     private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
 416     private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
 417     private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
 418     private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
 419     private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);

 420 
 421     // initialized by nasgen
 422     private static PropertyMap $nasgenmap$;
 423 
 424     // context to which this global belongs to
 425     private final Context context;
 426 
 427     // current ScriptContext to use - can be null.
 428     private ScriptContext scontext;
 429     // current ScriptEngine associated - can be null.
 430     private ScriptEngine engine;
 431 






 432     /**
 433      * Set the current script context
 434      * @param scontext script context
 435      */
 436     public void setScriptContext(final ScriptContext scontext) {
 437         this.scontext = scontext;
 438     }
 439 
 440     @Override
 441     protected Context getContext() {
 442         return context;
 443     }
 444 
 445     // performs initialization checks for Global constructor and returns the
 446     // PropertyMap, if everything is fine.
 447     private static PropertyMap checkAndGetMap(final Context context) {
 448         // security check first
 449         final SecurityManager sm = System.getSecurityManager();
 450         if (sm != null) {
 451             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 452         }
 453 
 454         // null check on context
 455         context.getClass();
 456 
 457         return $nasgenmap$;
 458     }
 459 
 460     /**
 461      * Constructor
 462      *
 463      * @param context the context
 464      */
 465     public Global(final Context context) {
 466         super(checkAndGetMap(context));
 467         this.context = context;
 468         this.setIsScope();

 469     }
 470 
 471     /**
 472      * Script access to "current" Global instance
 473      *
 474      * @return the global singleton
 475      */
 476     public static Global instance() {
 477         final Global global = Context.getGlobal();
 478         global.getClass(); // null check
 479         return global;
 480     }
 481 
 482     private static Global instanceFrom(final Object self) {
 483         return self instanceof Global? (Global)self : instance();
 484     }
 485 
 486     /**
 487      * Check if we have a Global instance
 488      * @return true if one exists
 489      */
 490     public static boolean hasInstance() {
 491         return Context.getGlobal() != null;
 492     }
 493 
 494     /**
 495      * Script access to {@link ScriptEnvironment}
 496      *
 497      * @return the script environment
 498      */
 499     static ScriptEnvironment getEnv() {
 500         return instance().getContext().getEnv();
 501     }
 502 
 503     /**
 504      * Script access to {@link Context}
 505      *
 506      * @return the context
 507      */
 508     static Context getThisContext() {
 509         return instance().getContext();
 510     }
 511 
 512     // Runtime interface to Global
 513 
 514     /**
 515      * Is there a class filter in the current Context?
 516      * @return class filter
 517      */
 518     public ClassFilter getClassFilter() {
 519         return context.getClassFilter();
 520     }
 521 
 522     /**
 523      * Is this global of the given Context?
 524      * @param ctxt the context
 525      * @return true if this global belongs to the given Context
 526      */
 527     public boolean isOfContext(final Context ctxt) {
 528         return this.context == ctxt;
 529     }
 530 
 531     /**
 532      * Does this global belong to a strict Context?
 533      * @return true if this global belongs to a strict Context
 534      */
 535     public boolean isStrictContext() {
 536         return context.getEnv()._strict;
 537     }
 538 
 539     /**
 540      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
 541      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
 542      * of the global scope object.
 543      *
 544      * @param eng ScriptEngine to initialize
 545      */
 546     public void initBuiltinObjects(final ScriptEngine eng) {
 547         if (this.builtinObject != null) {
 548             // already initialized, just return
 549             return;
 550         }
 551 
 552         this.engine = eng;
 553         init(eng);
 554     }
 555 
 556     /**
 557      * Wrap a Java object as corresponding script object
 558      *
 559      * @param obj object to wrap
 560      * @return    wrapped object
 561      */
 562     public Object wrapAsObject(final Object obj) {
 563         if (obj instanceof Boolean) {
 564             return new NativeBoolean((Boolean)obj, this);
 565         } else if (obj instanceof Number) {
 566             return new NativeNumber(((Number)obj).doubleValue(), this);
 567         } else if (obj instanceof String || obj instanceof ConsString) {
 568             return new NativeString((CharSequence)obj, this);
 569         } else if (obj instanceof Object[]) { // extension
 570             return new NativeArray((Object[])obj);
 571         } else if (obj instanceof double[]) { // extension
 572             return new NativeArray((double[])obj);
 573         } else if (obj instanceof long[]) {
 574             return new NativeArray((long[])obj);
 575         } else if (obj instanceof int[]) {
 576             return new NativeArray((int[])obj);
 577         } else {
 578             // FIXME: more special cases? Map? List?
 579             return obj;
 580         }
 581     }
 582 
 583     /**
 584      * Lookup helper for JS primitive types
 585      *
 586      * @param request the link request for the dynamic call site.
 587      * @param self     self reference
 588      *
 589      * @return guarded invocation
 590      */
 591     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
 592         if (self instanceof String || self instanceof ConsString) {
 593             return NativeString.lookupPrimitive(request, self);
 594         } else if (self instanceof Number) {
 595             return NativeNumber.lookupPrimitive(request, self);
 596         } else if (self instanceof Boolean) {
 597             return NativeBoolean.lookupPrimitive(request, self);
 598         }
 599         throw new IllegalArgumentException("Unsupported primitive: " + self);
 600     }
 601 
 602     /**
 603      * Returns a method handle that creates a wrapper object for a JS primitive value.
 604      *
 605      * @param self receiver object
 606      * @return method handle to create wrapper objects for primitive receiver
 607      */
 608     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
 609         if (self instanceof String || self instanceof ConsString) {
 610             return NativeString.WRAPFILTER;
 611         } else if (self instanceof Number) {
 612             return NativeNumber.WRAPFILTER;
 613         } else if (self instanceof Boolean) {
 614             return NativeBoolean.WRAPFILTER;
 615         }
 616         throw new IllegalArgumentException("Unsupported primitive: " + self);
 617     }
 618 
 619 
 620     /**
 621      * Create a new empty script object
 622      *
 623      * @return the new ScriptObject
 624      */
 625     public ScriptObject newObject() {
 626         return new JO(getObjectPrototype(), JO.getInitialMap());
 627     }
 628 
 629     /**
 630      * Default value of given type
 631      *
 632      * @param sobj     script object
 633      * @param typeHint type hint
 634      *
 635      * @return default value
 636      */
 637     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
 638         // When the [[DefaultValue]] internal method of O is called with no hint,
 639         // then it behaves as if the hint were Number, unless O is a Date object
 640         // in which case it behaves as if the hint were String.
 641         Class<?> hint = typeHint;
 642         if (hint == null) {
 643             hint = Number.class;
 644         }
 645 
 646         try {
 647             if (hint == String.class) {
 648 
 649                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 650 
 651                 if (Bootstrap.isCallable(toString)) {
 652                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 653                     if (JSType.isPrimitive(value)) {
 654                         return value;
 655                     }
 656                 }
 657 
 658                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 659                 if (Bootstrap.isCallable(valueOf)) {
 660                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 661                     if (JSType.isPrimitive(value)) {
 662                         return value;
 663                     }
 664                 }
 665                 throw typeError(this, "cannot.get.default.string");
 666             }
 667 
 668             if (hint == Number.class) {
 669                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 670                 if (Bootstrap.isCallable(valueOf)) {
 671                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 672                     if (JSType.isPrimitive(value)) {
 673                         return value;
 674                     }
 675                 }
 676 
 677                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 678                 if (Bootstrap.isCallable(toString)) {
 679                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 680                     if (JSType.isPrimitive(value)) {
 681                         return value;
 682                     }
 683                 }
 684 
 685                 throw typeError(this, "cannot.get.default.number");
 686             }
 687         } catch (final RuntimeException | Error e) {
 688             throw e;
 689         } catch (final Throwable t) {
 690             throw new RuntimeException(t);
 691         }
 692 
 693         return UNDEFINED;
 694     }
 695 
 696     /**
 697      * Is the given ScriptObject an ECMAScript Error object?
 698      *
 699      * @param sobj the object being checked
 700      * @return true if sobj is an Error object
 701      */
 702     public boolean isError(final ScriptObject sobj) {
 703         final ScriptObject errorProto = getErrorPrototype();
 704         ScriptObject proto = sobj.getProto();
 705         while (proto != null) {
 706             if (proto == errorProto) {
 707                 return true;
 708             }
 709             proto = proto.getProto();
 710         }
 711         return false;
 712     }
 713 
 714     /**
 715      * Create a new ECMAScript Error object.
 716      *
 717      * @param msg error message
 718      * @return newly created Error object
 719      */
 720     public ScriptObject newError(final String msg) {
 721         return new NativeError(msg, this);
 722     }
 723 
 724     /**
 725      * Create a new ECMAScript EvalError object.
 726      *
 727      * @param msg error message
 728      * @return newly created EvalError object
 729      */
 730     public ScriptObject newEvalError(final String msg) {
 731         return new NativeEvalError(msg, this);
 732     }
 733 
 734     /**
 735      * Create a new ECMAScript RangeError object.
 736      *
 737      * @param msg error message
 738      * @return newly created RangeError object
 739      */
 740     public ScriptObject newRangeError(final String msg) {
 741         return new NativeRangeError(msg, this);
 742     }
 743 
 744     /**
 745      * Create a new ECMAScript ReferenceError object.
 746      *
 747      * @param msg error message
 748      * @return newly created ReferenceError object
 749      */
 750     public ScriptObject newReferenceError(final String msg) {
 751         return new NativeReferenceError(msg, this);
 752     }
 753 
 754     /**
 755      * Create a new ECMAScript SyntaxError object.
 756      *
 757      * @param msg error message
 758      * @return newly created SyntaxError object
 759      */
 760     public ScriptObject newSyntaxError(final String msg) {
 761         return new NativeSyntaxError(msg, this);
 762     }
 763 
 764     /**
 765      * Create a new ECMAScript TypeError object.
 766      *
 767      * @param msg error message
 768      * @return newly created TypeError object
 769      */
 770     public ScriptObject newTypeError(final String msg) {
 771         return new NativeTypeError(msg, this);
 772     }
 773 
 774     /**
 775      * Create a new ECMAScript URIError object.
 776      *
 777      * @param msg error message
 778      * @return newly created URIError object
 779      */
 780     public ScriptObject newURIError(final String msg) {
 781         return new NativeURIError(msg, this);
 782     }
 783 
 784     /**
 785      * Create a new ECMAScript GenericDescriptor object.
 786      *
 787      * @param configurable is the property configurable?
 788      * @param enumerable is the property enumerable?
 789      * @return newly created GenericDescriptor object
 790      */
 791     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
 792         return new GenericPropertyDescriptor(configurable, enumerable, this);
 793     }
 794 
 795     /**
 796      * Create a new ECMAScript DatePropertyDescriptor object.
 797      *
 798      * @param value of the data property
 799      * @param configurable is the property configurable?
 800      * @param enumerable is the property enumerable?
 801      * @param writable is the property writable?
 802      * @return newly created DataPropertyDescriptor object
 803      */
 804     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
 805         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
 806     }
 807 
 808     /**
 809      * Create a new ECMAScript AccessorPropertyDescriptor object.
 810      *
 811      * @param get getter function of the user accessor property
 812      * @param set setter function of the user accessor property
 813      * @param configurable is the property configurable?
 814      * @param enumerable is the property enumerable?
 815      * @return newly created AccessorPropertyDescriptor object
 816      */
 817     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
 818         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
 819 
 820         if (get == null) {
 821             desc.delete(PropertyDescriptor.GET, false);
 822         }
 823 
 824         if (set == null) {
 825             desc.delete(PropertyDescriptor.SET, false);
 826         }
 827 
 828         return desc;
 829     }
 830 
 831     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
 832         final T obj = map.get(key);
 833         if (obj != null) {
 834             return obj;
 835         }
 836 
 837         try {
 838             final T newObj = creator.call();
 839             final T existingObj = map.putIfAbsent(key, newObj);
 840             return existingObj != null ? existingObj : newObj;
 841         } catch (final Exception exp) {
 842             throw new RuntimeException(exp);
 843         }
 844     }
 845 
 846     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
 847 
 848 
 849     /**
 850      * Get cached InvokeByName object for the given key
 851      * @param key key to be associated with InvokeByName object
 852      * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
 853      * @return InvokeByName object associated with the key.
 854      */
 855     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
 856         return getLazilyCreatedValue(key, creator, namedInvokers);
 857     }
 858 
 859     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
 860 
 861     /**
 862      * Get cached dynamic method handle for the given key
 863      * @param key key to be associated with dynamic method handle
 864      * @param creator if method handle is absent 'creator' is called to make one (lazy init)
 865      * @return dynamic method handle associated with the key.
 866      */
 867     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
 868         return getLazilyCreatedValue(key, creator, dynamicInvokers);
 869     }
 870 
 871     /**
 872      * Hook to search missing variables in ScriptContext if available
 873      * @param self used to detect if scope call or not (this function is 'strict')
 874      * @param name name of the variable missing
 875      * @return value of the missing variable or undefined (or TypeError for scope search)
 876      */
 877     public static Object __noSuchProperty__(final Object self, final Object name) {
 878         final Global global = Global.instance();
 879         final ScriptContext sctxt = global.scontext;
 880         final String nameStr = name.toString();
 881 
 882         if (sctxt != null) {
 883             final int scope = sctxt.getAttributesScope(nameStr);
 884             if (scope != -1) {
 885                 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
 886             }
 887         }
 888 
 889         switch (nameStr) {
 890         case "context":
 891             return sctxt;
 892         case "engine":
 893             return global.engine;
 894         default:
 895             break;
 896         }
 897 
 898         if (self == UNDEFINED) {
 899             // scope access and so throw ReferenceError
 900             throw referenceError(global, "not.defined", nameStr);
 901         }
 902 
 903         return UNDEFINED;
 904     }
 905 
 906     /**
 907      * This is the eval used when 'indirect' eval call is made.
 908      *
 909      * var global = this;
 910      * global.eval("print('hello')");
 911      *
 912      * @param self  eval scope
 913      * @param str   eval string
 914      *
 915      * @return the result of eval
 916      */
 917     public static Object eval(final Object self, final Object str) {
 918         return directEval(self, str, UNDEFINED, UNDEFINED, false);
 919     }
 920 
 921     /**
 922      * Direct eval
 923      *
 924      * @param self     The scope of eval passed as 'self'
 925      * @param str      Evaluated code
 926      * @param callThis "this" to be passed to the evaluated code
 927      * @param location location of the eval call
 928      * @param strict   is eval called a strict mode code?
 929      *
 930      * @return the return value of the eval
 931      *
 932      * This is directly invoked from generated when eval(code) is called in user code
 933      */
 934     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
 935         if (!(str instanceof String || str instanceof ConsString)) {
 936             return str;
 937         }
 938         final Global global = Global.instanceFrom(self);
 939         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
 940 
 941         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
 942     }
 943 
 944     /**
 945      * Global print implementation - Nashorn extension
 946      *
 947      * @param self    scope
 948      * @param objects arguments to print
 949      *
 950      * @return result of print (undefined)
 951      */
 952     public static Object print(final Object self, final Object... objects) {
 953         return Global.instanceFrom(self).printImpl(false, objects);
 954     }
 955 
 956     /**
 957      * Global println implementation - Nashorn extension
 958      *
 959      * @param self    scope
 960      * @param objects arguments to print
 961      *
 962      * @return result of println (undefined)
 963      */
 964     public static Object println(final Object self, final Object... objects) {
 965         return Global.instanceFrom(self).printImpl(true, objects);
 966     }
 967 
 968     /**
 969      * Global load implementation - Nashorn extension
 970      *
 971      * @param self    scope
 972      * @param source  source to load
 973      *
 974      * @return result of load (undefined)
 975      *
 976      * @throws IOException if source could not be read
 977      */
 978     public static Object load(final Object self, final Object source) throws IOException {
 979         final Global global = Global.instanceFrom(self);
 980         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
 981         return global.getContext().load(scope, source);
 982     }
 983 
 984     /**
 985      * Global loadWithNewGlobal implementation - Nashorn extension
 986      *
 987      * @param self scope
 988      * @param args from plus (optional) arguments to be passed to the loaded script
 989      *
 990      * @return result of load (may be undefined)
 991      *
 992      * @throws IOException if source could not be read
 993      */
 994     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
 995         final Global global = Global.instanceFrom(self);
 996         final int length = args.length;
 997         final boolean hasArgs = 0 < length;
 998         final Object from = hasArgs ? args[0] : UNDEFINED;
 999         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1000 
1001         return global.getContext().loadWithNewGlobal(from, arguments);
1002     }
1003 
1004     /**
1005      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1006      *
1007      * @param self  self reference
1008      * @param code  exit code
1009      *
1010      * @return undefined (will never be reached)
1011      */
1012     public static Object exit(final Object self, final Object code) {
1013         System.exit(JSType.toInt32(code));
1014         return UNDEFINED;
1015     }
1016 
1017     // builtin prototype accessors
1018     ScriptObject getFunctionPrototype() {
1019         return ScriptFunction.getPrototype(builtinFunction);
1020     }
1021 
1022     ScriptObject getObjectPrototype() {
1023         return ScriptFunction.getPrototype(builtinObject);
1024     }
1025 
1026     ScriptObject getArrayPrototype() {
1027         return ScriptFunction.getPrototype(builtinArray);
1028     }
1029 
1030     ScriptObject getBooleanPrototype() {
1031         return ScriptFunction.getPrototype(builtinBoolean);
1032     }
1033 
1034     ScriptObject getNumberPrototype() {
1035         return ScriptFunction.getPrototype(builtinNumber);
1036     }
1037 
1038     ScriptObject getDatePrototype() {
1039         return ScriptFunction.getPrototype(builtinDate);
1040     }
1041 
1042     ScriptObject getRegExpPrototype() {
1043         return ScriptFunction.getPrototype(builtinRegExp);
1044     }
1045 
1046     ScriptObject getStringPrototype() {
1047         return ScriptFunction.getPrototype(builtinString);
1048     }
1049 
1050     ScriptObject getErrorPrototype() {
1051         return ScriptFunction.getPrototype(builtinError);
1052     }
1053 
1054     ScriptObject getEvalErrorPrototype() {
1055         return ScriptFunction.getPrototype(builtinEvalError);
1056     }
1057 
1058     ScriptObject getRangeErrorPrototype() {
1059         return ScriptFunction.getPrototype(builtinRangeError);
1060     }
1061 
1062     ScriptObject getReferenceErrorPrototype() {
1063         return ScriptFunction.getPrototype(builtinReferenceError);
1064     }
1065 
1066     ScriptObject getSyntaxErrorPrototype() {
1067         return ScriptFunction.getPrototype(builtinSyntaxError);
1068     }
1069 
1070     ScriptObject getTypeErrorPrototype() {
1071         return ScriptFunction.getPrototype(builtinTypeError);
1072     }
1073 
1074     ScriptObject getURIErrorPrototype() {
1075         return ScriptFunction.getPrototype(builtinURIError);
1076     }
1077 
1078     ScriptObject getJavaImporterPrototype() {
1079         return ScriptFunction.getPrototype(builtinJavaImporter);
1080     }
1081 
1082     ScriptObject getJSAdapterPrototype() {
1083         return ScriptFunction.getPrototype(builtinJSAdapter);
1084     }
1085 
1086     ScriptObject getArrayBufferPrototype() {
1087         return ScriptFunction.getPrototype(builtinArrayBuffer);
1088     }
1089 
1090     ScriptObject getDataViewPrototype() {
1091         return ScriptFunction.getPrototype(builtinDataView);
1092     }
1093 
1094     ScriptObject getInt8ArrayPrototype() {
1095         return ScriptFunction.getPrototype(builtinInt8Array);
1096     }
1097 
1098     ScriptObject getUint8ArrayPrototype() {
1099         return ScriptFunction.getPrototype(builtinUint8Array);
1100     }
1101 
1102     ScriptObject getUint8ClampedArrayPrototype() {
1103         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
1104     }
1105 
1106     ScriptObject getInt16ArrayPrototype() {
1107         return ScriptFunction.getPrototype(builtinInt16Array);
1108     }
1109 
1110     ScriptObject getUint16ArrayPrototype() {
1111         return ScriptFunction.getPrototype(builtinUint16Array);
1112     }
1113 
1114     ScriptObject getInt32ArrayPrototype() {
1115         return ScriptFunction.getPrototype(builtinInt32Array);
1116     }
1117 
1118     ScriptObject getUint32ArrayPrototype() {
1119         return ScriptFunction.getPrototype(builtinUint32Array);
1120     }
1121 
1122     ScriptObject getFloat32ArrayPrototype() {
1123         return ScriptFunction.getPrototype(builtinFloat32Array);
1124     }
1125 
1126     ScriptObject getFloat64ArrayPrototype() {
1127         return ScriptFunction.getPrototype(builtinFloat64Array);
1128     }
1129 
1130     private ScriptFunction getBuiltinArray() {
1131         return builtinArray;
1132     }
1133 
1134     ScriptFunction getTypeErrorThrower() {
1135         return typeErrorThrower;
1136     }
1137 
1138     /**
1139      * Called from compiled script code to test if builtin has been overridden
1140      *
1141      * @return true if builtin array has not been overridden
1142      */
1143     public static boolean isBuiltinArray() {
1144         final Global instance = Global.instance();
1145         return instance.array == instance.getBuiltinArray();
1146     }
1147 
1148     private ScriptFunction getBuiltinBoolean() {
1149         return builtinBoolean;
1150     }
1151 
1152     /**
1153      * Called from compiled script code to test if builtin has been overridden
1154      *
1155      * @return true if builtin boolean has not been overridden
1156      */
1157     public static boolean isBuiltinBoolean() {
1158         final Global instance = Global.instance();
1159         return instance._boolean == instance.getBuiltinBoolean();
1160     }
1161 
1162     private ScriptFunction getBuiltinDate() {
1163         return builtinDate;
1164     }
1165 
1166     /**
1167      * Called from compiled script code to test if builtin has been overridden
1168      *
1169      * @return true if builtin date has not been overridden
1170      */
1171     public static boolean isBuiltinDate() {
1172         final Global instance = Global.instance();
1173         return instance.date == instance.getBuiltinDate();
1174     }
1175 
1176     private ScriptFunction getBuiltinError() {
1177         return builtinError;
1178     }
1179 
1180     /**
1181      * Called from compiled script code to test if builtin has been overridden
1182      *
1183      * @return true if builtin error has not been overridden
1184      */
1185     public static boolean isBuiltinError() {
1186         final Global instance = Global.instance();
1187         return instance.error == instance.getBuiltinError();
1188     }
1189 
1190     private ScriptFunction getBuiltinEvalError() {
1191         return builtinEvalError;
1192     }
1193 
1194     /**
1195      * Called from compiled script code to test if builtin has been overridden
1196      *
1197      * @return true if builtin eval error has not been overridden
1198      */
1199     public static boolean isBuiltinEvalError() {
1200         final Global instance = Global.instance();
1201         return instance.evalError == instance.getBuiltinEvalError();
1202     }
1203 
1204     private ScriptFunction getBuiltinFunction() {
1205         return builtinFunction;
1206     }
1207 
1208     /**
1209      * Called from compiled script code to test if builtin has been overridden
1210      *
1211      * @return true if builtin function has not been overridden
1212      */
1213     public static boolean isBuiltinFunction() {
1214         final Global instance = Global.instance();
1215         return instance.function == instance.getBuiltinFunction();
1216     }
1217 
1218     /**
1219      * Get the switchpoint used to check property changes for Function.prototype.apply
1220      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1221      */
1222     public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1223         return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1224     }
1225 
1226     private static boolean isBuiltinFunctionProperty(final String name) {
1227         final Global instance = Global.instance();
1228         final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1229         if (builtinFunction == null) {
1230             return false; //conservative for compile-only mode
1231         }
1232         final boolean isBuiltinFunction = instance.function == builtinFunction;
1233         return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1234     }
1235 
1236     /**
1237      * Check if the Function.prototype.apply has not been replaced
1238      * @return true if Function.prototype.apply has been replaced
1239      */
1240     public static boolean isBuiltinFunctionPrototypeApply() {
1241         return isBuiltinFunctionProperty("apply");
1242     }
1243 
1244     /**
1245      * Check if the Function.prototype.apply has not been replaced
1246      * @return true if Function.prototype.call has been replaced
1247      */
1248     public static boolean isBuiltinFunctionPrototypeCall() {
1249         return isBuiltinFunctionProperty("call");
1250     }
1251 
1252     private ScriptFunction getBuiltinJSAdapter() {
1253         return builtinJSAdapter;
1254     }
1255 
1256     /**
1257      * Called from compiled script code to test if builtin has been overridden
1258      *
1259      * @return true if builtin JSAdapter has not been overridden
1260      */
1261     public static boolean isBuiltinJSAdapter() {
1262         final Global instance = Global.instance();
1263         return instance.jsadapter == instance.getBuiltinJSAdapter();
1264     }
1265 
1266     private ScriptObject getBuiltinJSON() {
1267         return builtinJSON;
1268     }
1269 
1270     /**
1271      * Called from compiled script code to test if builtin has been overridden
1272      *
1273      * @return true if builtin JSON has has not been overridden
1274      */
1275     public static boolean isBuiltinJSON() {
1276         final Global instance = Global.instance();
1277         return instance.json == instance.getBuiltinJSON();
1278     }
1279 
1280     private ScriptObject getBuiltinJava() {
1281         return builtinJava;
1282     }
1283 
1284     /**
1285      * Called from compiled script code to test if builtin has been overridden
1286      *
1287      * @return true if builtin Java has not been overridden
1288      */
1289     public static boolean isBuiltinJava() {
1290         final Global instance = Global.instance();
1291         return instance.java == instance.getBuiltinJava();
1292     }
1293 
1294     private ScriptObject getBuiltinJavax() {
1295         return builtinJavax;
1296     }
1297 
1298     /**
1299      * Called from compiled script code to test if builtin has been overridden
1300      *
1301      * @return true if builtin Javax has not been overridden
1302      */
1303     public static boolean isBuiltinJavax() {
1304         final Global instance = Global.instance();
1305         return instance.javax == instance.getBuiltinJavax();
1306     }
1307 
1308     private ScriptObject getBuiltinJavaImporter() {
1309         return builtinJavaImporter;
1310     }
1311 
1312     /**
1313      * Called from compiled script code to test if builtin has been overridden
1314      *
1315      * @return true if builtin Java importer has not been overridden
1316      */
1317     public static boolean isBuiltinJavaImporter() {
1318         final Global instance = Global.instance();
1319         return instance.javaImporter == instance.getBuiltinJavaImporter();
1320     }
1321 
1322     private ScriptObject getBuiltinMath() {
1323         return builtinMath;
1324     }
1325 
1326     /**
1327      * Called from compiled script code to test if builtin has been overridden
1328      *
1329      * @return true if builtin math has not been overridden
1330      */
1331     public static boolean isBuiltinMath() {
1332         final Global instance = Global.instance();
1333         return instance.math == instance.getBuiltinMath();
1334     }
1335 
1336     private ScriptFunction getBuiltinNumber() {
1337         return builtinNumber;
1338     }
1339 
1340     /**
1341      * Called from compiled script code to test if builtin has been overridden
1342      *
1343      * @return true if builtin number has not been overridden
1344      */
1345     public static boolean isBuiltinNumber() {
1346         final Global instance = Global.instance();
1347         return instance.number == instance.getBuiltinNumber();
1348     }
1349 
1350     private ScriptFunction getBuiltinObject() {
1351         return builtinObject;
1352     }
1353 
1354     /**
1355      * Called from compiled script code to test if builtin has been overridden
1356      *
1357      * @return true if builtin object has not been overridden
1358      */
1359     public static boolean isBuiltinObject() {
1360         final Global instance = Global.instance();
1361         return instance.object == instance.getBuiltinObject();
1362     }
1363 
1364     private ScriptObject getBuiltinPackages() {
1365         return builtinPackages;
1366     }
1367 
1368     /**
1369      * Called from compiled script code to test if builtin has been overridden
1370      *
1371      * @return true if builtin package has not been overridden
1372      */
1373     public static boolean isBuiltinPackages() {
1374         final Global instance = Global.instance();
1375         return instance.packages == instance.getBuiltinPackages();
1376     }
1377 
1378     private ScriptFunction getBuiltinRangeError() {
1379         return builtinRangeError;
1380     }
1381 
1382     /**
1383      * Called from compiled script code to test if builtin has been overridden
1384      *
1385      * @return true if builtin range error has not been overridden
1386      */
1387     public static boolean isBuiltinRangeError() {
1388         final Global instance = Global.instance();
1389         return instance.rangeError == instance.getBuiltinRangeError();
1390     }
1391 
1392     private ScriptFunction getBuiltinReferenceError() {
1393         return builtinReferenceError;
1394     }
1395 
1396     /**
1397      * Called from compiled script code to test if builtin has been overridden
1398      *
1399      * @return true if builtin reference error has not been overridden
1400      */
1401     public static boolean isBuiltinReferenceError() {
1402         final Global instance = Global.instance();
1403         return instance.referenceError == instance.getBuiltinReferenceError();
1404     }
1405 
1406     private ScriptFunction getBuiltinRegExp() {
1407         return builtinRegExp;
1408     }
1409 
1410     /**
1411      * Called from compiled script code to test if builtin has been overridden
1412      *
1413      * @return true if builtin regexp has not been overridden
1414      */
1415     public static boolean isBuiltinRegExp() {
1416         final Global instance = Global.instance();
1417         return instance.regexp == instance.getBuiltinRegExp();
1418     }
1419 
1420     private ScriptFunction getBuiltinString() {
1421         return builtinString;
1422     }
1423 
1424     /**
1425      * Called from compiled script code to test if builtin has been overridden
1426      *
1427      * @return true if builtin Java has not been overridden
1428      */
1429     public static boolean isBuiltinString() {
1430         final Global instance = Global.instance();
1431         return instance.string == instance.getBuiltinString();
1432     }
1433 
1434     private ScriptFunction getBuiltinSyntaxError() {
1435         return builtinSyntaxError;
1436     }
1437 
1438     /**
1439      * Called from compiled script code to test if builtin has been overridden
1440      *
1441      * @return true if builtin syntax error has not been overridden
1442      */
1443     public static boolean isBuiltinSyntaxError() {
1444         final Global instance = Global.instance();
1445         return instance.syntaxError == instance.getBuiltinSyntaxError();
1446     }
1447 
1448     private ScriptFunction getBuiltinTypeError() {
1449         return builtinTypeError;
1450     }
1451 
1452     /**
1453      * Called from compiled script code to test if builtin has been overridden
1454      *
1455      * @return true if builtin type error has not been overridden
1456      */
1457     public static boolean isBuiltinTypeError() {
1458         final Global instance = Global.instance();
1459         return instance.typeError == instance.getBuiltinTypeError();
1460     }
1461 
1462     private ScriptFunction getBuiltinURIError() {
1463         return builtinURIError;
1464     }
1465 
1466     /**
1467      * Called from compiled script code to test if builtin has been overridden
1468      *
1469      * @return true if builtin URI error has not been overridden
1470      */
1471     public static boolean isBuiltinURIError() {
1472         final Global instance = Global.instance();
1473         return instance.uriError == instance.getBuiltinURIError();
1474     }
1475 
1476     @Override
1477     public String getClassName() {
1478         return "global";
1479     }
1480 
1481     /**
1482      * Copy function used to clone NativeRegExp objects.
1483      *
1484      * @param regexp a NativeRegExp to clone
1485      *
1486      * @return copy of the given regexp object
1487      */
1488     public static Object regExpCopy(final Object regexp) {
1489         return new NativeRegExp((NativeRegExp)regexp);
1490     }
1491 
1492     /**
1493      * Convert given object to NativeRegExp type.
1494      *
1495      * @param obj object to be converted
1496      * @return NativeRegExp instance
1497      */
1498     public static NativeRegExp toRegExp(final Object obj) {
1499         if (obj instanceof NativeRegExp) {
1500             return (NativeRegExp)obj;
1501         }
1502         return new NativeRegExp(JSType.toString(obj));
1503     }
1504 
1505     /**
1506      * ECMA 9.9 ToObject implementation
1507      *
1508      * @param obj  an item for which to run ToObject
1509      * @return ToObject version of given item
1510      */
1511     public static Object toObject(final Object obj) {
1512         if (obj == null || obj == UNDEFINED) {
1513             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1514         }
1515 
1516         if (obj instanceof ScriptObject) {
1517             return obj;
1518         }
1519 
1520         return instance().wrapAsObject(obj);
1521     }
1522 
1523     /**
1524      * Allocate a new object array.
1525      *
1526      * @param initial object values.
1527      * @return the new array
1528      */
1529     public static NativeArray allocate(final Object[] initial) {
1530         ArrayData arrayData = ArrayData.allocate(initial);
1531 
1532         for (int index = 0; index < initial.length; index++) {
1533             final Object value = initial[index];
1534 
1535             if (value == ScriptRuntime.EMPTY) {
1536                 arrayData = arrayData.delete(index);
1537             }
1538         }
1539 
1540         return new NativeArray(arrayData);
1541     }
1542 
1543     /**
1544      * Allocate a new number array.
1545      *
1546      * @param initial number values.
1547      * @return the new array
1548      */
1549     public static NativeArray allocate(final double[] initial) {
1550         return new NativeArray(ArrayData.allocate(initial));
1551     }
1552 
1553     /**
1554      * Allocate a new long array.
1555      *
1556      * @param initial number values.
1557      * @return the new array
1558      */
1559     public static NativeArray allocate(final long[] initial) {
1560         return new NativeArray(ArrayData.allocate(initial));
1561     }
1562 
1563     /**
1564      * Allocate a new integer array.
1565      *
1566      * @param initial number values.
1567      * @return the new array
1568      */
1569     public static NativeArray allocate(final int[] initial) {
1570         return new NativeArray(ArrayData.allocate(initial));
1571     }
1572 
1573     /**
1574      * Allocate a new object array for arguments.
1575      *
1576      * @param arguments initial arguments passed.
1577      * @param callee reference to the function that uses arguments object
1578      * @param numParams actual number of declared parameters
1579      *
1580      * @return the new array
1581      */
1582     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1583         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1584     }
1585 
1586     /**
1587      * Called from generated to check if given function is the builtin 'eval'. If
1588      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1589      *
1590      * @param  fn function object that is checked
1591      * @return true if fn is the builtin eval
1592      */
1593     public static boolean isEval(final Object fn) {
1594         return fn == Global.instance().builtinEval;
1595     }
1596 
1597     /**
1598      * Called from generated to replace a location property placeholder with the actual location property value.
1599      *
1600      * @param  placeholder the value tested for being a placeholder for a location property
1601      * @param  locationProperty the actual value for the location property
1602      * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
1603      */
1604     public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
1605         return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
1606     }
1607 
1608     /**
1609      * Called from runtime internals to check if the passed value is a location property placeholder.
1610      * @param  placeholder the value tested for being a placeholder for a location property
1611      * @return true if the value is a placeholder, false otherwise.
1612      */
1613     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
1614         return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
1615     }
1616 
1617     /**
1618      * Create a new RegExp object.
1619      *
1620      * @param expression Regular expression.
1621      * @param options    Search options.
1622      *
1623      * @return New RegExp object.
1624      */
1625     public static Object newRegExp(final String expression, final String options) {
1626         if (options == null) {
1627             return new NativeRegExp(expression);
1628         }
1629         return new NativeRegExp(expression, options);
1630     }
1631 
1632     /**
1633      * Get the object prototype
1634      *
1635      * @return the object prototype
1636      */
1637     public static ScriptObject objectPrototype() {
1638         return Global.instance().getObjectPrototype();
1639     }
1640 
1641     /**
1642      * Create a new empty object instance.
1643      *
1644      * @return New empty object.
1645      */
1646     public static ScriptObject newEmptyInstance() {
1647         return Global.instance().newObject();
1648     }
1649 
1650     /**
1651      * Check if a given object is a ScriptObject, raises an exception if this is
1652      * not the case
1653      *
1654      * @param obj and object to check
1655      * @return the script object
1656      */
1657     public static ScriptObject checkObject(final Object obj) {
1658         if (!(obj instanceof ScriptObject)) {
1659             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1660         }
1661         return (ScriptObject)obj;
1662     }
1663 
1664     /**
1665      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1666      * if this object is null or undefined.
1667      *
1668      * @param obj an object to check
1669      */
1670     public static void checkObjectCoercible(final Object obj) {
1671         if (obj == null || obj == UNDEFINED) {
1672             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1673         }
1674     }
1675 
1676     /**
1677      * Get the current split state.
1678      *
1679      * @return current split state
1680      */
1681     @Override
1682     public int getSplitState() {
1683         return splitState;
1684     }
1685 
1686     /**
1687      * Set the current split state.
1688      *
1689      * @param state current split state
1690      */
1691     @Override
1692     public void setSplitState(final int state) {
1693         splitState = state;
1694     }
1695 































































































































1696     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
1697         final T func = initConstructor(name, clazz);
1698         tagBuiltinProperties(name, func);
1699         return func;
1700     }
1701 
1702     private void init(final ScriptEngine eng) {
1703         assert Context.getGlobal() == this : "this global is not set as current";
1704 
1705         final ScriptEnvironment env = getContext().getEnv();
1706 
1707         // initialize Function and Object constructor
1708         initFunctionAndObject();
1709 
1710         // Now fix Global's own proto.
1711         this.setInitialProto(getObjectPrototype());
1712 
1713         // initialize global function properties
1714         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1715 
1716         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
1717                     new Specialization[] {
1718                     new Specialization(GlobalFunctions.PARSEINT_Z),
1719                     new Specialization(GlobalFunctions.PARSEINT_I),
1720                     new Specialization(GlobalFunctions.PARSEINT_J),
1721                     new Specialization(GlobalFunctions.PARSEINT_OI),
1722                     new Specialization(GlobalFunctions.PARSEINT_O) });
1723         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1724         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
1725                    new Specialization[] {
1726                         new Specialization(GlobalFunctions.IS_NAN_I),
1727                         new Specialization(GlobalFunctions.IS_NAN_J),
1728                         new Specialization(GlobalFunctions.IS_NAN_D) });
1729         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1730         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1731         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1732         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1733         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1734         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1735         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1736         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1737         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1738         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1739         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1740         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1741         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1742         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1743 
1744         // built-in constructors
1745         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
1746         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
1747         this.builtinDate      = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1748         this.builtinJSON      = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1749         this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1750         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
1751         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
1752         this.builtinRegExp    = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
1753         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
1754 
1755         // initialize String.prototype.length to 0
1756         // add String.prototype.length
1757         final ScriptObject stringPrototype = getStringPrototype();
1758         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1759 
1760         // set isArray flag on Array.prototype
1761         final ScriptObject arrayPrototype = getArrayPrototype();
1762         arrayPrototype.setIsArray();
1763 
1764         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1765 
1766         // initialize default regexp object
1767         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1768 
1769         // RegExp.prototype should behave like a RegExp object. So copy the
1770         // properties.
1771         final ScriptObject regExpProto = getRegExpPrototype();
1772         regExpProto.addBoundProperties(DEFAULT_REGEXP);
1773 
1774         // Error stuff
1775         initErrorObjects();
1776 
1777         // java access
1778         if (! env._no_java) {
1779             initJavaAccess();
1780         }
1781 
1782         if (! env._no_typed_arrays) {
1783             initTypedArray();
1784         }
1785 
1786         if (env._scripting) {
1787             initScripting(env);
1788         }
1789 
1790         if (Context.DEBUG) {
1791             boolean debugOkay;
1792             final SecurityManager sm = System.getSecurityManager();
1793             if (sm != null) {
1794                 try {
1795                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1796                     debugOkay = true;
1797                 } catch (final SecurityException ignored) {
1798                     // if no permission, don't initialize Debug object
1799                     debugOkay = false;
1800                 }
1801 
1802             } else {
1803                 debugOkay = true;
1804             }
1805 
1806             if (debugOkay) {
1807                 initDebug();
1808             }
1809         }
1810 
1811         copyBuiltins();
1812 
1813         // expose script (command line) arguments as "arguments" property of global
1814         arguments = wrapAsObject(env.getArguments().toArray());
1815         if (env._scripting) {
1816             // synonym for "arguments" in scripting mode
1817             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
1818         }
1819 
1820         if (eng != null) {
1821             // default file name
1822             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
1823             // __noSuchProperty__ hook for ScriptContext search of missing variables
1824             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
1825             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
1826         }
1827     }
1828 
1829     private void initErrorObjects() {
1830         // Error objects
1831         this.builtinError = initConstructor("Error", ScriptFunction.class);
1832         final ScriptObject errorProto = getErrorPrototype();
1833 
1834         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1835         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1836         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1837         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1838         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1839         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1840         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1841         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1842         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1843         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1844         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1845         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1846         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1847 
1848         // ECMA 15.11.4.2 Error.prototype.name
1849         // Error.prototype.name = "Error";
1850         errorProto.set(NativeError.NAME, "Error", 0);
1851         // ECMA 15.11.4.3 Error.prototype.message
1852         // Error.prototype.message = "";
1853         errorProto.set(NativeError.MESSAGE, "", 0);
1854 
1855         tagBuiltinProperties("Error", builtinError);
1856 
1857         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1858         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1859         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1860         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1861         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1862         this.builtinURIError = initErrorSubtype("URIError", errorProto);
1863     }
1864 
1865     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1866         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
1867         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1868         prototype.set(NativeError.NAME, name, 0);
1869         prototype.set(NativeError.MESSAGE, "", 0);
1870         prototype.setInitialProto(errorProto);
1871         tagBuiltinProperties(name, cons);
1872         return cons;
1873     }
1874 
1875     private void initJavaAccess() {
1876         final ScriptObject objectProto = getObjectPrototype();
1877         this.builtinPackages = new NativeJavaPackage("", objectProto);
1878         this.builtinCom = new NativeJavaPackage("com", objectProto);
1879         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1880         this.builtinJava = new NativeJavaPackage("java", objectProto);
1881         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1882         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1883         this.builtinOrg = new NativeJavaPackage("org", objectProto);
1884         this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1885         this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1886     }
1887 
1888     private void initScripting(final ScriptEnvironment scriptEnv) {
1889         Object value;
1890         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1891         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1892 
1893         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1894         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1895 
1896         final String execName = ScriptingFunctions.EXEC_NAME;
1897         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1898         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1899 
1900         // Nashorn extension: global.echo (scripting-mode-only)
1901         // alias for "print"
1902         value = get("print");
1903         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1904 
1905         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1906         final ScriptObject options = newObject();
1907         copyOptions(options, scriptEnv);
1908         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1909 
1910         // Nashorn extension: global.$ENV (scripting-mode-only)
1911         if (System.getSecurityManager() == null) {
1912             // do not fill $ENV if we have a security manager around
1913             // Retrieve current state of ENV variables.
1914             final ScriptObject env = newObject();
1915             env.putAll(System.getenv(), scriptEnv._strict);
1916             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1917         } else {
1918             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1919         }
1920 
1921         // add other special properties for exec support
1922         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1923         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1924         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1925     }
1926 
1927     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1928         for (final Field f : scriptEnv.getClass().getFields()) {
1929             try {
1930                 options.set(f.getName(), f.get(scriptEnv), 0);
1931             } catch (final IllegalArgumentException | IllegalAccessException exp) {
1932                 throw new RuntimeException(exp);
1933             }
1934         }
1935     }
1936 
1937     private void initTypedArray() {
1938         this.builtinArrayBuffer       = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1939         this.builtinDataView          = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1940         this.builtinInt8Array         = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1941         this.builtinUint8Array        = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1942         this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1943         this.builtinInt16Array        = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1944         this.builtinUint16Array       = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1945         this.builtinInt32Array        = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1946         this.builtinUint32Array       = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1947         this.builtinFloat32Array      = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1948         this.builtinFloat64Array      = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1949 
1950     }
1951 
1952     private void copyBuiltins() {
1953         this.array             = this.builtinArray;
1954         this._boolean          = this.builtinBoolean;
1955         this.date              = this.builtinDate;
1956         this.error             = this.builtinError;
1957         this.evalError         = this.builtinEvalError;
1958         this.function          = this.builtinFunction;
1959         this.jsadapter         = this.builtinJSAdapter;
1960         this.json              = this.builtinJSON;
1961         this.com               = this.builtinCom;
1962         this.edu               = this.builtinEdu;
1963         this.java              = this.builtinJava;
1964         this.javafx            = this.builtinJavafx;
1965         this.javax             = this.builtinJavax;
1966         this.org               = this.builtinOrg;
1967         this.javaImporter      = this.builtinJavaImporter;
1968         this.javaApi           = this.builtinJavaApi;
1969         this.math              = this.builtinMath;
1970         this.number            = this.builtinNumber;
1971         this.object            = this.builtinObject;
1972         this.packages          = this.builtinPackages;
1973         this.rangeError        = this.builtinRangeError;
1974         this.referenceError    = this.builtinReferenceError;
1975         this.regexp            = this.builtinRegExp;
1976         this.string            = this.builtinString;
1977         this.syntaxError       = this.builtinSyntaxError;
1978         this.typeError         = this.builtinTypeError;
1979         this.uriError          = this.builtinURIError;
1980         this.arrayBuffer       = this.builtinArrayBuffer;
1981         this.dataView          = this.builtinDataView;
1982         this.int8Array         = this.builtinInt8Array;
1983         this.uint8Array        = this.builtinUint8Array;
1984         this.uint8ClampedArray = this.builtinUint8ClampedArray;
1985         this.int16Array        = this.builtinInt16Array;
1986         this.uint16Array       = this.builtinUint16Array;
1987         this.int32Array        = this.builtinInt32Array;
1988         this.uint32Array       = this.builtinUint32Array;
1989         this.float32Array      = this.builtinFloat32Array;
1990         this.float64Array      = this.builtinFloat64Array;
1991     }
1992 
1993     private void initDebug() {
1994         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
1995     }
1996 
1997     private Object printImpl(final boolean newLine, final Object... objects) {
1998         @SuppressWarnings("resource")
1999         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2000         final StringBuilder sb = new StringBuilder();
2001 
2002         for (final Object obj : objects) {
2003             if (sb.length() != 0) {
2004                 sb.append(' ');
2005             }
2006 
2007             sb.append(JSType.toString(obj));
2008         }
2009 
2010         // Print all at once to ensure thread friendly result.
2011         if (newLine) {
2012             out.println(sb.toString());
2013         } else {
2014             out.print(sb.toString());
2015         }
2016 
2017         out.flush();
2018 
2019         return UNDEFINED;
2020     }
2021 
2022     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2023         try {
2024             // Assuming class name pattern for built-in JS constructors.
2025             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2026 
2027             sb.append("Native");
2028             sb.append(name);
2029             sb.append("$Constructor");
2030 
2031             final Class<?> funcClass = Class.forName(sb.toString());
2032             final T res = clazz.cast(funcClass.newInstance());
2033 
2034             if (res instanceof ScriptFunction) {
2035                 // All global constructor prototypes are not-writable,
2036                 // not-enumerable and not-configurable.
2037                 final ScriptFunction func = (ScriptFunction)res;
2038                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2039             }
2040 
2041             if (res.getProto() == null) {
2042                 res.setInitialProto(getObjectPrototype());
2043             }
2044 
2045             res.setIsBuiltin();
2046 
2047             return res;
2048         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2049             throw new RuntimeException(e);
2050         }
2051     }
2052 
2053     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2054         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2055 
2056         list.addAll(Arrays.asList(func.getMap().getProperties()));
2057 
2058         if (func instanceof ScriptFunction) {
2059             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2060             if (proto != null) {
2061                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2062             }
2063         }
2064 
2065         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2066         if (prop != null) {
2067             list.add(prop);
2068         }
2069 
2070         return list;
2071     }
2072 
2073     /**
2074      * Given a builtin object, traverse its properties recursively and associate them with a name that
2075      * will be a key to their invalidation switchpoint.
2076      * @param name name for key
2077      * @param func builtin script object
2078      */
2079     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2080         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2081         if (sp == null) {
2082             sp = context.newBuiltinSwitchPoint(name);
2083         }
2084 
2085         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2086         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2087         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2088             prop.setBuiltinSwitchPoint(sp);
2089         }
2090     }
2091 
2092     // Function and Object constructors are inter-dependent. Also,
2093     // Function.prototype
2094     // functions are not properly initialized. We fix the references here.
2095     // NOTE: be careful if you want to re-order the operations here. You may
2096     // have
2097     // to play with object references carefully!!
2098     private void initFunctionAndObject() {
2099         // First-n-foremost is Function
2100 
2101         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2102 
2103         // create global anonymous function
2104         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2105         // need to copy over members of Function.prototype to anon function
2106         anon.addBoundProperties(getFunctionPrototype());
2107 
2108         // Function.prototype === Object.getPrototypeOf(Function) ===
2109         // <anon-function>
2110         builtinFunction.setInitialProto(anon);
2111         builtinFunction.setPrototype(anon);
2112         anon.set("constructor", builtinFunction, 0);
2113         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2114 
2115         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2116         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2117         typeErrorThrower.setPrototype(UNDEFINED);
2118         // Non-constructor built-in functions do not have "prototype" property
2119         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2120         typeErrorThrower.preventExtensions();
2121 
2122         // now initialize Object
2123         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2124         final ScriptObject ObjectPrototype = getObjectPrototype();
2125         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2126         anon.setInitialProto(ObjectPrototype);
2127 
2128         // ES6 draft compliant __proto__ property of Object.prototype
2129         // accessors on Object.prototype for "__proto__"
2130         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2131         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2132         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2133 
2134         // Function valued properties of Function.prototype were not properly
2135         // initialized. Because, these were created before global.function and
2136         // global.object were not initialized.
2137         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2138         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2139             final Object key = property.getKey();
2140             final Object value = builtinFunction.get(key);
2141 
2142             if (value instanceof ScriptFunction && value != anon) {
2143                 final ScriptFunction func = (ScriptFunction)value;
2144                 func.setInitialProto(getFunctionPrototype());
2145                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2146                 if (prototype != null) {
2147                     prototype.setInitialProto(ObjectPrototype);
2148                 }
2149             }
2150         }
2151 
2152         // For function valued properties of Object and Object.prototype, make
2153         // sure prototype's proto chain ends with Object.prototype
2154         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2155             final Object key = property.getKey();
2156             final Object value = builtinObject.get(key);
2157 
2158             if (value instanceof ScriptFunction) {
2159                 final ScriptFunction func = (ScriptFunction)value;
2160                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2161                 if (prototype != null) {
2162                     prototype.setInitialProto(ObjectPrototype);
2163                 }
2164             }
2165         }
2166 
2167         properties = getObjectPrototype().getMap().getProperties();
2168 
2169         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2170             final Object key   = property.getKey();
2171             if (key.equals("constructor")) {
2172                 continue;
2173             }
2174 
2175             final Object value = ObjectPrototype.get(key);
2176             if (value instanceof ScriptFunction) {
2177                 final ScriptFunction func = (ScriptFunction)value;
2178                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2179                 if (prototype != null) {
2180                     prototype.setInitialProto(ObjectPrototype);
2181                 }
2182             }
2183         }
2184 
2185         tagBuiltinProperties("Object", builtinObject);
2186         tagBuiltinProperties("Function", builtinFunction);
2187         tagBuiltinProperties("Function", anon);
2188     }
2189 
2190     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2191         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2192     }
2193 
2194     RegExpResult getLastRegExpResult() {
2195         return lastRegExpResult;
2196     }
2197 
2198     void setLastRegExpResult(final RegExpResult regExpResult) {
2199         this.lastRegExpResult = regExpResult;
2200     }
2201 
2202     @Override
2203     protected boolean isGlobal() {
2204         return true;
2205     }
































2206 }
--- EOF ---