1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.objects;
  27 
  28 import static jdk.nashorn.internal.lookup.Lookup.MH;
  29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  31 
  32 import java.io.IOException;
  33 import java.io.PrintWriter;
  34 import java.lang.invoke.MethodHandle;
  35 import java.lang.invoke.MethodHandles;
  36 import java.lang.ref.ReferenceQueue;
  37 import java.lang.ref.SoftReference;
  38 import java.lang.reflect.Field;
  39 import java.util.Arrays;
  40 import java.util.LinkedHashMap;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.concurrent.Callable;
  44 import java.util.concurrent.ConcurrentHashMap;
  45 import jdk.internal.dynalink.linker.GuardedInvocation;
  46 import jdk.internal.dynalink.linker.LinkRequest;
  47 import jdk.nashorn.internal.lookup.Lookup;
  48 import jdk.nashorn.internal.objects.annotations.Attribute;
  49 import jdk.nashorn.internal.objects.annotations.Property;
  50 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  51 import jdk.nashorn.internal.runtime.ConsString;
  52 import jdk.nashorn.internal.runtime.Context;
  53 import jdk.nashorn.internal.runtime.GlobalFunctions;
  54 import jdk.nashorn.internal.runtime.GlobalObject;
  55 import jdk.nashorn.internal.runtime.JSType;
  56 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  57 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  58 import jdk.nashorn.internal.runtime.PropertyMap;
  59 import jdk.nashorn.internal.runtime.Scope;
  60 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  61 import jdk.nashorn.internal.runtime.ScriptFunction;

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