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.typeError;
  30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  31 
  32 import java.io.IOException;
  33 import java.io.PrintWriter;
  34 import java.lang.invoke.MethodHandle;
  35 import java.lang.invoke.MethodHandles;
  36 import java.lang.ref.ReferenceQueue;
  37 import java.lang.ref.SoftReference;
  38 import java.lang.reflect.Field;
  39 import java.util.Arrays;
  40 import java.util.LinkedHashMap;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.concurrent.Callable;
  44 import java.util.concurrent.ConcurrentHashMap;
  45 import jdk.internal.dynalink.linker.GuardedInvocation;
  46 import jdk.internal.dynalink.linker.LinkRequest;
  47 import jdk.nashorn.internal.lookup.Lookup;
  48 import jdk.nashorn.internal.objects.annotations.Attribute;
  49 import jdk.nashorn.internal.objects.annotations.Property;
  50 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  51 import jdk.nashorn.internal.runtime.ConsString;
  52 import jdk.nashorn.internal.runtime.Context;
  53 import jdk.nashorn.internal.runtime.GlobalFunctions;
  54 import jdk.nashorn.internal.runtime.GlobalObject;
  55 import jdk.nashorn.internal.runtime.JSType;
  56 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  57 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  58 import jdk.nashorn.internal.runtime.PropertyMap;
  59 import jdk.nashorn.internal.runtime.Scope;
  60 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  61 import jdk.nashorn.internal.runtime.ScriptFunction;
  62 import jdk.nashorn.internal.runtime.ScriptObject;
  63 import jdk.nashorn.internal.runtime.ScriptRuntime;
  64 import jdk.nashorn.internal.runtime.ScriptingFunctions;
  65 import jdk.nashorn.internal.runtime.Source;
  66 import jdk.nashorn.internal.runtime.arrays.ArrayData;
  67 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  68 import jdk.nashorn.internal.runtime.linker.InvokeByName;
  69 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
  70 import jdk.nashorn.internal.scripts.JO;
  71 
  72 /**
  73  * Representation of global scope.
  74  */
  75 @ScriptClass("Global")
  76 public final class Global extends ScriptObject implements GlobalObject, Scope {
  77     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  78     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  79 
  80     /** ECMA 15.1.2.2 parseInt (string , radix) */
  81     @Property(attributes = Attribute.NOT_ENUMERABLE)
  82     public Object parseInt;
  83 
  84     /** ECMA 15.1.2.3 parseFloat (string) */
  85     @Property(attributes = Attribute.NOT_ENUMERABLE)
  86     public Object parseFloat;
  87 
  88     /** ECMA 15.1.2.4 isNaN (number) */
  89     @Property(attributes = Attribute.NOT_ENUMERABLE)
  90     public Object isNaN;
  91 
  92     /** ECMA 15.1.2.5 isFinite (number) */
  93     @Property(attributes = Attribute.NOT_ENUMERABLE)
  94     public Object isFinite;
  95 
  96     /** ECMA 15.1.3.3 encodeURI */
  97     @Property(attributes = Attribute.NOT_ENUMERABLE)
  98     public Object encodeURI;
  99 
 100     /** ECMA 15.1.3.4 encodeURIComponent */
 101     @Property(attributes = Attribute.NOT_ENUMERABLE)
 102     public Object encodeURIComponent;
 103 
 104     /** ECMA 15.1.3.1 decodeURI */
 105     @Property(attributes = Attribute.NOT_ENUMERABLE)
 106     public Object decodeURI;
 107 
 108     /** ECMA 15.1.3.2 decodeURIComponent */
 109     @Property(attributes = Attribute.NOT_ENUMERABLE)
 110     public Object decodeURIComponent;
 111 
 112     /** ECMA B.2.1 escape (string) */
 113     @Property(attributes = Attribute.NOT_ENUMERABLE)
 114     public Object escape;
 115 
 116     /** ECMA B.2.2 unescape (string) */
 117     @Property(attributes = Attribute.NOT_ENUMERABLE)
 118     public Object unescape;
 119 
 120     /** Nashorn extension: global.print */
 121     @Property(attributes = Attribute.NOT_ENUMERABLE)
 122     public Object print;
 123 
 124     /** Nashorn extension: global.load */
 125     @Property(attributes = Attribute.NOT_ENUMERABLE)
 126     public Object load;
 127 
 128     /** Nashorn extension: global.loadWithNewGlobal */
 129     @Property(attributes = Attribute.NOT_ENUMERABLE)
 130     public Object loadWithNewGlobal;
 131 
 132     /** Nashorn extension: global.exit */
 133     @Property(attributes = Attribute.NOT_ENUMERABLE)
 134     public Object exit;
 135 
 136     /** Nashorn extension: global.quit */
 137     @Property(attributes = Attribute.NOT_ENUMERABLE)
 138     public Object quit;
 139 
 140     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 141     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 142     public final Object NaN = Double.NaN;
 143 
 144     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 145     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 146     public final Object Infinity = Double.POSITIVE_INFINITY;
 147 
 148     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 149     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 150     public final Object undefined = UNDEFINED;
 151 
 152     /** ECMA 15.1.2.1 eval(x) */
 153     @Property(attributes = Attribute.NOT_ENUMERABLE)
 154     public Object eval;
 155 
 156     /** ECMA 15.1.4.1 Object constructor. */
 157     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 158     public volatile Object object;
 159 
 160     /** ECMA 15.1.4.2 Function constructor. */
 161     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 162     public volatile Object function;
 163 
 164     /** ECMA 15.1.4.3 Array constructor. */
 165     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 166     public volatile Object array;
 167 
 168     /** ECMA 15.1.4.4 String constructor */
 169     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 170     public volatile Object string;
 171 
 172     /** ECMA 15.1.4.5 Boolean constructor */
 173     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 174     public volatile Object _boolean;
 175 
 176     /** ECMA 15.1.4.6 - Number constructor */
 177     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 178     public volatile Object number;
 179 
 180     /** ECMA 15.1.4.7 Date constructor */
 181     @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 182     public volatile Object date;
 183 
 184     /** ECMA 15.1.4.8 RegExp constructor */
 185     @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 186     public volatile Object regexp;
 187 
 188     /** ECMA 15.12 - The JSON object */
 189     @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 190     public volatile Object json;
 191 
 192     /** Nashorn extension: global.JSAdapter */
 193     @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 194     public volatile Object jsadapter;
 195 
 196     /** ECMA 15.8 - The Math object */
 197     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
 198     public volatile Object math;
 199 
 200     /** Error object */
 201     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
 202     public volatile Object error;
 203 
 204     /** EvalError object */
 205     @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 206     public volatile Object evalError;
 207 
 208     /** RangeError object */
 209     @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 210     public volatile Object rangeError;
 211 
 212     /** ReferenceError object */
 213     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
 214     public volatile Object referenceError;
 215 
 216     /** SyntaxError object */
 217     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
 218     public volatile Object syntaxError;
 219 
 220     /** TypeError object */
 221     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
 222     public volatile Object typeError;
 223 
 224     /** URIError object */
 225     @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 226     public volatile Object uriError;
 227 
 228     /** ArrayBuffer object */
 229     @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 230     public volatile Object arrayBuffer;
 231 
 232     /** TypedArray (int8) */
 233     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 234     public volatile Object int8Array;
 235 
 236     /** TypedArray (uint8) */
 237     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 238     public volatile Object uint8Array;
 239 
 240     /** TypedArray (uint8) - Clamped */
 241     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 242     public volatile Object uint8ClampedArray;
 243 
 244     /** TypedArray (int16) */
 245     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 246     public volatile Object int16Array;
 247 
 248     /** TypedArray (uint16) */
 249     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 250     public volatile Object uint16Array;
 251 
 252     /** TypedArray (int32) */
 253     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 254     public volatile Object int32Array;
 255 
 256     /** TypedArray (uint32) */
 257     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 258     public volatile Object uint32Array;
 259 
 260     /** TypedArray (float32) */
 261     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 262     public volatile Object float32Array;
 263 
 264     /** TypedArray (float64) */
 265     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 266     public volatile Object float64Array;
 267 
 268     /** Nashorn extension: Java access - global.Packages */
 269     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 270     public volatile Object packages;
 271 
 272     /** Nashorn extension: Java access - global.com */
 273     @Property(attributes = Attribute.NOT_ENUMERABLE)
 274     public volatile Object com;
 275 
 276     /** Nashorn extension: Java access - global.edu */
 277     @Property(attributes = Attribute.NOT_ENUMERABLE)
 278     public volatile Object edu;
 279 
 280     /** Nashorn extension: Java access - global.java */
 281     @Property(attributes = Attribute.NOT_ENUMERABLE)
 282     public volatile Object java;
 283 
 284     /** Nashorn extension: Java access - global.javafx */
 285     @Property(attributes = Attribute.NOT_ENUMERABLE)
 286     public volatile Object javafx;
 287 
 288     /** Nashorn extension: Java access - global.javax */
 289     @Property(attributes = Attribute.NOT_ENUMERABLE)
 290     public volatile Object javax;
 291 
 292     /** Nashorn extension: Java access - global.org */
 293     @Property(attributes = Attribute.NOT_ENUMERABLE)
 294     public volatile Object org;
 295 
 296     /** Nashorn extension: Java access - global.javaImporter */
 297     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 298     public volatile Object javaImporter;
 299 
 300     /** Nashorn extension: global.Java Object constructor. */
 301     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 302     public volatile Object javaApi;
 303 
 304     /** Nashorn extension: current script's file name */
 305     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 306     public Object __FILE__;
 307 
 308     /** Nashorn extension: current script's directory */
 309     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 310     public Object __DIR__;
 311 
 312     /** Nashorn extension: current source line number being executed */
 313     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 314     public Object __LINE__;
 315 
 316     /** Used as Date.prototype's default value */
 317     public NativeDate   DEFAULT_DATE;
 318 
 319     /** Used as RegExp.prototype's default value */
 320     public NativeRegExp DEFAULT_REGEXP;
 321 
 322     /*
 323      * Built-in constructor objects: Even if user changes dynamic values of
 324      * "Object", "Array" etc., we still want to keep original values of these
 325      * constructors here. For example, we need to be able to create array,
 326      * regexp literals even after user overwrites global "Array" or "RegExp"
 327      * constructor - see also ECMA 262 spec. Annex D.
 328      */
 329     private ScriptFunction builtinFunction;
 330     private ScriptFunction builtinObject;
 331     private ScriptFunction builtinArray;
 332     private ScriptFunction builtinBoolean;
 333     private ScriptFunction builtinDate;
 334     private ScriptObject   builtinJSON;
 335     private ScriptFunction builtinJSAdapter;
 336     private ScriptObject   builtinMath;
 337     private ScriptFunction builtinNumber;
 338     private ScriptFunction builtinRegExp;
 339     private ScriptFunction builtinString;
 340     private ScriptFunction builtinError;
 341     private ScriptFunction builtinEval;
 342     private ScriptFunction builtinEvalError;
 343     private ScriptFunction builtinRangeError;
 344     private ScriptFunction builtinReferenceError;
 345     private ScriptFunction builtinSyntaxError;
 346     private ScriptFunction builtinTypeError;
 347     private ScriptFunction builtinURIError;
 348     private ScriptObject   builtinPackages;
 349     private ScriptObject   builtinCom;
 350     private ScriptObject   builtinEdu;
 351     private ScriptObject   builtinJava;
 352     private ScriptObject   builtinJavafx;
 353     private ScriptObject   builtinJavax;
 354     private ScriptObject   builtinOrg;
 355     private ScriptObject   builtinJavaImporter;
 356     private ScriptObject   builtinJavaApi;
 357     private ScriptObject   builtinArrayBuffer;
 358     private ScriptObject   builtinInt8Array;
 359     private ScriptObject   builtinUint8Array;
 360     private ScriptObject   builtinUint8ClampedArray;
 361     private ScriptObject   builtinInt16Array;
 362     private ScriptObject   builtinUint16Array;
 363     private ScriptObject   builtinInt32Array;
 364     private ScriptObject   builtinUint32Array;
 365     private ScriptObject   builtinFloat32Array;
 366     private ScriptObject   builtinFloat64Array;
 367 
 368     /*
 369      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 370      */
 371     private ScriptFunction typeErrorThrower;
 372 
 373     private PropertyMap    accessorPropertyDescriptorMap;
 374     private PropertyMap    arrayBufferViewMap;
 375     private PropertyMap    dataPropertyDescriptorMap;
 376     private PropertyMap    genericPropertyDescriptorMap;
 377     private PropertyMap    nativeArgumentsMap;
 378     private PropertyMap    nativeArrayMap;
 379     private PropertyMap    nativeArrayBufferMap;
 380     private PropertyMap    nativeBooleanMap;
 381     private PropertyMap    nativeDateMap;
 382     private PropertyMap    nativeErrorMap;
 383     private PropertyMap    nativeEvalErrorMap;
 384     private PropertyMap    nativeJSAdapterMap;
 385     private PropertyMap    nativeJavaImporterMap;
 386     private PropertyMap    nativeNumberMap;
 387     private PropertyMap    nativeRangeErrorMap;
 388     private PropertyMap    nativeReferenceErrorMap;
 389     private PropertyMap    nativeRegExpMap;
 390     private PropertyMap    nativeRegExpExecResultMap;
 391     private PropertyMap    nativeStrictArgumentsMap;
 392     private PropertyMap    nativeStringMap;
 393     private PropertyMap    nativeSyntaxErrorMap;
 394     private PropertyMap    nativeTypeErrorMap;
 395     private PropertyMap    nativeURIErrorMap;
 396     private PropertyMap    prototypeObjectMap;
 397     private PropertyMap    objectMap;
 398     private PropertyMap    functionMap;
 399     private PropertyMap    anonymousFunctionMap;
 400     private PropertyMap    strictFunctionMap;
 401     private PropertyMap    boundFunctionMap;
 402 
 403     // Flag to indicate that a split method issued a return statement
 404     private int splitState = -1;
 405 
 406     // class cache
 407     private ClassCache classCache;
 408 
 409     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 410     private RegExpResult lastRegExpResult;
 411 
 412     private static final MethodHandle EVAL              = findOwnMH("eval",              Object.class, Object.class, Object.class);
 413     private static final MethodHandle PRINT             = findOwnMH("print",             Object.class, Object.class, Object[].class);
 414     private static final MethodHandle PRINTLN           = findOwnMH("println",           Object.class, Object.class, Object[].class);
 415     private static final MethodHandle LOAD              = findOwnMH("load",              Object.class, Object.class, Object.class);
 416     private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
 417     private static final MethodHandle EXIT              = findOwnMH("exit",              Object.class, Object.class, Object.class);
 418 
 419     // initialized by nasgen
 420     private static PropertyMap $nasgenmap$;
 421 
 422     // context to which this global belongs to
 423     private final Context context;
 424 
 425     @Override
 426     protected Context getContext() {
 427         return context;
 428     }
 429 
 430     // performs initialization checks for Global constructor and returns the
 431     // PropertyMap, if everything is fine.
 432     private static PropertyMap checkAndGetMap(final Context context) {
 433         // security check first
 434         final SecurityManager sm = System.getSecurityManager();
 435         if (sm != null) {
 436             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 437         }
 438 
 439         // null check on context
 440         context.getClass();
 441 
 442         /*
 443          * Duplicate global's map and use it. This way the initial Map filled
 444          * by nasgen (referenced from static field in this class) is retained
 445          * 'as is' (as that one is process wide singleton.
 446          */
 447         return $nasgenmap$.duplicate();
 448     }
 449 
 450     /**
 451      * Constructor
 452      *
 453      * @param context the context
 454      */
 455     public Global(final Context context) {
 456         super(checkAndGetMap(context));
 457         this.context = context;
 458         this.setIsScope();
 459 
 460         final int cacheSize = context.getEnv()._class_cache_size;
 461         if (cacheSize > 0) {
 462             classCache = new ClassCache(cacheSize);
 463         }
 464     }
 465 
 466     /**
 467      * Script access to "current" Global instance
 468      *
 469      * @return the global singleton
 470      */
 471     public static Global instance() {
 472         ScriptObject global = Context.getGlobal();
 473         if (! (global instanceof Global)) {
 474             throw new IllegalStateException("no current global instance");
 475         }
 476         return (Global)global;
 477     }
 478 
 479     /**
 480      * Script access to {@link ScriptEnvironment}
 481      *
 482      * @return the script environment
 483      */
 484     static ScriptEnvironment getEnv() {
 485         return instance().getContext().getEnv();
 486     }
 487 
 488     /**
 489      * Script access to {@link Context}
 490      *
 491      * @return the context
 492      */
 493     static Context getThisContext() {
 494         return instance().getContext();
 495     }
 496 
 497     // GlobalObject interface implementation
 498 
 499     @Override
 500     public boolean isOfContext(final Context ctxt) {
 501         return this.context == ctxt;
 502     }
 503 
 504     @Override
 505     public boolean isStrictContext() {
 506         return context.getEnv()._strict;
 507     }
 508 
 509     @Override
 510     public void initBuiltinObjects() {
 511         if (this.builtinObject != null) {
 512             // already initialized, just return
 513             return;
 514         }
 515 
 516         init();
 517     }
 518 
 519     @Override
 520     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
 521         return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
 522     }
 523 
 524     @Override
 525     public Object wrapAsObject(final Object obj) {
 526         if (obj instanceof Boolean) {
 527             return new NativeBoolean((Boolean)obj, this);
 528         } else if (obj instanceof Number) {
 529             return new NativeNumber(((Number)obj).doubleValue(), this);
 530         } else if (obj instanceof String || obj instanceof ConsString) {
 531             return new NativeString((CharSequence)obj, this);
 532         } else if (obj instanceof Object[]) { // extension
 533             return new NativeArray((Object[])obj);
 534         } else if (obj instanceof double[]) { // extension
 535             return new NativeArray((double[])obj);
 536         } else if (obj instanceof long[]) {
 537             return new NativeArray((long[])obj);
 538         } else if (obj instanceof int[]) {
 539             return new NativeArray((int[])obj);
 540         } else {
 541             // FIXME: more special cases? Map? List?
 542             return obj;
 543         }
 544     }
 545 
 546     @Override
 547     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
 548         if (self instanceof String || self instanceof ConsString) {
 549             return NativeString.lookupPrimitive(request, self);
 550         } else if (self instanceof Number) {
 551             return NativeNumber.lookupPrimitive(request, self);
 552         } else if (self instanceof Boolean) {
 553             return NativeBoolean.lookupPrimitive(request, self);
 554         }
 555         throw new IllegalArgumentException("Unsupported primitive: " + self);
 556     }
 557 
 558     @Override
 559     public ScriptObject newObject() {
 560         return new JO(getObjectPrototype(), getObjectMap());
 561     }
 562 
 563     @Override
 564     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
 565         // When the [[DefaultValue]] internal method of O is called with no hint,
 566         // then it behaves as if the hint were Number, unless O is a Date object
 567         // in which case it behaves as if the hint were String.
 568         Class<?> hint = typeHint;
 569         if (hint == null) {
 570             hint = Number.class;
 571         }
 572 
 573         try {
 574             if (hint == String.class) {
 575 
 576                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 577 
 578                 if (Bootstrap.isCallable(toString)) {
 579                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 580                     if (JSType.isPrimitive(value)) {
 581                         return value;
 582                     }
 583                 }
 584 
 585                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 586                 if (Bootstrap.isCallable(valueOf)) {
 587                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 588                     if (JSType.isPrimitive(value)) {
 589                         return value;
 590                     }
 591                 }
 592                 throw typeError(this, "cannot.get.default.string");
 593             }
 594 
 595             if (hint == Number.class) {
 596                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 597                 if (Bootstrap.isCallable(valueOf)) {
 598                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 599                     if (JSType.isPrimitive(value)) {
 600                         return value;
 601                     }
 602                 }
 603 
 604                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 605                 if (Bootstrap.isCallable(toString)) {
 606                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 607                     if (JSType.isPrimitive(value)) {
 608                         return value;
 609                     }
 610                 }
 611 
 612                 throw typeError(this, "cannot.get.default.number");
 613             }
 614         } catch (final RuntimeException | Error e) {
 615             throw e;
 616         } catch (final Throwable t) {
 617             throw new RuntimeException(t);
 618         }
 619 
 620         return UNDEFINED;
 621     }
 622 
 623     @Override
 624     public boolean isError(final ScriptObject sobj) {
 625         final ScriptObject errorProto = getErrorPrototype();
 626         ScriptObject proto = sobj.getProto();
 627         while (proto != null) {
 628             if (proto == errorProto) {
 629                 return true;
 630             }
 631             proto = proto.getProto();
 632         }
 633         return false;
 634     }
 635 
 636     @Override
 637     public ScriptObject newError(final String msg) {
 638         return new NativeError(msg, this);
 639     }
 640 
 641     @Override
 642     public ScriptObject newEvalError(final String msg) {
 643         return new NativeEvalError(msg, this);
 644     }
 645 
 646     @Override
 647     public ScriptObject newRangeError(final String msg) {
 648         return new NativeRangeError(msg, this);
 649     }
 650 
 651     @Override
 652     public ScriptObject newReferenceError(final String msg) {
 653         return new NativeReferenceError(msg, this);
 654     }
 655 
 656     @Override
 657     public ScriptObject newSyntaxError(final String msg) {
 658         return new NativeSyntaxError(msg, this);
 659     }
 660 
 661     @Override
 662     public ScriptObject newTypeError(final String msg) {
 663         return new NativeTypeError(msg, this);
 664     }
 665 
 666     @Override
 667     public ScriptObject newURIError(final String msg) {
 668         return new NativeURIError(msg, this);
 669     }
 670 
 671     @Override
 672     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
 673         return new GenericPropertyDescriptor(configurable, enumerable, this);
 674     }
 675 
 676     @Override
 677     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
 678         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
 679     }
 680 
 681     @Override
 682     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
 683         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
 684 
 685         if (get == null) {
 686             desc.delete(PropertyDescriptor.GET, false);
 687         }
 688 
 689         if (set == null) {
 690             desc.delete(PropertyDescriptor.SET, false);
 691         }
 692 
 693         return desc;
 694     }
 695 
 696 
 697     /**
 698      * Cache for compiled script classes.
 699      */
 700     @SuppressWarnings("serial")
 701     private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
 702         private final int size;
 703         private final ReferenceQueue<Class<?>> queue;
 704 
 705         ClassCache(int size) {
 706             super(size, 0.75f, true);
 707             this.size = size;
 708             this.queue = new ReferenceQueue<>();
 709         }
 710 
 711         void cache(final Source source, final Class<?> clazz) {
 712             put(source, new ClassReference(clazz, queue, source));
 713         }
 714 
 715         @Override
 716         protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
 717             return size() > size;
 718         }
 719 
 720         @Override
 721         public ClassReference get(Object key) {
 722             for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
 723                 remove(ref.source);
 724             }
 725             return super.get(key);
 726         }
 727 
 728     }
 729 
 730     private static class ClassReference extends SoftReference<Class<?>> {
 731         private final Source source;
 732 
 733         ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
 734             super(clazz, queue);
 735             this.source = source;
 736         }
 737     }
 738 
 739     // Class cache management
 740     @Override
 741     public Class<?> findCachedClass(final Source source) {
 742         assert classCache != null : "Class cache used without being initialized";
 743         ClassReference ref = classCache.get(source);
 744         return ref != null ? ref.get() : null;
 745     }
 746 
 747     @Override
 748     public void cacheClass(final Source source, final Class<?> clazz) {
 749         assert classCache != null : "Class cache used without being initialized";
 750         classCache.cache(source, clazz);
 751     }
 752 
 753     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
 754         final T obj = map.get(key);
 755         if (obj != null) {
 756             return obj;
 757         }
 758 
 759         try {
 760             final T newObj = creator.call();
 761             final T existingObj = map.putIfAbsent(key, newObj);
 762             return existingObj != null ? existingObj : newObj;
 763         } catch (final Exception exp) {
 764             throw new RuntimeException(exp);
 765         }
 766     }
 767 
 768     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
 769 
 770     @Override
 771     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
 772         return getLazilyCreatedValue(key, creator, namedInvokers);
 773     }
 774 
 775     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
 776 
 777     @Override
 778     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
 779         return getLazilyCreatedValue(key, creator, dynamicInvokers);
 780     }
 781 
 782     /**
 783      * This is the eval used when 'indirect' eval call is made.
 784      *
 785      * var global = this;
 786      * global.eval("print('hello')");
 787      *
 788      * @param self  eval scope
 789      * @param str   eval string
 790      *
 791      * @return the result of eval
 792      */
 793     public static Object eval(final Object self, final Object str) {
 794         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
 795     }
 796 
 797     /**
 798      * Direct eval
 799      *
 800      * @param self     The scope of eval passed as 'self'
 801      * @param str      Evaluated code
 802      * @param callThis "this" to be passed to the evaluated code
 803      * @param location location of the eval call
 804      * @param strict   is eval called a strict mode code?
 805      *
 806      * @return the return value of the eval
 807      *
 808      * This is directly invoked from generated when eval(code) is called in user code
 809      */
 810     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
 811         if (!(str instanceof String || str instanceof ConsString)) {
 812             return str;
 813         }
 814         final Global global = Global.instance();
 815         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
 816 
 817         return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
 818     }
 819 
 820     /**
 821      * Global print implementation - Nashorn extension
 822      *
 823      * @param self    scope
 824      * @param objects arguments to print
 825      *
 826      * @return result of print (undefined)
 827      */
 828     public static Object print(final Object self, final Object... objects) {
 829         return printImpl(false, objects);
 830     }
 831 
 832     /**
 833      * Global println implementation - Nashorn extension
 834      *
 835      * @param self    scope
 836      * @param objects arguments to print
 837      *
 838      * @return result of println (undefined)
 839      */
 840     public static Object println(final Object self, final Object... objects) {
 841         return printImpl(true, objects);
 842     }
 843 
 844     /**
 845      * Global load implementation - Nashorn extension
 846      *
 847      * @param self    scope
 848      * @param source  source to load
 849      *
 850      * @return result of load (undefined)
 851      *
 852      * @throws IOException if source could not be read
 853      */
 854     public static Object load(final Object self, final Object source) throws IOException {
 855         final Global global = Global.instance();
 856         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
 857         return global.getContext().load(scope, source);
 858     }
 859 
 860     /**
 861      * Global loadWithNewGlobal implementation - Nashorn extension
 862      *
 863      * @param self scope
 864      * @param args from plus (optional) arguments to be passed to the loaded script
 865      *
 866      * @return result of load (may be undefined)
 867      *
 868      * @throws IOException if source could not be read
 869      */
 870     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
 871         final Global global = Global.instance();
 872         final int length = args.length;
 873         final boolean hasArgs = 0 < length;
 874         final Object from = hasArgs ? args[0] : UNDEFINED;
 875         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
 876 
 877         return global.getContext().loadWithNewGlobal(from, arguments);
 878     }
 879 
 880     /**
 881      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
 882      *
 883      * @param self  self reference
 884      * @param code  exit code
 885      *
 886      * @return undefined (will never be reacheD)
 887      */
 888     public static Object exit(final Object self, final Object code) {
 889         System.exit(JSType.toInt32(code));
 890         return UNDEFINED;
 891     }
 892 
 893     // builtin prototype accessors
 894     ScriptObject getFunctionPrototype() {
 895         return ScriptFunction.getPrototype(builtinFunction);
 896     }
 897 
 898     ScriptObject getObjectPrototype() {
 899         return ScriptFunction.getPrototype(builtinObject);
 900     }
 901 
 902     ScriptObject getArrayPrototype() {
 903         return ScriptFunction.getPrototype(builtinArray);
 904     }
 905 
 906     ScriptObject getBooleanPrototype() {
 907         return ScriptFunction.getPrototype(builtinBoolean);
 908     }
 909 
 910     ScriptObject getNumberPrototype() {
 911         return ScriptFunction.getPrototype(builtinNumber);
 912     }
 913 
 914     ScriptObject getDatePrototype() {
 915         return ScriptFunction.getPrototype(builtinDate);
 916     }
 917 
 918     ScriptObject getRegExpPrototype() {
 919         return ScriptFunction.getPrototype(builtinRegExp);
 920     }
 921 
 922     ScriptObject getStringPrototype() {
 923         return ScriptFunction.getPrototype(builtinString);
 924     }
 925 
 926     ScriptObject getErrorPrototype() {
 927         return ScriptFunction.getPrototype(builtinError);
 928     }
 929 
 930     ScriptObject getEvalErrorPrototype() {
 931         return ScriptFunction.getPrototype(builtinEvalError);
 932     }
 933 
 934     ScriptObject getRangeErrorPrototype() {
 935         return ScriptFunction.getPrototype(builtinRangeError);
 936     }
 937 
 938     ScriptObject getReferenceErrorPrototype() {
 939         return ScriptFunction.getPrototype(builtinReferenceError);
 940     }
 941 
 942     ScriptObject getSyntaxErrorPrototype() {
 943         return ScriptFunction.getPrototype(builtinSyntaxError);
 944     }
 945 
 946     ScriptObject getTypeErrorPrototype() {
 947         return ScriptFunction.getPrototype(builtinTypeError);
 948     }
 949 
 950     ScriptObject getURIErrorPrototype() {
 951         return ScriptFunction.getPrototype(builtinURIError);
 952     }
 953 
 954     ScriptObject getJavaImporterPrototype() {
 955         return ScriptFunction.getPrototype(builtinJavaImporter);
 956     }
 957 
 958     ScriptObject getJSAdapterPrototype() {
 959         return ScriptFunction.getPrototype(builtinJSAdapter);
 960     }
 961 
 962     ScriptObject getArrayBufferPrototype() {
 963         return ScriptFunction.getPrototype(builtinArrayBuffer);
 964     }
 965 
 966     ScriptObject getInt8ArrayPrototype() {
 967         return ScriptFunction.getPrototype(builtinInt8Array);
 968     }
 969 
 970     ScriptObject getUint8ArrayPrototype() {
 971         return ScriptFunction.getPrototype(builtinUint8Array);
 972     }
 973 
 974     ScriptObject getUint8ClampedArrayPrototype() {
 975         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
 976     }
 977 
 978     ScriptObject getInt16ArrayPrototype() {
 979         return ScriptFunction.getPrototype(builtinInt16Array);
 980     }
 981 
 982     ScriptObject getUint16ArrayPrototype() {
 983         return ScriptFunction.getPrototype(builtinUint16Array);
 984     }
 985 
 986     ScriptObject getInt32ArrayPrototype() {
 987         return ScriptFunction.getPrototype(builtinInt32Array);
 988     }
 989 
 990     ScriptObject getUint32ArrayPrototype() {
 991         return ScriptFunction.getPrototype(builtinUint32Array);
 992     }
 993 
 994     ScriptObject getFloat32ArrayPrototype() {
 995         return ScriptFunction.getPrototype(builtinFloat32Array);
 996     }
 997 
 998     ScriptObject getFloat64ArrayPrototype() {
 999         return ScriptFunction.getPrototype(builtinFloat64Array);
1000     }
1001 
1002     // Builtin PropertyMap accessors
1003     PropertyMap getAccessorPropertyDescriptorMap() {
1004         return accessorPropertyDescriptorMap;
1005     }
1006 
1007     PropertyMap getArrayBufferViewMap() {
1008         return arrayBufferViewMap;
1009     }
1010 
1011     PropertyMap getDataPropertyDescriptorMap() {
1012         return dataPropertyDescriptorMap;
1013     }
1014 
1015     PropertyMap getGenericPropertyDescriptorMap() {
1016         return genericPropertyDescriptorMap;
1017     }
1018 
1019     PropertyMap getArgumentsMap() {
1020         return nativeArgumentsMap;
1021     }
1022 
1023     PropertyMap getArrayMap() {
1024         return nativeArrayMap;
1025     }
1026 
1027     PropertyMap getArrayBufferMap() {
1028         return nativeArrayBufferMap;
1029     }
1030 
1031     PropertyMap getBooleanMap() {
1032         return nativeBooleanMap;
1033     }
1034 
1035     PropertyMap getDateMap() {
1036         return nativeDateMap;
1037     }
1038 
1039     PropertyMap getErrorMap() {
1040         return nativeErrorMap;
1041     }
1042 
1043     PropertyMap getEvalErrorMap() {
1044         return nativeEvalErrorMap;
1045     }
1046 
1047     PropertyMap getJSAdapterMap() {
1048         return nativeJSAdapterMap;
1049     }
1050 
1051     PropertyMap getJavaImporterMap() {
1052         return nativeJavaImporterMap;
1053     }
1054 
1055     PropertyMap getNumberMap() {
1056         return nativeNumberMap;
1057     }
1058 
1059     PropertyMap getRangeErrorMap() {
1060         return nativeRangeErrorMap;
1061     }
1062 
1063     PropertyMap getReferenceErrorMap() {
1064         return nativeReferenceErrorMap;
1065     }
1066 
1067     PropertyMap getRegExpMap() {
1068         return nativeRegExpMap;
1069     }
1070 
1071     PropertyMap getRegExpExecResultMap() {
1072         return nativeRegExpExecResultMap;
1073     }
1074 
1075     PropertyMap getStrictArgumentsMap() {
1076         return nativeStrictArgumentsMap;
1077     }
1078 
1079     PropertyMap getStringMap() {
1080         return nativeStringMap;
1081     }
1082 
1083     PropertyMap getSyntaxErrorMap() {
1084         return nativeSyntaxErrorMap;
1085     }
1086 
1087     PropertyMap getTypeErrorMap() {
1088         return nativeTypeErrorMap;
1089     }
1090 
1091     PropertyMap getURIErrorMap() {
1092         return nativeURIErrorMap;
1093     }
1094 
1095     PropertyMap getPrototypeObjectMap() {
1096         return prototypeObjectMap;
1097     }
1098 
1099     PropertyMap getObjectMap() {
1100         return objectMap;
1101     }
1102 
1103     PropertyMap getFunctionMap() {
1104         return functionMap;
1105     }
1106 
1107     PropertyMap getAnonymousFunctionMap() {
1108         return anonymousFunctionMap;
1109     }
1110 
1111     PropertyMap getStrictFunctionMap() {
1112         return strictFunctionMap;
1113     }
1114 
1115     PropertyMap getBoundFunctionMap() {
1116         return boundFunctionMap;
1117     }
1118 
1119     private ScriptFunction getBuiltinArray() {
1120         return builtinArray;
1121     }
1122 
1123     ScriptFunction getTypeErrorThrower() {
1124         return typeErrorThrower;
1125     }
1126 
1127     /**
1128      * Called from compiled script code to test if builtin has been overridden
1129      *
1130      * @return true if builtin array has not been overridden
1131      */
1132     public static boolean isBuiltinArray() {
1133         final Global instance = Global.instance();
1134         return instance.array == instance.getBuiltinArray();
1135     }
1136 
1137     private ScriptFunction getBuiltinBoolean() {
1138         return builtinBoolean;
1139     }
1140 
1141     /**
1142      * Called from compiled script code to test if builtin has been overridden
1143      *
1144      * @return true if builtin boolean has not been overridden
1145      */
1146     public static boolean isBuiltinBoolean() {
1147         final Global instance = Global.instance();
1148         return instance._boolean == instance.getBuiltinBoolean();
1149     }
1150 
1151     private ScriptFunction getBuiltinDate() {
1152         return builtinDate;
1153     }
1154 
1155     /**
1156      * Called from compiled script code to test if builtin has been overridden
1157      *
1158      * @return true if builtin date has not been overridden
1159      */
1160     public static boolean isBuiltinDate() {
1161         final Global instance = Global.instance();
1162         return instance.date == instance.getBuiltinDate();
1163     }
1164 
1165     private ScriptFunction getBuiltinError() {
1166         return builtinError;
1167     }
1168 
1169     /**
1170      * Called from compiled script code to test if builtin has been overridden
1171      *
1172      * @return true if builtin error has not been overridden
1173      */
1174     public static boolean isBuiltinError() {
1175         final Global instance = Global.instance();
1176         return instance.error == instance.getBuiltinError();
1177     }
1178 
1179     private ScriptFunction getBuiltinEvalError() {
1180         return builtinEvalError;
1181     }
1182 
1183     /**
1184      * Called from compiled script code to test if builtin has been overridden
1185      *
1186      * @return true if builtin eval error has not been overridden
1187      */
1188     public static boolean isBuiltinEvalError() {
1189         final Global instance = Global.instance();
1190         return instance.evalError == instance.getBuiltinEvalError();
1191     }
1192 
1193     private ScriptFunction getBuiltinFunction() {
1194         return builtinFunction;
1195     }
1196 
1197     /**
1198      * Called from compiled script code to test if builtin has been overridden
1199      *
1200      * @return true if builtin function has not been overridden
1201      */
1202     public static boolean isBuiltinFunction() {
1203         final Global instance = Global.instance();
1204         return instance.function == instance.getBuiltinFunction();
1205     }
1206 
1207     private ScriptFunction getBuiltinJSAdapter() {
1208         return builtinJSAdapter;
1209     }
1210 
1211     /**
1212      * Called from compiled script code to test if builtin has been overridden
1213      *
1214      * @return true if builtin JSAdapter has not been overridden
1215      */
1216     public static boolean isBuiltinJSAdapter() {
1217         final Global instance = Global.instance();
1218         return instance.jsadapter == instance.getBuiltinJSAdapter();
1219     }
1220 
1221     private ScriptObject getBuiltinJSON() {
1222         return builtinJSON;
1223     }
1224 
1225     /**
1226      * Called from compiled script code to test if builtin has been overridden
1227      *
1228      * @return true if builtin JSON has has not been overridden
1229      */
1230     public static boolean isBuiltinJSON() {
1231         final Global instance = Global.instance();
1232         return instance.json == instance.getBuiltinJSON();
1233     }
1234 
1235     private ScriptObject getBuiltinJava() {
1236         return builtinJava;
1237     }
1238 
1239     /**
1240      * Called from compiled script code to test if builtin has been overridden
1241      *
1242      * @return true if builtin Java has not been overridden
1243      */
1244     public static boolean isBuiltinJava() {
1245         final Global instance = Global.instance();
1246         return instance.java == instance.getBuiltinJava();
1247     }
1248 
1249     private ScriptObject getBuiltinJavax() {
1250         return builtinJavax;
1251     }
1252 
1253     /**
1254      * Called from compiled script code to test if builtin has been overridden
1255      *
1256      * @return true if builtin Javax has not been overridden
1257      */
1258     public static boolean isBuiltinJavax() {
1259         final Global instance = Global.instance();
1260         return instance.javax == instance.getBuiltinJavax();
1261     }
1262 
1263     private ScriptObject getBuiltinJavaImporter() {
1264         return builtinJavaImporter;
1265     }
1266 
1267     /**
1268      * Called from compiled script code to test if builtin has been overridden
1269      *
1270      * @return true if builtin Java importer has not been overridden
1271      */
1272     public static boolean isBuiltinJavaImporter() {
1273         final Global instance = Global.instance();
1274         return instance.javaImporter == instance.getBuiltinJavaImporter();
1275     }
1276 
1277     private ScriptObject getBuiltinMath() {
1278         return builtinMath;
1279     }
1280 
1281     /**
1282      * Called from compiled script code to test if builtin has been overridden
1283      *
1284      * @return true if builtin math has not been overridden
1285      */
1286     public static boolean isBuiltinMath() {
1287         final Global instance = Global.instance();
1288         return instance.math == instance.getBuiltinMath();
1289     }
1290 
1291     private ScriptFunction getBuiltinNumber() {
1292         return builtinNumber;
1293     }
1294 
1295     /**
1296      * Called from compiled script code to test if builtin has been overridden
1297      *
1298      * @return true if builtin number has not been overridden
1299      */
1300     public static boolean isBuiltinNumber() {
1301         final Global instance = Global.instance();
1302         return instance.number == instance.getBuiltinNumber();
1303     }
1304 
1305     private ScriptFunction getBuiltinObject() {
1306         return builtinObject;
1307     }
1308 
1309     /**
1310      * Called from compiled script code to test if builtin has been overridden
1311      *
1312      * @return true if builtin object has not been overridden
1313      */
1314     public static boolean isBuiltinObject() {
1315         final Global instance = Global.instance();
1316         return instance.object == instance.getBuiltinObject();
1317     }
1318 
1319     private ScriptObject getBuiltinPackages() {
1320         return builtinPackages;
1321     }
1322 
1323     /**
1324      * Called from compiled script code to test if builtin has been overridden
1325      *
1326      * @return true if builtin package has not been overridden
1327      */
1328     public static boolean isBuiltinPackages() {
1329         final Global instance = Global.instance();
1330         return instance.packages == instance.getBuiltinPackages();
1331     }
1332 
1333     private ScriptFunction getBuiltinRangeError() {
1334         return builtinRangeError;
1335     }
1336 
1337     /**
1338      * Called from compiled script code to test if builtin has been overridden
1339      *
1340      * @return true if builtin range error has not been overridden
1341      */
1342     public static boolean isBuiltinRangeError() {
1343         final Global instance = Global.instance();
1344         return instance.rangeError == instance.getBuiltinRangeError();
1345     }
1346 
1347     private ScriptFunction getBuiltinReferenceError() {
1348         return builtinReferenceError;
1349     }
1350 
1351     /**
1352      * Called from compiled script code to test if builtin has been overridden
1353      *
1354      * @return true if builtin reference error has not been overridden
1355      */
1356     public static boolean isBuiltinReferenceError() {
1357         final Global instance = Global.instance();
1358         return instance.referenceError == instance.getBuiltinReferenceError();
1359     }
1360 
1361     private ScriptFunction getBuiltinRegExp() {
1362         return builtinRegExp;
1363     }
1364 
1365     /**
1366      * Called from compiled script code to test if builtin has been overridden
1367      *
1368      * @return true if builtin regexp has not been overridden
1369      */
1370     public static boolean isBuiltinRegExp() {
1371         final Global instance = Global.instance();
1372         return instance.regexp == instance.getBuiltinRegExp();
1373     }
1374 
1375     private ScriptFunction getBuiltinString() {
1376         return builtinString;
1377     }
1378 
1379     /**
1380      * Called from compiled script code to test if builtin has been overridden
1381      *
1382      * @return true if builtin Java has not been overridden
1383      */
1384     public static boolean isBuiltinString() {
1385         final Global instance = Global.instance();
1386         return instance.string == instance.getBuiltinString();
1387     }
1388 
1389     private ScriptFunction getBuiltinSyntaxError() {
1390         return builtinSyntaxError;
1391     }
1392 
1393     /**
1394      * Called from compiled script code to test if builtin has been overridden
1395      *
1396      * @return true if builtin syntax error has not been overridden
1397      */
1398     public static boolean isBuiltinSyntaxError() {
1399         final Global instance = Global.instance();
1400         return instance.syntaxError == instance.getBuiltinSyntaxError();
1401     }
1402 
1403     private ScriptFunction getBuiltinTypeError() {
1404         return builtinTypeError;
1405     }
1406 
1407     /**
1408      * Called from compiled script code to test if builtin has been overridden
1409      *
1410      * @return true if builtin type error has not been overridden
1411      */
1412     public static boolean isBuiltinTypeError() {
1413         final Global instance = Global.instance();
1414         return instance.typeError == instance.getBuiltinTypeError();
1415     }
1416 
1417     private ScriptFunction getBuiltinURIError() {
1418         return builtinURIError;
1419     }
1420 
1421     /**
1422      * Called from compiled script code to test if builtin has been overridden
1423      *
1424      * @return true if builtin URI error has not been overridden
1425      */
1426     public static boolean isBuiltinURIError() {
1427         final Global instance = Global.instance();
1428         return instance.uriError == instance.getBuiltinURIError();
1429     }
1430 
1431     @Override
1432     public String getClassName() {
1433         return "global";
1434     }
1435 
1436     /**
1437      * Copy function used to clone NativeRegExp objects.
1438      *
1439      * @param regexp a NativeRegExp to clone
1440      *
1441      * @return copy of the given regexp object
1442      */
1443     public static Object regExpCopy(final Object regexp) {
1444         return new NativeRegExp((NativeRegExp)regexp);
1445     }
1446 
1447     /**
1448      * Convert given object to NativeRegExp type.
1449      *
1450      * @param obj object to be converted
1451      * @return NativeRegExp instance
1452      */
1453     public static NativeRegExp toRegExp(final Object obj) {
1454         if (obj instanceof NativeRegExp) {
1455             return (NativeRegExp)obj;
1456         }
1457         return new NativeRegExp(JSType.toString(obj));
1458     }
1459 
1460     /**
1461      * ECMA 9.9 ToObject implementation
1462      *
1463      * @param obj  an item for which to run ToObject
1464      * @return ToObject version of given item
1465      */
1466     public static Object toObject(final Object obj) {
1467         if (obj == null || obj == UNDEFINED) {
1468             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1469         }
1470 
1471         if (obj instanceof ScriptObject) {
1472             return obj;
1473         }
1474 
1475         return instance().wrapAsObject(obj);
1476     }
1477 
1478     /**
1479      * Allocate a new object array.
1480      *
1481      * @param initial object values.
1482      * @return the new array
1483      */
1484     public static NativeArray allocate(final Object[] initial) {
1485         ArrayData arrayData = ArrayData.allocate(initial);
1486 
1487         for (int index = 0; index < initial.length; index++) {
1488             final Object value = initial[index];
1489 
1490             if (value == ScriptRuntime.EMPTY) {
1491                 arrayData = arrayData.delete(index);
1492             }
1493         }
1494 
1495         return new NativeArray(arrayData);
1496     }
1497 
1498     /**
1499      * Allocate a new number array.
1500      *
1501      * @param initial number values.
1502      * @return the new array
1503      */
1504     public static NativeArray allocate(final double[] initial) {
1505         return new NativeArray(ArrayData.allocate(initial));
1506     }
1507 
1508     /**
1509      * Allocate a new long array.
1510      *
1511      * @param initial number values.
1512      * @return the new array
1513      */
1514     public static NativeArray allocate(final long[] initial) {
1515         return new NativeArray(ArrayData.allocate(initial));
1516     }
1517 
1518     /**
1519      * Allocate a new integer array.
1520      *
1521      * @param initial number values.
1522      * @return the new array
1523      */
1524     public static NativeArray allocate(final int[] initial) {
1525         return new NativeArray(ArrayData.allocate(initial));
1526     }
1527 
1528     /**
1529      * Allocate a new object array for arguments.
1530      *
1531      * @param arguments initial arguments passed.
1532      * @param callee reference to the function that uses arguments object
1533      * @param numParams actual number of declared parameters
1534      *
1535      * @return the new array
1536      */
1537     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1538         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1539     }
1540 
1541     /**
1542      * Called from generated to check if given function is the builtin 'eval'. If
1543      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1544      *
1545      * @param  fn function object that is checked
1546      * @return true if fn is the builtin eval
1547      */
1548     public static boolean isEval(final Object fn) {
1549         return fn == Global.instance().builtinEval;
1550     }
1551 
1552     /**
1553      * Create a new RegExp object.
1554      *
1555      * @param expression Regular expression.
1556      * @param options    Search options.
1557      *
1558      * @return New RegExp object.
1559      */
1560     public static Object newRegExp(final String expression, final String options) {
1561         if (options == null) {
1562             return new NativeRegExp(expression);
1563         }
1564         return new NativeRegExp(expression, options);
1565     }
1566 
1567     /**
1568      * Get the object prototype
1569      *
1570      * @return the object prototype
1571      */
1572     public static ScriptObject objectPrototype() {
1573         return Global.instance().getObjectPrototype();
1574     }
1575 
1576     /**
1577      * Create a new empty object instance.
1578      *
1579      * @return New empty object.
1580      */
1581     public static ScriptObject newEmptyInstance() {
1582         return Global.instance().newObject();
1583     }
1584 
1585     /**
1586      * Check if a given object is a ScriptObject, raises an exception if this is
1587      * not the case
1588      *
1589      * @param obj and object to check
1590      */
1591     public static void checkObject(final Object obj) {
1592         if (!(obj instanceof ScriptObject)) {
1593             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1594         }
1595     }
1596 
1597     /**
1598      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1599      * if this object is null or undefined.
1600      *
1601      * @param obj an object to check
1602      */
1603     public static void checkObjectCoercible(final Object obj) {
1604         if (obj == null || obj == UNDEFINED) {
1605             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1606         }
1607     }
1608 
1609     /**
1610      * Get the current split state.
1611      *
1612      * @return current split state
1613      */
1614     @Override
1615     public int getSplitState() {
1616         return splitState;
1617     }
1618 
1619     /**
1620      * Set the current split state.
1621      *
1622      * @param state current split state
1623      */
1624     @Override
1625     public void setSplitState(final int state) {
1626         splitState = state;
1627     }
1628 
1629     private void init() {
1630         assert Context.getGlobal() == this : "this global is not set as current";
1631 
1632         final ScriptEnvironment env = getContext().getEnv();
1633 
1634         // duplicate PropertyMaps of Native* classes
1635         copyInitialMaps(env);
1636 
1637         // initialize Function and Object constructor
1638         initFunctionAndObject();
1639 
1640         // Now fix Global's own proto.
1641         this.setProto(getObjectPrototype());
1642 
1643         // initialize global function properties
1644         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1645 
1646         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
1647         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1648         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1649         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1650         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1651         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1652         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1653         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1654         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1655         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1656         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1657         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1658         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1659         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1660         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1661 
1662         // built-in constructors
1663         this.builtinArray     = (ScriptFunction)initConstructor("Array");
1664         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
1665         this.builtinDate      = (ScriptFunction)initConstructor("Date");
1666         this.builtinJSON      = initConstructor("JSON");
1667         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1668         this.builtinMath      = initConstructor("Math");
1669         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
1670         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
1671         this.builtinString    = (ScriptFunction)initConstructor("String");
1672 
1673         // initialize String.prototype.length to 0
1674         // add String.prototype.length
1675         final ScriptObject stringPrototype = getStringPrototype();
1676         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1677 
1678         // set isArray flag on Array.prototype
1679         final ScriptObject arrayPrototype = getArrayPrototype();
1680         arrayPrototype.setIsArray();
1681 
1682         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1683 
1684         // initialize default regexp object
1685         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1686 
1687         // RegExp.prototype should behave like a RegExp object. So copy the
1688         // properties.
1689         final ScriptObject regExpProto = getRegExpPrototype();
1690         regExpProto.addBoundProperties(DEFAULT_REGEXP);
1691 
1692         // Error stuff
1693         initErrorObjects();
1694 
1695         // java access
1696         if (! env._no_java) {
1697             initJavaAccess();
1698         }
1699 
1700         if (! env._no_typed_arrays) {
1701             initTypedArray();
1702         }
1703 
1704         if (env._scripting) {
1705             initScripting(env);
1706         }
1707 
1708         if (Context.DEBUG && System.getSecurityManager() == null) {
1709             initDebug();
1710         }
1711 
1712         copyBuiltins();
1713 
1714         // initialized with strings so that typeof will work as expected.
1715         this.__FILE__ = "";
1716         this.__DIR__  = "";
1717         this.__LINE__ = 0.0;
1718 
1719         // expose script (command line) arguments as "arguments" property of global
1720         final List<String> arguments = env.getArguments();
1721         final Object argsObj = wrapAsObject(arguments.toArray());
1722 
1723         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1724         if (env._scripting) {
1725             // synonym for "arguments" in scripting mode
1726             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1727         }
1728     }
1729 
1730     private void initErrorObjects() {
1731         // Error objects
1732         this.builtinError = (ScriptFunction)initConstructor("Error");
1733         final ScriptObject errorProto = getErrorPrototype();
1734 
1735         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1736         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1737         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1738         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1739         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1740         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1741         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1742         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1743         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1744         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1745         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1746         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1747         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1748 
1749         // ECMA 15.11.4.2 Error.prototype.name
1750         // Error.prototype.name = "Error";
1751         errorProto.set(NativeError.NAME, "Error", false);
1752         // ECMA 15.11.4.3 Error.prototype.message
1753         // Error.prototype.message = "";
1754         errorProto.set(NativeError.MESSAGE, "", false);
1755 
1756         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1757         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1758         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1759         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1760         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1761         this.builtinURIError = initErrorSubtype("URIError", errorProto);
1762     }
1763 
1764     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1765         final ScriptObject cons = initConstructor(name);
1766         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1767         prototype.set(NativeError.NAME, name, false);
1768         prototype.set(NativeError.MESSAGE, "", false);
1769         prototype.setProto(errorProto);
1770         return (ScriptFunction)cons;
1771     }
1772 
1773     private void initJavaAccess() {
1774         final ScriptObject objectProto = getObjectPrototype();
1775         this.builtinPackages = new NativeJavaPackage("", objectProto);
1776         this.builtinCom = new NativeJavaPackage("com", objectProto);
1777         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1778         this.builtinJava = new NativeJavaPackage("java", objectProto);
1779         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1780         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1781         this.builtinOrg = new NativeJavaPackage("org", objectProto);
1782         this.builtinJavaImporter = initConstructor("JavaImporter");
1783         this.builtinJavaApi = initConstructor("Java");
1784     }
1785 
1786     private void initScripting(final ScriptEnvironment scriptEnv) {
1787         Object value;
1788         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1789         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1790 
1791         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1792         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1793 
1794         final String execName = ScriptingFunctions.EXEC_NAME;
1795         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1796         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1797 
1798         // Nashorn extension: global.echo (scripting-mode-only)
1799         // alias for "print"
1800         value = get("print");
1801         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1802 
1803         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1804         final ScriptObject options = newObject();
1805         copyOptions(options, scriptEnv);
1806         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1807 
1808         // Nashorn extension: global.$ENV (scripting-mode-only)
1809         if (System.getSecurityManager() == null) {
1810             // do not fill $ENV if we have a security manager around
1811             // Retrieve current state of ENV variables.
1812             final ScriptObject env = newObject();
1813             env.putAll(System.getenv(), scriptEnv._strict);
1814             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1815         } else {
1816             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1817         }
1818 
1819         // add other special properties for exec support
1820         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1821         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1822         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1823     }
1824 
1825     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1826         for (Field f : scriptEnv.getClass().getFields()) {
1827             try {
1828                 options.set(f.getName(), f.get(scriptEnv), false);
1829             } catch (final IllegalArgumentException | IllegalAccessException exp) {
1830                 throw new RuntimeException(exp);
1831             }
1832         }
1833     }
1834 
1835     private void initTypedArray() {
1836         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
1837         this.builtinInt8Array         = initConstructor("Int8Array");
1838         this.builtinUint8Array        = initConstructor("Uint8Array");
1839         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1840         this.builtinInt16Array        = initConstructor("Int16Array");
1841         this.builtinUint16Array       = initConstructor("Uint16Array");
1842         this.builtinInt32Array        = initConstructor("Int32Array");
1843         this.builtinUint32Array       = initConstructor("Uint32Array");
1844         this.builtinFloat32Array      = initConstructor("Float32Array");
1845         this.builtinFloat64Array      = initConstructor("Float64Array");
1846     }
1847 
1848     private void copyBuiltins() {
1849         this.array             = this.builtinArray;
1850         this._boolean          = this.builtinBoolean;
1851         this.date              = this.builtinDate;
1852         this.error             = this.builtinError;
1853         this.evalError         = this.builtinEvalError;
1854         this.function          = this.builtinFunction;
1855         this.jsadapter         = this.builtinJSAdapter;
1856         this.json              = this.builtinJSON;
1857         this.com               = this.builtinCom;
1858         this.edu               = this.builtinEdu;
1859         this.java              = this.builtinJava;
1860         this.javafx            = this.builtinJavafx;
1861         this.javax             = this.builtinJavax;
1862         this.org               = this.builtinOrg;
1863         this.javaImporter      = this.builtinJavaImporter;
1864         this.javaApi           = this.builtinJavaApi;
1865         this.math              = this.builtinMath;
1866         this.number            = this.builtinNumber;
1867         this.object            = this.builtinObject;
1868         this.packages          = this.builtinPackages;
1869         this.rangeError        = this.builtinRangeError;
1870         this.referenceError    = this.builtinReferenceError;
1871         this.regexp            = this.builtinRegExp;
1872         this.string            = this.builtinString;
1873         this.syntaxError       = this.builtinSyntaxError;
1874         this.typeError         = this.builtinTypeError;
1875         this.uriError          = this.builtinURIError;
1876         this.arrayBuffer       = this.builtinArrayBuffer;
1877         this.int8Array         = this.builtinInt8Array;
1878         this.uint8Array        = this.builtinUint8Array;
1879         this.uint8ClampedArray = this.builtinUint8ClampedArray;
1880         this.int16Array        = this.builtinInt16Array;
1881         this.uint16Array       = this.builtinUint16Array;
1882         this.int32Array        = this.builtinInt32Array;
1883         this.uint32Array       = this.builtinUint32Array;
1884         this.float32Array      = this.builtinFloat32Array;
1885         this.float64Array      = this.builtinFloat64Array;
1886     }
1887 
1888     private void initDebug() {
1889         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1890     }
1891 
1892     @SuppressWarnings("resource")
1893     private static Object printImpl(final boolean newLine, final Object... objects) {
1894         final PrintWriter out = Global.getEnv().getOut();
1895         final StringBuilder sb = new StringBuilder();
1896 
1897         for (final Object object : objects) {
1898             if (sb.length() != 0) {
1899                 sb.append(' ');
1900             }
1901 
1902             sb.append(JSType.toString(object));
1903         }
1904 
1905         // Print all at once to ensure thread friendly result.
1906         if (newLine) {
1907             out.println(sb.toString());
1908         } else {
1909             out.print(sb.toString());
1910         }
1911 
1912         out.flush();
1913 
1914         return UNDEFINED;
1915     }
1916 
1917     /**
1918      * These classes are generated by nasgen tool and so we have to use
1919      * reflection to load and create new instance of these classes.
1920      */
1921     private ScriptObject initConstructor(final String name) {
1922         try {
1923             // Assuming class name pattern for built-in JS constructors.
1924             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1925 
1926             sb.append("Native");
1927             sb.append(name);
1928             sb.append("$Constructor");
1929 
1930             final Class<?>     funcClass = Class.forName(sb.toString());
1931             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
1932 
1933             if (res instanceof ScriptFunction) {
1934                 // All global constructor prototypes are not-writable,
1935                 // not-enumerable and not-configurable.
1936                 final ScriptFunction func = (ScriptFunction)res;
1937                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1938             }
1939 
1940             if (res.getProto() == null) {
1941                 res.setProto(getObjectPrototype());
1942             }
1943 
1944             return res;
1945 
1946         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1947             throw new RuntimeException(e);
1948         }
1949     }
1950 
1951     private void copyInitialMaps(final ScriptEnvironment env) {
1952         this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
1953         this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
1954         this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
1955         this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
1956         this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
1957         this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
1958         this.nativeDateMap = NativeDate.getInitialMap().duplicate();
1959         this.nativeErrorMap = NativeError.getInitialMap().duplicate();
1960         this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
1961         this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
1962         this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
1963         this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
1964         this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
1965         this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
1966         this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
1967         this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
1968         this.nativeStringMap = NativeString.getInitialMap().duplicate();
1969         this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
1970         this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
1971         this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
1972         this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
1973         this.objectMap = JO.getInitialMap().duplicate();
1974         this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
1975         this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
1976         this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
1977         this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
1978 
1979         // java
1980         if (! env._no_java) {
1981             this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
1982         }
1983 
1984         // typed arrays
1985         if (! env._no_typed_arrays) {
1986             this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
1987             this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
1988         }
1989     }
1990 
1991     // Function and Object constructors are inter-dependent. Also,
1992     // Function.prototype
1993     // functions are not properly initialized. We fix the references here.
1994     // NOTE: be careful if you want to re-order the operations here. You may
1995     // have
1996     // to play with object references carefully!!
1997     private void initFunctionAndObject() {
1998         // First-n-foremost is Function
1999         this.builtinFunction = (ScriptFunction)initConstructor("Function");
2000 
2001         // create global anonymous function
2002         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
2003         // need to copy over members of Function.prototype to anon function
2004         anon.addBoundProperties(getFunctionPrototype());
2005 
2006         // Function.prototype === Object.getPrototypeOf(Function) ===
2007         // <anon-function>
2008         builtinFunction.setProto(anon);
2009         builtinFunction.setPrototype(anon);
2010         anon.set("constructor", builtinFunction, false);
2011         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2012 
2013         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2014         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false);
2015         typeErrorThrower.setPrototype(UNDEFINED);
2016         // Non-constructor built-in functions do not have "prototype" property
2017         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2018         typeErrorThrower.preventExtensions();
2019 
2020         // now initialize Object
2021         this.builtinObject = (ScriptFunction)initConstructor("Object");
2022         final ScriptObject ObjectPrototype = getObjectPrototype();
2023         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2024         anon.setProto(ObjectPrototype);
2025 
2026         // Function valued properties of Function.prototype were not properly
2027         // initialized. Because, these were created before global.function and
2028         // global.object were not initialized.
2029         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2030         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2031             final Object key = property.getKey();
2032             final Object value = builtinFunction.get(key);
2033 
2034             if (value instanceof ScriptFunction && value != anon) {
2035                 final ScriptFunction func = (ScriptFunction)value;
2036                 func.setProto(getFunctionPrototype());
2037                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2038                 if (prototype != null) {
2039                     prototype.setProto(ObjectPrototype);
2040                 }
2041             }
2042         }
2043 
2044         // For function valued properties of Object and Object.prototype, make
2045         // sure prototype's proto chain ends with Object.prototype
2046         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2047             final Object key = property.getKey();
2048             final Object value = builtinObject.get(key);
2049 
2050             if (value instanceof ScriptFunction) {
2051                 final ScriptFunction func = (ScriptFunction)value;
2052                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2053                 if (prototype != null) {
2054                     prototype.setProto(ObjectPrototype);
2055                 }
2056             }
2057         }
2058 
2059         properties = getObjectPrototype().getMap().getProperties();
2060         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2061             final Object key   = property.getKey();
2062             final Object value = ObjectPrototype.get(key);
2063 
2064             if (key.equals("constructor")) {
2065                 continue;
2066             }
2067 
2068             if (value instanceof ScriptFunction) {
2069                 final ScriptFunction func = (ScriptFunction)value;
2070                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2071                 if (prototype != null) {
2072                     prototype.setProto(ObjectPrototype);
2073                 }
2074             }
2075         }
2076     }
2077 
2078     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
2079         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2080     }
2081 
2082     RegExpResult getLastRegExpResult() {
2083         return lastRegExpResult;
2084     }
2085 
2086     void setLastRegExpResult(final RegExpResult regExpResult) {
2087         this.lastRegExpResult = regExpResult;
2088     }
2089 
2090 }