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     /** TypedArray (int8) */
 230     @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 231     public volatile Object int8Array;
 232 
 233     /** TypedArray (uint8) */
 234     @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 235     public volatile Object uint8Array;
 236 
 237     /** TypedArray (uint8) - Clamped */
 238     @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 239     public volatile Object uint8ClampedArray;
 240 
 241     /** TypedArray (int16) */
 242     @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 243     public volatile Object int16Array;
 244 
 245     /** TypedArray (uint16) */
 246     @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 247     public volatile Object uint16Array;
 248 
 249     /** TypedArray (int32) */
 250     @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 251     public volatile Object int32Array;
 252 
 253     /** TypedArray (uint32) */
 254     @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 255     public volatile Object uint32Array;
 256 
 257     /** TypedArray (float32) */
 258     @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 259     public volatile Object float32Array;
 260 
 261     /** TypedArray (float64) */
 262     @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 263     public volatile Object float64Array;
 264 
 265     /** Nashorn extension: Java access - global.Packages */
 266     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 267     public volatile Object packages;
 268 
 269     /** Nashorn extension: Java access - global.com */
 270     @Property(attributes = Attribute.NOT_ENUMERABLE)
 271     public volatile Object com;
 272 
 273     /** Nashorn extension: Java access - global.edu */
 274     @Property(attributes = Attribute.NOT_ENUMERABLE)
 275     public volatile Object edu;
 276 
 277     /** Nashorn extension: Java access - global.java */
 278     @Property(attributes = Attribute.NOT_ENUMERABLE)
 279     public volatile Object java;
 280 
 281     /** Nashorn extension: Java access - global.javafx */
 282     @Property(attributes = Attribute.NOT_ENUMERABLE)
 283     public volatile Object javafx;
 284 
 285     /** Nashorn extension: Java access - global.javax */
 286     @Property(attributes = Attribute.NOT_ENUMERABLE)
 287     public volatile Object javax;
 288 
 289     /** Nashorn extension: Java access - global.org */
 290     @Property(attributes = Attribute.NOT_ENUMERABLE)
 291     public volatile Object org;
 292 
 293     /** Nashorn extension: Java access - global.javaImporter */
 294     @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 295     public volatile Object javaImporter;
 296 
 297     /** Nashorn extension: global.Java Object constructor. */
 298     @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 299     public volatile Object javaApi;
 300 
 301     /** Nashorn extension: current script's file name */
 302     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 303     public Object __FILE__;
 304 
 305     /** Nashorn extension: current script's directory */
 306     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 307     public Object __DIR__;
 308 
 309     /** Nashorn extension: current source line number being executed */
 310     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 311     public Object __LINE__;
 312 
 313     /** Used as Date.prototype's default value */
 314     public NativeDate   DEFAULT_DATE;
 315 
 316     /** Used as RegExp.prototype's default value */
 317     public NativeRegExp DEFAULT_REGEXP;
 318 
 319     /*
 320      * Built-in constructor objects: Even if user changes dynamic values of
 321      * "Object", "Array" etc., we still want to keep original values of these
 322      * constructors here. For example, we need to be able to create array,
 323      * regexp literals even after user overwrites global "Array" or "RegExp"
 324      * constructor - see also ECMA 262 spec. Annex D.
 325      */
 326     private ScriptFunction builtinFunction;
 327     private ScriptFunction builtinObject;
 328     private ScriptFunction builtinArray;
 329     private ScriptFunction builtinBoolean;
 330     private ScriptFunction builtinDate;
 331     private ScriptObject   builtinJSON;
 332     private ScriptFunction builtinJSAdapter;
 333     private ScriptObject   builtinMath;
 334     private ScriptFunction builtinNumber;
 335     private ScriptFunction builtinRegExp;
 336     private ScriptFunction builtinString;
 337     private ScriptFunction builtinError;
 338     private ScriptFunction builtinEval;
 339     private ScriptFunction builtinEvalError;
 340     private ScriptFunction builtinRangeError;
 341     private ScriptFunction builtinReferenceError;
 342     private ScriptFunction builtinSyntaxError;
 343     private ScriptFunction builtinTypeError;
 344     private ScriptFunction builtinURIError;
 345     private ScriptObject   builtinPackages;
 346     private ScriptObject   builtinCom;
 347     private ScriptObject   builtinEdu;
 348     private ScriptObject   builtinJava;
 349     private ScriptObject   builtinJavafx;
 350     private ScriptObject   builtinJavax;
 351     private ScriptObject   builtinOrg;
 352     private ScriptObject   builtinJavaImporter;
 353     private ScriptObject   builtinJavaApi;
 354     private ScriptObject   builtinArrayBuffer;

 355     private ScriptObject   builtinInt8Array;
 356     private ScriptObject   builtinUint8Array;
 357     private ScriptObject   builtinUint8ClampedArray;
 358     private ScriptObject   builtinInt16Array;
 359     private ScriptObject   builtinUint16Array;
 360     private ScriptObject   builtinInt32Array;
 361     private ScriptObject   builtinUint32Array;
 362     private ScriptObject   builtinFloat32Array;
 363     private ScriptObject   builtinFloat64Array;
 364 
 365     /*
 366      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 367      */
 368     private ScriptFunction typeErrorThrower;
 369 
 370     // Flag to indicate that a split method issued a return statement
 371     private int splitState = -1;
 372 
 373     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 374     private RegExpResult lastRegExpResult;
 375 
 376     private static final MethodHandle EVAL              = findOwnMH("eval",              Object.class, Object.class, Object.class);
 377     private static final MethodHandle PRINT             = findOwnMH("print",             Object.class, Object.class, Object[].class);
 378     private static final MethodHandle PRINTLN           = findOwnMH("println",           Object.class, Object.class, Object[].class);
 379     private static final MethodHandle LOAD              = findOwnMH("load",              Object.class, Object.class, Object.class);
 380     private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
 381     private static final MethodHandle EXIT              = findOwnMH("exit",              Object.class, Object.class, Object.class);
 382 
 383     // initialized by nasgen
 384     private static PropertyMap $nasgenmap$;
 385 
 386     // context to which this global belongs to
 387     private final Context context;
 388 
 389     @Override
 390     protected Context getContext() {
 391         return context;
 392     }
 393 
 394     // performs initialization checks for Global constructor and returns the
 395     // PropertyMap, if everything is fine.
 396     private static PropertyMap checkAndGetMap(final Context context) {
 397         // security check first
 398         final SecurityManager sm = System.getSecurityManager();
 399         if (sm != null) {
 400             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 401         }
 402 
 403         // null check on context
 404         context.getClass();
 405 
 406         /*
 407          * Duplicate global's map and use it. This way the initial Map filled
 408          * by nasgen (referenced from static field in this class) is retained
 409          * 'as is' (as that one is process wide singleton.
 410          */
 411         return $nasgenmap$.duplicate();
 412     }
 413 
 414     /**
 415      * Constructor
 416      *
 417      * @param context the context
 418      */
 419     public Global(final Context context) {
 420         super(checkAndGetMap(context));
 421         this.context = context;
 422         this.setIsScope();
 423     }
 424 
 425     /**
 426      * Script access to "current" Global instance
 427      *
 428      * @return the global singleton
 429      */
 430     public static Global instance() {
 431         ScriptObject global = Context.getGlobal();
 432         if (! (global instanceof Global)) {
 433             throw new IllegalStateException("no current global instance");
 434         }
 435         return (Global)global;
 436     }
 437 
 438     /**
 439      * Script access to {@link ScriptEnvironment}
 440      *
 441      * @return the script environment
 442      */
 443     static ScriptEnvironment getEnv() {
 444         return instance().getContext().getEnv();
 445     }
 446 
 447     /**
 448      * Script access to {@link Context}
 449      *
 450      * @return the context
 451      */
 452     static Context getThisContext() {
 453         return instance().getContext();
 454     }
 455 
 456     // GlobalObject interface implementation
 457 
 458     @Override
 459     public boolean isOfContext(final Context ctxt) {
 460         return this.context == ctxt;
 461     }
 462 
 463     @Override
 464     public boolean isStrictContext() {
 465         return context.getEnv()._strict;
 466     }
 467 
 468     @Override
 469     public void initBuiltinObjects() {
 470         if (this.builtinObject != null) {
 471             // already initialized, just return
 472             return;
 473         }
 474 
 475         init();
 476     }
 477 
 478     @Override
 479     public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
 480         return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
 481     }
 482 
 483     @Override
 484     public Object wrapAsObject(final Object obj) {
 485         if (obj instanceof Boolean) {
 486             return new NativeBoolean((Boolean)obj, this);
 487         } else if (obj instanceof Number) {
 488             return new NativeNumber(((Number)obj).doubleValue(), this);
 489         } else if (obj instanceof String || obj instanceof ConsString) {
 490             return new NativeString((CharSequence)obj, this);
 491         } else if (obj instanceof Object[]) { // extension
 492             return new NativeArray((Object[])obj);
 493         } else if (obj instanceof double[]) { // extension
 494             return new NativeArray((double[])obj);
 495         } else if (obj instanceof long[]) {
 496             return new NativeArray((long[])obj);
 497         } else if (obj instanceof int[]) {
 498             return new NativeArray((int[])obj);
 499         } else {
 500             // FIXME: more special cases? Map? List?
 501             return obj;
 502         }
 503     }
 504 
 505     @Override
 506     public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
 507         if (self instanceof String || self instanceof ConsString) {
 508             return NativeString.lookupPrimitive(request, self);
 509         } else if (self instanceof Number) {
 510             return NativeNumber.lookupPrimitive(request, self);
 511         } else if (self instanceof Boolean) {
 512             return NativeBoolean.lookupPrimitive(request, self);
 513         }
 514         throw new IllegalArgumentException("Unsupported primitive: " + self);
 515     }
 516 
 517     @Override
 518     public ScriptObject newObject() {
 519         return new JO(getObjectPrototype(), JO.getInitialMap());
 520     }
 521 
 522     @Override
 523     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
 524         // When the [[DefaultValue]] internal method of O is called with no hint,
 525         // then it behaves as if the hint were Number, unless O is a Date object
 526         // in which case it behaves as if the hint were String.
 527         Class<?> hint = typeHint;
 528         if (hint == null) {
 529             hint = Number.class;
 530         }
 531 
 532         try {
 533             if (hint == String.class) {
 534 
 535                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 536 
 537                 if (Bootstrap.isCallable(toString)) {
 538                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 539                     if (JSType.isPrimitive(value)) {
 540                         return value;
 541                     }
 542                 }
 543 
 544                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 545                 if (Bootstrap.isCallable(valueOf)) {
 546                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 547                     if (JSType.isPrimitive(value)) {
 548                         return value;
 549                     }
 550                 }
 551                 throw typeError(this, "cannot.get.default.string");
 552             }
 553 
 554             if (hint == Number.class) {
 555                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 556                 if (Bootstrap.isCallable(valueOf)) {
 557                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 558                     if (JSType.isPrimitive(value)) {
 559                         return value;
 560                     }
 561                 }
 562 
 563                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 564                 if (Bootstrap.isCallable(toString)) {
 565                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 566                     if (JSType.isPrimitive(value)) {
 567                         return value;
 568                     }
 569                 }
 570 
 571                 throw typeError(this, "cannot.get.default.number");
 572             }
 573         } catch (final RuntimeException | Error e) {
 574             throw e;
 575         } catch (final Throwable t) {
 576             throw new RuntimeException(t);
 577         }
 578 
 579         return UNDEFINED;
 580     }
 581 
 582     @Override
 583     public boolean isError(final ScriptObject sobj) {
 584         final ScriptObject errorProto = getErrorPrototype();
 585         ScriptObject proto = sobj.getProto();
 586         while (proto != null) {
 587             if (proto == errorProto) {
 588                 return true;
 589             }
 590             proto = proto.getProto();
 591         }
 592         return false;
 593     }
 594 
 595     @Override
 596     public ScriptObject newError(final String msg) {
 597         return new NativeError(msg, this);
 598     }
 599 
 600     @Override
 601     public ScriptObject newEvalError(final String msg) {
 602         return new NativeEvalError(msg, this);
 603     }
 604 
 605     @Override
 606     public ScriptObject newRangeError(final String msg) {
 607         return new NativeRangeError(msg, this);
 608     }
 609 
 610     @Override
 611     public ScriptObject newReferenceError(final String msg) {
 612         return new NativeReferenceError(msg, this);
 613     }
 614 
 615     @Override
 616     public ScriptObject newSyntaxError(final String msg) {
 617         return new NativeSyntaxError(msg, this);
 618     }
 619 
 620     @Override
 621     public ScriptObject newTypeError(final String msg) {
 622         return new NativeTypeError(msg, this);
 623     }
 624 
 625     @Override
 626     public ScriptObject newURIError(final String msg) {
 627         return new NativeURIError(msg, this);
 628     }
 629 
 630     @Override
 631     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
 632         return new GenericPropertyDescriptor(configurable, enumerable, this);
 633     }
 634 
 635     @Override
 636     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
 637         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
 638     }
 639 
 640     @Override
 641     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
 642         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
 643 
 644         if (get == null) {
 645             desc.delete(PropertyDescriptor.GET, false);
 646         }
 647 
 648         if (set == null) {
 649             desc.delete(PropertyDescriptor.SET, false);
 650         }
 651 
 652         return desc;
 653     }
 654 
 655 
 656     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
 657         final T obj = map.get(key);
 658         if (obj != null) {
 659             return obj;
 660         }
 661 
 662         try {
 663             final T newObj = creator.call();
 664             final T existingObj = map.putIfAbsent(key, newObj);
 665             return existingObj != null ? existingObj : newObj;
 666         } catch (final Exception exp) {
 667             throw new RuntimeException(exp);
 668         }
 669     }
 670 
 671     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
 672 
 673     @Override
 674     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
 675         return getLazilyCreatedValue(key, creator, namedInvokers);
 676     }
 677 
 678     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
 679 
 680     @Override
 681     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
 682         return getLazilyCreatedValue(key, creator, dynamicInvokers);
 683     }
 684 
 685     /**
 686      * This is the eval used when 'indirect' eval call is made.
 687      *
 688      * var global = this;
 689      * global.eval("print('hello')");
 690      *
 691      * @param self  eval scope
 692      * @param str   eval string
 693      *
 694      * @return the result of eval
 695      */
 696     public static Object eval(final Object self, final Object str) {
 697         return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
 698     }
 699 
 700     /**
 701      * Direct eval
 702      *
 703      * @param self     The scope of eval passed as 'self'
 704      * @param str      Evaluated code
 705      * @param callThis "this" to be passed to the evaluated code
 706      * @param location location of the eval call
 707      * @param strict   is eval called a strict mode code?
 708      *
 709      * @return the return value of the eval
 710      *
 711      * This is directly invoked from generated when eval(code) is called in user code
 712      */
 713     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
 714         if (!(str instanceof String || str instanceof ConsString)) {
 715             return str;
 716         }
 717         final Global global = Global.instance();
 718         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
 719 
 720         return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
 721     }
 722 
 723     /**
 724      * Global print implementation - Nashorn extension
 725      *
 726      * @param self    scope
 727      * @param objects arguments to print
 728      *
 729      * @return result of print (undefined)
 730      */
 731     public static Object print(final Object self, final Object... objects) {
 732         return printImpl(false, objects);
 733     }
 734 
 735     /**
 736      * Global println implementation - Nashorn extension
 737      *
 738      * @param self    scope
 739      * @param objects arguments to print
 740      *
 741      * @return result of println (undefined)
 742      */
 743     public static Object println(final Object self, final Object... objects) {
 744         return printImpl(true, objects);
 745     }
 746 
 747     /**
 748      * Global load implementation - Nashorn extension
 749      *
 750      * @param self    scope
 751      * @param source  source to load
 752      *
 753      * @return result of load (undefined)
 754      *
 755      * @throws IOException if source could not be read
 756      */
 757     public static Object load(final Object self, final Object source) throws IOException {
 758         final Global global = Global.instance();
 759         final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
 760         return global.getContext().load(scope, source);
 761     }
 762 
 763     /**
 764      * Global loadWithNewGlobal implementation - Nashorn extension
 765      *
 766      * @param self scope
 767      * @param args from plus (optional) arguments to be passed to the loaded script
 768      *
 769      * @return result of load (may be undefined)
 770      *
 771      * @throws IOException if source could not be read
 772      */
 773     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
 774         final Global global = Global.instance();
 775         final int length = args.length;
 776         final boolean hasArgs = 0 < length;
 777         final Object from = hasArgs ? args[0] : UNDEFINED;
 778         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
 779 
 780         return global.getContext().loadWithNewGlobal(from, arguments);
 781     }
 782 
 783     /**
 784      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
 785      *
 786      * @param self  self reference
 787      * @param code  exit code
 788      *
 789      * @return undefined (will never be reacheD)
 790      */
 791     public static Object exit(final Object self, final Object code) {
 792         System.exit(JSType.toInt32(code));
 793         return UNDEFINED;
 794     }
 795 
 796     // builtin prototype accessors
 797     ScriptObject getFunctionPrototype() {
 798         return ScriptFunction.getPrototype(builtinFunction);
 799     }
 800 
 801     ScriptObject getObjectPrototype() {
 802         return ScriptFunction.getPrototype(builtinObject);
 803     }
 804 
 805     ScriptObject getArrayPrototype() {
 806         return ScriptFunction.getPrototype(builtinArray);
 807     }
 808 
 809     ScriptObject getBooleanPrototype() {
 810         return ScriptFunction.getPrototype(builtinBoolean);
 811     }
 812 
 813     ScriptObject getNumberPrototype() {
 814         return ScriptFunction.getPrototype(builtinNumber);
 815     }
 816 
 817     ScriptObject getDatePrototype() {
 818         return ScriptFunction.getPrototype(builtinDate);
 819     }
 820 
 821     ScriptObject getRegExpPrototype() {
 822         return ScriptFunction.getPrototype(builtinRegExp);
 823     }
 824 
 825     ScriptObject getStringPrototype() {
 826         return ScriptFunction.getPrototype(builtinString);
 827     }
 828 
 829     ScriptObject getErrorPrototype() {
 830         return ScriptFunction.getPrototype(builtinError);
 831     }
 832 
 833     ScriptObject getEvalErrorPrototype() {
 834         return ScriptFunction.getPrototype(builtinEvalError);
 835     }
 836 
 837     ScriptObject getRangeErrorPrototype() {
 838         return ScriptFunction.getPrototype(builtinRangeError);
 839     }
 840 
 841     ScriptObject getReferenceErrorPrototype() {
 842         return ScriptFunction.getPrototype(builtinReferenceError);
 843     }
 844 
 845     ScriptObject getSyntaxErrorPrototype() {
 846         return ScriptFunction.getPrototype(builtinSyntaxError);
 847     }
 848 
 849     ScriptObject getTypeErrorPrototype() {
 850         return ScriptFunction.getPrototype(builtinTypeError);
 851     }
 852 
 853     ScriptObject getURIErrorPrototype() {
 854         return ScriptFunction.getPrototype(builtinURIError);
 855     }
 856 
 857     ScriptObject getJavaImporterPrototype() {
 858         return ScriptFunction.getPrototype(builtinJavaImporter);
 859     }
 860 
 861     ScriptObject getJSAdapterPrototype() {
 862         return ScriptFunction.getPrototype(builtinJSAdapter);
 863     }
 864 
 865     ScriptObject getArrayBufferPrototype() {
 866         return ScriptFunction.getPrototype(builtinArrayBuffer);
 867     }
 868 




 869     ScriptObject getInt8ArrayPrototype() {
 870         return ScriptFunction.getPrototype(builtinInt8Array);
 871     }
 872 
 873     ScriptObject getUint8ArrayPrototype() {
 874         return ScriptFunction.getPrototype(builtinUint8Array);
 875     }
 876 
 877     ScriptObject getUint8ClampedArrayPrototype() {
 878         return ScriptFunction.getPrototype(builtinUint8ClampedArray);
 879     }
 880 
 881     ScriptObject getInt16ArrayPrototype() {
 882         return ScriptFunction.getPrototype(builtinInt16Array);
 883     }
 884 
 885     ScriptObject getUint16ArrayPrototype() {
 886         return ScriptFunction.getPrototype(builtinUint16Array);
 887     }
 888 
 889     ScriptObject getInt32ArrayPrototype() {
 890         return ScriptFunction.getPrototype(builtinInt32Array);
 891     }
 892 
 893     ScriptObject getUint32ArrayPrototype() {
 894         return ScriptFunction.getPrototype(builtinUint32Array);
 895     }
 896 
 897     ScriptObject getFloat32ArrayPrototype() {
 898         return ScriptFunction.getPrototype(builtinFloat32Array);
 899     }
 900 
 901     ScriptObject getFloat64ArrayPrototype() {
 902         return ScriptFunction.getPrototype(builtinFloat64Array);
 903     }
 904 
 905     private ScriptFunction getBuiltinArray() {
 906         return builtinArray;
 907     }
 908 
 909     ScriptFunction getTypeErrorThrower() {
 910         return typeErrorThrower;
 911     }
 912 
 913     /**
 914      * Called from compiled script code to test if builtin has been overridden
 915      *
 916      * @return true if builtin array has not been overridden
 917      */
 918     public static boolean isBuiltinArray() {
 919         final Global instance = Global.instance();
 920         return instance.array == instance.getBuiltinArray();
 921     }
 922 
 923     private ScriptFunction getBuiltinBoolean() {
 924         return builtinBoolean;
 925     }
 926 
 927     /**
 928      * Called from compiled script code to test if builtin has been overridden
 929      *
 930      * @return true if builtin boolean has not been overridden
 931      */
 932     public static boolean isBuiltinBoolean() {
 933         final Global instance = Global.instance();
 934         return instance._boolean == instance.getBuiltinBoolean();
 935     }
 936 
 937     private ScriptFunction getBuiltinDate() {
 938         return builtinDate;
 939     }
 940 
 941     /**
 942      * Called from compiled script code to test if builtin has been overridden
 943      *
 944      * @return true if builtin date has not been overridden
 945      */
 946     public static boolean isBuiltinDate() {
 947         final Global instance = Global.instance();
 948         return instance.date == instance.getBuiltinDate();
 949     }
 950 
 951     private ScriptFunction getBuiltinError() {
 952         return builtinError;
 953     }
 954 
 955     /**
 956      * Called from compiled script code to test if builtin has been overridden
 957      *
 958      * @return true if builtin error has not been overridden
 959      */
 960     public static boolean isBuiltinError() {
 961         final Global instance = Global.instance();
 962         return instance.error == instance.getBuiltinError();
 963     }
 964 
 965     private ScriptFunction getBuiltinEvalError() {
 966         return builtinEvalError;
 967     }
 968 
 969     /**
 970      * Called from compiled script code to test if builtin has been overridden
 971      *
 972      * @return true if builtin eval error has not been overridden
 973      */
 974     public static boolean isBuiltinEvalError() {
 975         final Global instance = Global.instance();
 976         return instance.evalError == instance.getBuiltinEvalError();
 977     }
 978 
 979     private ScriptFunction getBuiltinFunction() {
 980         return builtinFunction;
 981     }
 982 
 983     /**
 984      * Called from compiled script code to test if builtin has been overridden
 985      *
 986      * @return true if builtin function has not been overridden
 987      */
 988     public static boolean isBuiltinFunction() {
 989         final Global instance = Global.instance();
 990         return instance.function == instance.getBuiltinFunction();
 991     }
 992 
 993     private ScriptFunction getBuiltinJSAdapter() {
 994         return builtinJSAdapter;
 995     }
 996 
 997     /**
 998      * Called from compiled script code to test if builtin has been overridden
 999      *
1000      * @return true if builtin JSAdapter has not been overridden
1001      */
1002     public static boolean isBuiltinJSAdapter() {
1003         final Global instance = Global.instance();
1004         return instance.jsadapter == instance.getBuiltinJSAdapter();
1005     }
1006 
1007     private ScriptObject getBuiltinJSON() {
1008         return builtinJSON;
1009     }
1010 
1011     /**
1012      * Called from compiled script code to test if builtin has been overridden
1013      *
1014      * @return true if builtin JSON has has not been overridden
1015      */
1016     public static boolean isBuiltinJSON() {
1017         final Global instance = Global.instance();
1018         return instance.json == instance.getBuiltinJSON();
1019     }
1020 
1021     private ScriptObject getBuiltinJava() {
1022         return builtinJava;
1023     }
1024 
1025     /**
1026      * Called from compiled script code to test if builtin has been overridden
1027      *
1028      * @return true if builtin Java has not been overridden
1029      */
1030     public static boolean isBuiltinJava() {
1031         final Global instance = Global.instance();
1032         return instance.java == instance.getBuiltinJava();
1033     }
1034 
1035     private ScriptObject getBuiltinJavax() {
1036         return builtinJavax;
1037     }
1038 
1039     /**
1040      * Called from compiled script code to test if builtin has been overridden
1041      *
1042      * @return true if builtin Javax has not been overridden
1043      */
1044     public static boolean isBuiltinJavax() {
1045         final Global instance = Global.instance();
1046         return instance.javax == instance.getBuiltinJavax();
1047     }
1048 
1049     private ScriptObject getBuiltinJavaImporter() {
1050         return builtinJavaImporter;
1051     }
1052 
1053     /**
1054      * Called from compiled script code to test if builtin has been overridden
1055      *
1056      * @return true if builtin Java importer has not been overridden
1057      */
1058     public static boolean isBuiltinJavaImporter() {
1059         final Global instance = Global.instance();
1060         return instance.javaImporter == instance.getBuiltinJavaImporter();
1061     }
1062 
1063     private ScriptObject getBuiltinMath() {
1064         return builtinMath;
1065     }
1066 
1067     /**
1068      * Called from compiled script code to test if builtin has been overridden
1069      *
1070      * @return true if builtin math has not been overridden
1071      */
1072     public static boolean isBuiltinMath() {
1073         final Global instance = Global.instance();
1074         return instance.math == instance.getBuiltinMath();
1075     }
1076 
1077     private ScriptFunction getBuiltinNumber() {
1078         return builtinNumber;
1079     }
1080 
1081     /**
1082      * Called from compiled script code to test if builtin has been overridden
1083      *
1084      * @return true if builtin number has not been overridden
1085      */
1086     public static boolean isBuiltinNumber() {
1087         final Global instance = Global.instance();
1088         return instance.number == instance.getBuiltinNumber();
1089     }
1090 
1091     private ScriptFunction getBuiltinObject() {
1092         return builtinObject;
1093     }
1094 
1095     /**
1096      * Called from compiled script code to test if builtin has been overridden
1097      *
1098      * @return true if builtin object has not been overridden
1099      */
1100     public static boolean isBuiltinObject() {
1101         final Global instance = Global.instance();
1102         return instance.object == instance.getBuiltinObject();
1103     }
1104 
1105     private ScriptObject getBuiltinPackages() {
1106         return builtinPackages;
1107     }
1108 
1109     /**
1110      * Called from compiled script code to test if builtin has been overridden
1111      *
1112      * @return true if builtin package has not been overridden
1113      */
1114     public static boolean isBuiltinPackages() {
1115         final Global instance = Global.instance();
1116         return instance.packages == instance.getBuiltinPackages();
1117     }
1118 
1119     private ScriptFunction getBuiltinRangeError() {
1120         return builtinRangeError;
1121     }
1122 
1123     /**
1124      * Called from compiled script code to test if builtin has been overridden
1125      *
1126      * @return true if builtin range error has not been overridden
1127      */
1128     public static boolean isBuiltinRangeError() {
1129         final Global instance = Global.instance();
1130         return instance.rangeError == instance.getBuiltinRangeError();
1131     }
1132 
1133     private ScriptFunction getBuiltinReferenceError() {
1134         return builtinReferenceError;
1135     }
1136 
1137     /**
1138      * Called from compiled script code to test if builtin has been overridden
1139      *
1140      * @return true if builtin reference error has not been overridden
1141      */
1142     public static boolean isBuiltinReferenceError() {
1143         final Global instance = Global.instance();
1144         return instance.referenceError == instance.getBuiltinReferenceError();
1145     }
1146 
1147     private ScriptFunction getBuiltinRegExp() {
1148         return builtinRegExp;
1149     }
1150 
1151     /**
1152      * Called from compiled script code to test if builtin has been overridden
1153      *
1154      * @return true if builtin regexp has not been overridden
1155      */
1156     public static boolean isBuiltinRegExp() {
1157         final Global instance = Global.instance();
1158         return instance.regexp == instance.getBuiltinRegExp();
1159     }
1160 
1161     private ScriptFunction getBuiltinString() {
1162         return builtinString;
1163     }
1164 
1165     /**
1166      * Called from compiled script code to test if builtin has been overridden
1167      *
1168      * @return true if builtin Java has not been overridden
1169      */
1170     public static boolean isBuiltinString() {
1171         final Global instance = Global.instance();
1172         return instance.string == instance.getBuiltinString();
1173     }
1174 
1175     private ScriptFunction getBuiltinSyntaxError() {
1176         return builtinSyntaxError;
1177     }
1178 
1179     /**
1180      * Called from compiled script code to test if builtin has been overridden
1181      *
1182      * @return true if builtin syntax error has not been overridden
1183      */
1184     public static boolean isBuiltinSyntaxError() {
1185         final Global instance = Global.instance();
1186         return instance.syntaxError == instance.getBuiltinSyntaxError();
1187     }
1188 
1189     private ScriptFunction getBuiltinTypeError() {
1190         return builtinTypeError;
1191     }
1192 
1193     /**
1194      * Called from compiled script code to test if builtin has been overridden
1195      *
1196      * @return true if builtin type error has not been overridden
1197      */
1198     public static boolean isBuiltinTypeError() {
1199         final Global instance = Global.instance();
1200         return instance.typeError == instance.getBuiltinTypeError();
1201     }
1202 
1203     private ScriptFunction getBuiltinURIError() {
1204         return builtinURIError;
1205     }
1206 
1207     /**
1208      * Called from compiled script code to test if builtin has been overridden
1209      *
1210      * @return true if builtin URI error has not been overridden
1211      */
1212     public static boolean isBuiltinURIError() {
1213         final Global instance = Global.instance();
1214         return instance.uriError == instance.getBuiltinURIError();
1215     }
1216 
1217     @Override
1218     public String getClassName() {
1219         return "global";
1220     }
1221 
1222     /**
1223      * Copy function used to clone NativeRegExp objects.
1224      *
1225      * @param regexp a NativeRegExp to clone
1226      *
1227      * @return copy of the given regexp object
1228      */
1229     public static Object regExpCopy(final Object regexp) {
1230         return new NativeRegExp((NativeRegExp)regexp);
1231     }
1232 
1233     /**
1234      * Convert given object to NativeRegExp type.
1235      *
1236      * @param obj object to be converted
1237      * @return NativeRegExp instance
1238      */
1239     public static NativeRegExp toRegExp(final Object obj) {
1240         if (obj instanceof NativeRegExp) {
1241             return (NativeRegExp)obj;
1242         }
1243         return new NativeRegExp(JSType.toString(obj));
1244     }
1245 
1246     /**
1247      * ECMA 9.9 ToObject implementation
1248      *
1249      * @param obj  an item for which to run ToObject
1250      * @return ToObject version of given item
1251      */
1252     public static Object toObject(final Object obj) {
1253         if (obj == null || obj == UNDEFINED) {
1254             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1255         }
1256 
1257         if (obj instanceof ScriptObject) {
1258             return obj;
1259         }
1260 
1261         return instance().wrapAsObject(obj);
1262     }
1263 
1264     /**
1265      * Allocate a new object array.
1266      *
1267      * @param initial object values.
1268      * @return the new array
1269      */
1270     public static NativeArray allocate(final Object[] initial) {
1271         ArrayData arrayData = ArrayData.allocate(initial);
1272 
1273         for (int index = 0; index < initial.length; index++) {
1274             final Object value = initial[index];
1275 
1276             if (value == ScriptRuntime.EMPTY) {
1277                 arrayData = arrayData.delete(index);
1278             }
1279         }
1280 
1281         return new NativeArray(arrayData);
1282     }
1283 
1284     /**
1285      * Allocate a new number array.
1286      *
1287      * @param initial number values.
1288      * @return the new array
1289      */
1290     public static NativeArray allocate(final double[] initial) {
1291         return new NativeArray(ArrayData.allocate(initial));
1292     }
1293 
1294     /**
1295      * Allocate a new long array.
1296      *
1297      * @param initial number values.
1298      * @return the new array
1299      */
1300     public static NativeArray allocate(final long[] initial) {
1301         return new NativeArray(ArrayData.allocate(initial));
1302     }
1303 
1304     /**
1305      * Allocate a new integer array.
1306      *
1307      * @param initial number values.
1308      * @return the new array
1309      */
1310     public static NativeArray allocate(final int[] initial) {
1311         return new NativeArray(ArrayData.allocate(initial));
1312     }
1313 
1314     /**
1315      * Allocate a new object array for arguments.
1316      *
1317      * @param arguments initial arguments passed.
1318      * @param callee reference to the function that uses arguments object
1319      * @param numParams actual number of declared parameters
1320      *
1321      * @return the new array
1322      */
1323     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
1324         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
1325     }
1326 
1327     /**
1328      * Called from generated to check if given function is the builtin 'eval'. If
1329      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
1330      *
1331      * @param  fn function object that is checked
1332      * @return true if fn is the builtin eval
1333      */
1334     public static boolean isEval(final Object fn) {
1335         return fn == Global.instance().builtinEval;
1336     }
1337 
1338     /**
1339      * Create a new RegExp object.
1340      *
1341      * @param expression Regular expression.
1342      * @param options    Search options.
1343      *
1344      * @return New RegExp object.
1345      */
1346     public static Object newRegExp(final String expression, final String options) {
1347         if (options == null) {
1348             return new NativeRegExp(expression);
1349         }
1350         return new NativeRegExp(expression, options);
1351     }
1352 
1353     /**
1354      * Get the object prototype
1355      *
1356      * @return the object prototype
1357      */
1358     public static ScriptObject objectPrototype() {
1359         return Global.instance().getObjectPrototype();
1360     }
1361 
1362     /**
1363      * Create a new empty object instance.
1364      *
1365      * @return New empty object.
1366      */
1367     public static ScriptObject newEmptyInstance() {
1368         return Global.instance().newObject();
1369     }
1370 
1371     /**
1372      * Check if a given object is a ScriptObject, raises an exception if this is
1373      * not the case
1374      *
1375      * @param obj and object to check
1376      */
1377     public static void checkObject(final Object obj) {
1378         if (!(obj instanceof ScriptObject)) {
1379             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1380         }
1381     }
1382 
1383     /**
1384      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
1385      * if this object is null or undefined.
1386      *
1387      * @param obj an object to check
1388      */
1389     public static void checkObjectCoercible(final Object obj) {
1390         if (obj == null || obj == UNDEFINED) {
1391             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1392         }
1393     }
1394 
1395     /**
1396      * Get the current split state.
1397      *
1398      * @return current split state
1399      */
1400     @Override
1401     public int getSplitState() {
1402         return splitState;
1403     }
1404 
1405     /**
1406      * Set the current split state.
1407      *
1408      * @param state current split state
1409      */
1410     @Override
1411     public void setSplitState(final int state) {
1412         splitState = state;
1413     }
1414 
1415     private void init() {
1416         assert Context.getGlobal() == this : "this global is not set as current";
1417 
1418         final ScriptEnvironment env = getContext().getEnv();
1419 
1420         // initialize Function and Object constructor
1421         initFunctionAndObject();
1422 
1423         // Now fix Global's own proto.
1424         this.setInitialProto(getObjectPrototype());
1425 
1426         // initialize global function properties
1427         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
1428 
1429         this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
1430         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
1431         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
1432         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
1433         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
1434         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
1435         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
1436         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
1437         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
1438         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
1439         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
1440         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
1441         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
1442         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
1443         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
1444 
1445         // built-in constructors
1446         this.builtinArray     = (ScriptFunction)initConstructor("Array");
1447         this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
1448         this.builtinDate      = (ScriptFunction)initConstructor("Date");
1449         this.builtinJSON      = initConstructor("JSON");
1450         this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
1451         this.builtinMath      = initConstructor("Math");
1452         this.builtinNumber    = (ScriptFunction)initConstructor("Number");
1453         this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
1454         this.builtinString    = (ScriptFunction)initConstructor("String");
1455 
1456         // initialize String.prototype.length to 0
1457         // add String.prototype.length
1458         final ScriptObject stringPrototype = getStringPrototype();
1459         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
1460 
1461         // set isArray flag on Array.prototype
1462         final ScriptObject arrayPrototype = getArrayPrototype();
1463         arrayPrototype.setIsArray();
1464 
1465         this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
1466 
1467         // initialize default regexp object
1468         this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
1469 
1470         // RegExp.prototype should behave like a RegExp object. So copy the
1471         // properties.
1472         final ScriptObject regExpProto = getRegExpPrototype();
1473         regExpProto.addBoundProperties(DEFAULT_REGEXP);
1474 
1475         // Error stuff
1476         initErrorObjects();
1477 
1478         // java access
1479         if (! env._no_java) {
1480             initJavaAccess();
1481         }
1482 
1483         if (! env._no_typed_arrays) {
1484             initTypedArray();
1485         }
1486 
1487         if (env._scripting) {
1488             initScripting(env);
1489         }
1490 
1491         if (Context.DEBUG) {
1492             boolean debugOkay;
1493             final SecurityManager sm = System.getSecurityManager();
1494             if (sm != null) {
1495                 try {
1496                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
1497                     debugOkay = true;
1498                 } catch (final SecurityException ignored) {
1499                     // if no permission, don't initialize Debug object
1500                     debugOkay = false;
1501                 }
1502 
1503             } else {
1504                 debugOkay = true;
1505             }
1506 
1507             if (debugOkay) {
1508                 initDebug();
1509             }
1510         }
1511 
1512         copyBuiltins();
1513 
1514         // initialized with strings so that typeof will work as expected.
1515         this.__FILE__ = "";
1516         this.__DIR__  = "";
1517         this.__LINE__ = 0.0;
1518 
1519         // expose script (command line) arguments as "arguments" property of global
1520         final List<String> arguments = env.getArguments();
1521         final Object argsObj = wrapAsObject(arguments.toArray());
1522 
1523         addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
1524         if (env._scripting) {
1525             // synonym for "arguments" in scripting mode
1526             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
1527         }
1528     }
1529 
1530     private void initErrorObjects() {
1531         // Error objects
1532         this.builtinError = (ScriptFunction)initConstructor("Error");
1533         final ScriptObject errorProto = getErrorPrototype();
1534 
1535         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
1536         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
1537         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
1538         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
1539         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
1540         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
1541         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
1542         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
1543         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
1544         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
1545         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
1546         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
1547         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
1548 
1549         // ECMA 15.11.4.2 Error.prototype.name
1550         // Error.prototype.name = "Error";
1551         errorProto.set(NativeError.NAME, "Error", false);
1552         // ECMA 15.11.4.3 Error.prototype.message
1553         // Error.prototype.message = "";
1554         errorProto.set(NativeError.MESSAGE, "", false);
1555 
1556         this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
1557         this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
1558         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
1559         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
1560         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
1561         this.builtinURIError = initErrorSubtype("URIError", errorProto);
1562     }
1563 
1564     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
1565         final ScriptObject cons = initConstructor(name);
1566         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
1567         prototype.set(NativeError.NAME, name, false);
1568         prototype.set(NativeError.MESSAGE, "", false);
1569         prototype.setInitialProto(errorProto);
1570         return (ScriptFunction)cons;
1571     }
1572 
1573     private void initJavaAccess() {
1574         final ScriptObject objectProto = getObjectPrototype();
1575         this.builtinPackages = new NativeJavaPackage("", objectProto);
1576         this.builtinCom = new NativeJavaPackage("com", objectProto);
1577         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
1578         this.builtinJava = new NativeJavaPackage("java", objectProto);
1579         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
1580         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
1581         this.builtinOrg = new NativeJavaPackage("org", objectProto);
1582         this.builtinJavaImporter = initConstructor("JavaImporter");
1583         this.builtinJavaApi = initConstructor("Java");
1584     }
1585 
1586     private void initScripting(final ScriptEnvironment scriptEnv) {
1587         Object value;
1588         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
1589         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
1590 
1591         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
1592         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
1593 
1594         final String execName = ScriptingFunctions.EXEC_NAME;
1595         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
1596         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
1597 
1598         // Nashorn extension: global.echo (scripting-mode-only)
1599         // alias for "print"
1600         value = get("print");
1601         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
1602 
1603         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
1604         final ScriptObject options = newObject();
1605         copyOptions(options, scriptEnv);
1606         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
1607 
1608         // Nashorn extension: global.$ENV (scripting-mode-only)
1609         if (System.getSecurityManager() == null) {
1610             // do not fill $ENV if we have a security manager around
1611             // Retrieve current state of ENV variables.
1612             final ScriptObject env = newObject();
1613             env.putAll(System.getenv(), scriptEnv._strict);
1614             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
1615         } else {
1616             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1617         }
1618 
1619         // add other special properties for exec support
1620         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1621         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1622         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
1623     }
1624 
1625     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
1626         for (Field f : scriptEnv.getClass().getFields()) {
1627             try {
1628                 options.set(f.getName(), f.get(scriptEnv), false);
1629             } catch (final IllegalArgumentException | IllegalAccessException exp) {
1630                 throw new RuntimeException(exp);
1631             }
1632         }
1633     }
1634 
1635     private void initTypedArray() {
1636         this.builtinArrayBuffer       = initConstructor("ArrayBuffer");

1637         this.builtinInt8Array         = initConstructor("Int8Array");
1638         this.builtinUint8Array        = initConstructor("Uint8Array");
1639         this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
1640         this.builtinInt16Array        = initConstructor("Int16Array");
1641         this.builtinUint16Array       = initConstructor("Uint16Array");
1642         this.builtinInt32Array        = initConstructor("Int32Array");
1643         this.builtinUint32Array       = initConstructor("Uint32Array");
1644         this.builtinFloat32Array      = initConstructor("Float32Array");
1645         this.builtinFloat64Array      = initConstructor("Float64Array");
1646     }
1647 
1648     private void copyBuiltins() {
1649         this.array             = this.builtinArray;
1650         this._boolean          = this.builtinBoolean;
1651         this.date              = this.builtinDate;
1652         this.error             = this.builtinError;
1653         this.evalError         = this.builtinEvalError;
1654         this.function          = this.builtinFunction;
1655         this.jsadapter         = this.builtinJSAdapter;
1656         this.json              = this.builtinJSON;
1657         this.com               = this.builtinCom;
1658         this.edu               = this.builtinEdu;
1659         this.java              = this.builtinJava;
1660         this.javafx            = this.builtinJavafx;
1661         this.javax             = this.builtinJavax;
1662         this.org               = this.builtinOrg;
1663         this.javaImporter      = this.builtinJavaImporter;
1664         this.javaApi           = this.builtinJavaApi;
1665         this.math              = this.builtinMath;
1666         this.number            = this.builtinNumber;
1667         this.object            = this.builtinObject;
1668         this.packages          = this.builtinPackages;
1669         this.rangeError        = this.builtinRangeError;
1670         this.referenceError    = this.builtinReferenceError;
1671         this.regexp            = this.builtinRegExp;
1672         this.string            = this.builtinString;
1673         this.syntaxError       = this.builtinSyntaxError;
1674         this.typeError         = this.builtinTypeError;
1675         this.uriError          = this.builtinURIError;
1676         this.arrayBuffer       = this.builtinArrayBuffer;

1677         this.int8Array         = this.builtinInt8Array;
1678         this.uint8Array        = this.builtinUint8Array;
1679         this.uint8ClampedArray = this.builtinUint8ClampedArray;
1680         this.int16Array        = this.builtinInt16Array;
1681         this.uint16Array       = this.builtinUint16Array;
1682         this.int32Array        = this.builtinInt32Array;
1683         this.uint32Array       = this.builtinUint32Array;
1684         this.float32Array      = this.builtinFloat32Array;
1685         this.float64Array      = this.builtinFloat64Array;
1686     }
1687 
1688     private void initDebug() {
1689         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
1690     }
1691 
1692     @SuppressWarnings("resource")
1693     private static Object printImpl(final boolean newLine, final Object... objects) {
1694         final PrintWriter out = Global.getEnv().getOut();
1695         final StringBuilder sb = new StringBuilder();
1696 
1697         for (final Object object : objects) {
1698             if (sb.length() != 0) {
1699                 sb.append(' ');
1700             }
1701 
1702             sb.append(JSType.toString(object));
1703         }
1704 
1705         // Print all at once to ensure thread friendly result.
1706         if (newLine) {
1707             out.println(sb.toString());
1708         } else {
1709             out.print(sb.toString());
1710         }
1711 
1712         out.flush();
1713 
1714         return UNDEFINED;
1715     }
1716 
1717     /**
1718      * These classes are generated by nasgen tool and so we have to use
1719      * reflection to load and create new instance of these classes.
1720      */
1721     private ScriptObject initConstructor(final String name) {
1722         try {
1723             // Assuming class name pattern for built-in JS constructors.
1724             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
1725 
1726             sb.append("Native");
1727             sb.append(name);
1728             sb.append("$Constructor");
1729 
1730             final Class<?>     funcClass = Class.forName(sb.toString());
1731             final ScriptObject res       = (ScriptObject)funcClass.newInstance();
1732 
1733             if (res instanceof ScriptFunction) {
1734                 // All global constructor prototypes are not-writable,
1735                 // not-enumerable and not-configurable.
1736                 final ScriptFunction func = (ScriptFunction)res;
1737                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
1738             }
1739 
1740             if (res.getProto() == null) {
1741                 res.setInitialProto(getObjectPrototype());
1742             }
1743 
1744             return res;
1745 
1746         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
1747             throw new RuntimeException(e);
1748         }
1749     }
1750 
1751     // Function and Object constructors are inter-dependent. Also,
1752     // Function.prototype
1753     // functions are not properly initialized. We fix the references here.
1754     // NOTE: be careful if you want to re-order the operations here. You may
1755     // have
1756     // to play with object references carefully!!
1757     private void initFunctionAndObject() {
1758         // First-n-foremost is Function
1759         this.builtinFunction = (ScriptFunction)initConstructor("Function");
1760 
1761         // create global anonymous function
1762         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
1763         // need to copy over members of Function.prototype to anon function
1764         anon.addBoundProperties(getFunctionPrototype());
1765 
1766         // Function.prototype === Object.getPrototypeOf(Function) ===
1767         // <anon-function>
1768         builtinFunction.setInitialProto(anon);
1769         builtinFunction.setPrototype(anon);
1770         anon.set("constructor", builtinFunction, false);
1771         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
1772 
1773         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
1774         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
1775         typeErrorThrower.setPrototype(UNDEFINED);
1776         // Non-constructor built-in functions do not have "prototype" property
1777         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
1778         typeErrorThrower.preventExtensions();
1779 
1780         // now initialize Object
1781         this.builtinObject = (ScriptFunction)initConstructor("Object");
1782         final ScriptObject ObjectPrototype = getObjectPrototype();
1783         // Object.getPrototypeOf(Function.prototype) === Object.prototype
1784         anon.setInitialProto(ObjectPrototype);
1785 
1786         // Function valued properties of Function.prototype were not properly
1787         // initialized. Because, these were created before global.function and
1788         // global.object were not initialized.
1789         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
1790         for (final jdk.nashorn.internal.runtime.Property property : properties) {
1791             final Object key = property.getKey();
1792             final Object value = builtinFunction.get(key);
1793 
1794             if (value instanceof ScriptFunction && value != anon) {
1795                 final ScriptFunction func = (ScriptFunction)value;
1796                 func.setInitialProto(getFunctionPrototype());
1797                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1798                 if (prototype != null) {
1799                     prototype.setInitialProto(ObjectPrototype);
1800                 }
1801             }
1802         }
1803 
1804         // For function valued properties of Object and Object.prototype, make
1805         // sure prototype's proto chain ends with Object.prototype
1806         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
1807             final Object key = property.getKey();
1808             final Object value = builtinObject.get(key);
1809 
1810             if (value instanceof ScriptFunction) {
1811                 final ScriptFunction func = (ScriptFunction)value;
1812                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1813                 if (prototype != null) {
1814                     prototype.setInitialProto(ObjectPrototype);
1815                 }
1816             }
1817         }
1818 
1819         properties = getObjectPrototype().getMap().getProperties();
1820         for (final jdk.nashorn.internal.runtime.Property property : properties) {
1821             final Object key   = property.getKey();
1822             final Object value = ObjectPrototype.get(key);
1823 
1824             if (key.equals("constructor")) {
1825                 continue;
1826             }
1827 
1828             if (value instanceof ScriptFunction) {
1829                 final ScriptFunction func = (ScriptFunction)value;
1830                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
1831                 if (prototype != null) {
1832                     prototype.setInitialProto(ObjectPrototype);
1833                 }
1834             }
1835         }
1836     }
1837 
1838     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
1839         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
1840     }
1841 
1842     RegExpResult getLastRegExpResult() {
1843         return lastRegExpResult;
1844     }
1845 
1846     void setLastRegExpResult(final RegExpResult regExpResult) {
1847         this.lastRegExpResult = regExpResult;
1848     }
1849 
1850 }
--- EOF ---