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