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