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.referenceError;
  30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  31 import static jdk.nashorn.internal.runtime.JSType.isString;
  32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  33 
  34 import java.io.IOException;
  35 import java.io.PrintWriter;
  36 import java.lang.invoke.MethodHandle;
  37 import java.lang.invoke.MethodHandles;
  38 import java.lang.invoke.MethodType;
  39 import java.lang.invoke.SwitchPoint;
  40 import java.lang.reflect.Field;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.List;
  44 import java.util.Map;
  45 import java.util.Objects;
  46 import java.util.concurrent.Callable;
  47 import java.util.concurrent.ConcurrentHashMap;
  48 import javax.script.ScriptContext;
  49 import javax.script.ScriptEngine;
  50 import jdk.internal.dynalink.CallSiteDescriptor;
  51 import jdk.internal.dynalink.linker.GuardedInvocation;
  52 import jdk.internal.dynalink.linker.LinkRequest;
  53 import jdk.nashorn.api.scripting.ClassFilter;
  54 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  55 import jdk.nashorn.internal.lookup.Lookup;
  56 import jdk.nashorn.internal.objects.annotations.Attribute;
  57 import jdk.nashorn.internal.objects.annotations.Getter;
  58 import jdk.nashorn.internal.objects.annotations.Property;
  59 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  60 import jdk.nashorn.internal.objects.annotations.Setter;
  61 import jdk.nashorn.internal.runtime.Context;
  62 import jdk.nashorn.internal.runtime.ECMAErrors;
  63 import jdk.nashorn.internal.runtime.FindProperty;
  64 import jdk.nashorn.internal.runtime.GlobalConstants;
  65 import jdk.nashorn.internal.runtime.GlobalFunctions;
  66 import jdk.nashorn.internal.runtime.JSType;
  67 import jdk.nashorn.internal.runtime.NativeJavaPackage;
  68 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  69 import jdk.nashorn.internal.runtime.PropertyMap;
  70 import jdk.nashorn.internal.runtime.Scope;
  71 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  72 import jdk.nashorn.internal.runtime.ScriptFunction;
  73 import jdk.nashorn.internal.runtime.ScriptObject;
  74 import jdk.nashorn.internal.runtime.ScriptRuntime;
  75 import jdk.nashorn.internal.runtime.ScriptingFunctions;
  76 import jdk.nashorn.internal.runtime.Specialization;
  77 import jdk.nashorn.internal.runtime.arrays.ArrayData;
  78 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  79 import jdk.nashorn.internal.runtime.linker.InvokeByName;
  80 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
  81 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
  82 import jdk.nashorn.internal.scripts.JO;
  83 import jdk.nashorn.tools.ShellFunctions;
  84 
  85 /**
  86  * Representation of global scope.
  87  */
  88 @ScriptClass("Global")
  89 public final class Global extends ScriptObject implements Scope {
  90     // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
  91     private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
  92     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
  93     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
  94 
  95     // placeholder value for lazily initialized global objects
  96     private static final Object LAZY_SENTINEL = new Object();
  97 
  98     /**
  99      * Optimistic builtin names that require switchpoint invalidation
 100      * upon assignment. Overly conservative, but works for now, to avoid
 101      * any complicated scope checks and especially heavy weight guards
 102      * like
 103      *
 104      * <pre>
 105      *     public boolean setterGuard(final Object receiver) {
 106      *         final Global          global = Global.instance();
 107      *         final ScriptObject    sobj   = global.getFunctionPrototype();
 108      *         final Object          apply  = sobj.get("apply");
 109      *         return apply == receiver;
 110      *     }
 111      * </pre>
 112      *
 113      * Naturally, checking for builtin classes like NativeFunction is cheaper,
 114      * it's when you start adding property checks for said builtins you have
 115      * problems with guard speed.
 116      */
 117 
 118     /** Nashorn extension: arguments array */
 119     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 120     public Object arguments;
 121 
 122     /** ECMA 15.1.2.2 parseInt (string , radix) */
 123     @Property(attributes = Attribute.NOT_ENUMERABLE)
 124     public Object parseInt;
 125 
 126     /** ECMA 15.1.2.3 parseFloat (string) */
 127     @Property(attributes = Attribute.NOT_ENUMERABLE)
 128     public Object parseFloat;
 129 
 130     /** ECMA 15.1.2.4 isNaN (number) */
 131     @Property(attributes = Attribute.NOT_ENUMERABLE)
 132     public Object isNaN;
 133 
 134     /** ECMA 15.1.2.5 isFinite (number) */
 135     @Property(attributes = Attribute.NOT_ENUMERABLE)
 136     public Object isFinite;
 137 
 138     /** ECMA 15.1.3.3 encodeURI */
 139     @Property(attributes = Attribute.NOT_ENUMERABLE)
 140     public Object encodeURI;
 141 
 142     /** ECMA 15.1.3.4 encodeURIComponent */
 143     @Property(attributes = Attribute.NOT_ENUMERABLE)
 144     public Object encodeURIComponent;
 145 
 146     /** ECMA 15.1.3.1 decodeURI */
 147     @Property(attributes = Attribute.NOT_ENUMERABLE)
 148     public Object decodeURI;
 149 
 150     /** ECMA 15.1.3.2 decodeURIComponent */
 151     @Property(attributes = Attribute.NOT_ENUMERABLE)
 152     public Object decodeURIComponent;
 153 
 154     /** ECMA B.2.1 escape (string) */
 155     @Property(attributes = Attribute.NOT_ENUMERABLE)
 156     public Object escape;
 157 
 158     /** ECMA B.2.2 unescape (string) */
 159     @Property(attributes = Attribute.NOT_ENUMERABLE)
 160     public Object unescape;
 161 
 162     /** Nashorn extension: global.print */
 163     @Property(attributes = Attribute.NOT_ENUMERABLE)
 164     public Object print;
 165 
 166     /** Nashorn extension: global.load */
 167     @Property(attributes = Attribute.NOT_ENUMERABLE)
 168     public Object load;
 169 
 170     /** Nashorn extension: global.loadWithNewGlobal */
 171     @Property(attributes = Attribute.NOT_ENUMERABLE)
 172     public Object loadWithNewGlobal;
 173 
 174     /** Nashorn extension: global.exit */
 175     @Property(attributes = Attribute.NOT_ENUMERABLE)
 176     public Object exit;
 177 
 178     /** Nashorn extension: global.quit */
 179     @Property(attributes = Attribute.NOT_ENUMERABLE)
 180     public Object quit;
 181 
 182     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
 183     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 184     public final double NaN = Double.NaN;
 185 
 186     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
 187     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 188     public final double Infinity = Double.POSITIVE_INFINITY;
 189 
 190     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
 191     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 192     public final Object undefined = UNDEFINED;
 193 
 194     /** ECMA 15.1.2.1 eval(x) */
 195     @Property(attributes = Attribute.NOT_ENUMERABLE)
 196     public Object eval;
 197 
 198     /** ECMA 15.1.4.1 Object constructor. */
 199     @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE)
 200     public volatile Object object;
 201 
 202     /** ECMA 15.1.4.2 Function constructor. */
 203     @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE)
 204     public volatile Object function;
 205 
 206     /** ECMA 15.1.4.3 Array constructor. */
 207     @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE)
 208     public volatile Object array;
 209 
 210     /** ECMA 15.1.4.4 String constructor */
 211     @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE)
 212     public volatile Object string;
 213 
 214     /** ECMA 15.1.4.5 Boolean constructor */
 215     @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE)
 216     public volatile Object _boolean;
 217 
 218     /** ECMA 15.1.4.6 - Number constructor */
 219     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
 220     public volatile Object number;
 221 
 222     /** ECMA 15.1.4.7 Date constructor */
 223     @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 224     public static Object getDate(final Object self) {
 225         final Global global = Global.instanceFrom(self);
 226         if (global.date == LAZY_SENTINEL) {
 227             global.date = global.getBuiltinDate();
 228         }
 229         return global.date;
 230     }
 231 
 232     @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
 233     public static void setDate(final Object self, final Object value) {
 234         final Global global = Global.instanceFrom(self);
 235         global.date = value;
 236     }
 237 
 238     private volatile Object date = LAZY_SENTINEL;
 239 
 240     /** ECMA 15.1.4.8 RegExp constructor */
 241     @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 242     public static Object getRegExp(final Object self) {
 243         final Global global = Global.instanceFrom(self);
 244         if (global.regexp == LAZY_SENTINEL) {
 245             global.regexp = global.getBuiltinRegExp();
 246         }
 247         return global.regexp;
 248     }
 249 
 250     @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
 251     public static void setRegExp(final Object self, final Object value) {
 252         final Global global = Global.instanceFrom(self);
 253         global.regexp = value;
 254     }
 255 
 256     private volatile Object regexp = LAZY_SENTINEL;
 257 
 258     /** ECMA 15.12 - The JSON object */
 259     @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 260     public static Object getJSON(final Object self) {
 261         final Global global = Global.instanceFrom(self);
 262         if (global.json == LAZY_SENTINEL) {
 263             global.json = global.getBuiltinJSON();
 264         }
 265         return global.json;
 266     }
 267 
 268     @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
 269     public static void setJSON(final Object self, final Object value) {
 270         final Global global = Global.instanceFrom(self);
 271         global.json = value;
 272     }
 273 
 274     private volatile Object json = LAZY_SENTINEL;
 275 
 276     /** Nashorn extension: global.JSAdapter */
 277     @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 278     public static Object getJSAdapter(final Object self) {
 279         final Global global = Global.instanceFrom(self);
 280         if (global.jsadapter == LAZY_SENTINEL) {
 281             global.jsadapter = global.getBuiltinJSAdapter();
 282         }
 283         return global.jsadapter;
 284     }
 285 
 286     @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
 287     public static void setJSAdapter(final Object self, final Object value) {
 288         final Global global = Global.instanceFrom(self);
 289         global.jsadapter = value;
 290     }
 291 
 292     private volatile Object jsadapter = LAZY_SENTINEL;
 293 
 294     /** ECMA 15.8 - The Math object */
 295     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
 296     public volatile Object math;
 297 
 298     /** Error object */
 299     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
 300     public volatile Object error;
 301 
 302     /** EvalError object */
 303     @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 304     public static Object getEvalError(final Object self) {
 305         final Global global = Global.instanceFrom(self);
 306         if (global.evalError == LAZY_SENTINEL) {
 307             global.evalError = global.getBuiltinEvalError();
 308         }
 309         return global.evalError;
 310     }
 311 
 312     @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
 313     public static void setEvalError(final Object self, final Object value) {
 314         final Global global = Global.instanceFrom(self);
 315         global.evalError = value;
 316     }
 317 
 318     private volatile Object evalError = LAZY_SENTINEL;
 319 
 320     /** RangeError object */
 321     @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 322     public static Object getRangeError(final Object self) {
 323         final Global global = Global.instanceFrom(self);
 324         if (global.rangeError == LAZY_SENTINEL) {
 325             global.rangeError = global.getBuiltinRangeError();
 326         }
 327         return global.rangeError;
 328     }
 329 
 330     @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
 331     public static void setRangeError(final Object self, final Object value) {
 332         final Global global = Global.instanceFrom(self);
 333         global.rangeError = value;
 334     }
 335 
 336     private volatile Object rangeError = LAZY_SENTINEL;
 337 
 338     /** ReferenceError object */
 339     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
 340     public volatile Object referenceError;
 341 
 342     /** SyntaxError object */
 343     @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE)
 344     public volatile Object syntaxError;
 345 
 346     /** TypeError object */
 347     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
 348     public volatile Object typeError;
 349 
 350     /** URIError object */
 351     @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 352     public static Object getURIError(final Object self) {
 353         final Global global = Global.instanceFrom(self);
 354         if (global.uriError == LAZY_SENTINEL) {
 355             global.uriError = global.getBuiltinURIError();
 356         }
 357         return global.uriError;
 358     }
 359 
 360     @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
 361     public static void setURIError(final Object self, final Object value) {
 362         final Global global = Global.instanceFrom(self);
 363         global.uriError = value;
 364     }
 365 
 366     private volatile Object uriError = LAZY_SENTINEL;
 367 
 368     /** ArrayBuffer object */
 369     @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 370     public static Object getArrayBuffer(final Object self) {
 371         final Global global = Global.instanceFrom(self);
 372         if (global.arrayBuffer == LAZY_SENTINEL) {
 373             global.arrayBuffer = global.getBuiltinArrayBuffer();
 374         }
 375         return global.arrayBuffer;
 376     }
 377 
 378     @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
 379     public static void setArrayBuffer(final Object self, final Object value) {
 380         final Global global = Global.instanceFrom(self);
 381         global.arrayBuffer = value;
 382     }
 383 
 384     private volatile Object arrayBuffer;
 385 
 386     /** DataView object */
 387     @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 388     public static Object getDataView(final Object self) {
 389         final Global global = Global.instanceFrom(self);
 390         if (global.dataView == LAZY_SENTINEL) {
 391             global.dataView = global.getBuiltinDataView();
 392         }
 393         return global.dataView;
 394     }
 395 
 396     @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
 397     public static void setDataView(final Object self, final Object value) {
 398         final Global global = Global.instanceFrom(self);
 399         global.dataView = value;
 400     }
 401 
 402     private volatile Object dataView;
 403 
 404     /** TypedArray (int8) */
 405     @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 406     public static Object getInt8Array(final Object self) {
 407         final Global global = Global.instanceFrom(self);
 408         if (global.int8Array == LAZY_SENTINEL) {
 409             global.int8Array = global.getBuiltinInt8Array();
 410         }
 411         return global.int8Array;
 412     }
 413 
 414     @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
 415     public static void setInt8Array(final Object self, final Object value) {
 416         final Global global = Global.instanceFrom(self);
 417         global.int8Array = value;
 418     }
 419 
 420     private volatile Object int8Array;
 421 
 422     /** TypedArray (uint8) */
 423     @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 424     public static Object getUint8Array(final Object self) {
 425         final Global global = Global.instanceFrom(self);
 426         if (global.uint8Array == LAZY_SENTINEL) {
 427             global.uint8Array = global.getBuiltinUint8Array();
 428         }
 429         return global.uint8Array;
 430     }
 431 
 432     @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
 433     public static void setUint8Array(final Object self, final Object value) {
 434         final Global global = Global.instanceFrom(self);
 435         global.uint8Array = value;
 436     }
 437 
 438     private volatile Object uint8Array;
 439 
 440     /** TypedArray (uint8) - Clamped */
 441     @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 442     public static Object getUint8ClampedArray(final Object self) {
 443         final Global global = Global.instanceFrom(self);
 444         if (global.uint8ClampedArray == LAZY_SENTINEL) {
 445             global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
 446         }
 447         return global.uint8ClampedArray;
 448     }
 449 
 450     @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
 451     public static void setUint8ClampedArray(final Object self, final Object value) {
 452         final Global global = Global.instanceFrom(self);
 453         global.uint8ClampedArray = value;
 454     }
 455 
 456     private volatile Object uint8ClampedArray;
 457 
 458     /** TypedArray (int16) */
 459     @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 460     public static Object getInt16Array(final Object self) {
 461         final Global global = Global.instanceFrom(self);
 462         if (global.int16Array == LAZY_SENTINEL) {
 463             global.int16Array = global.getBuiltinInt16Array();
 464         }
 465         return global.int16Array;
 466     }
 467 
 468     @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
 469     public static void setInt16Array(final Object self, final Object value) {
 470         final Global global = Global.instanceFrom(self);
 471         global.int16Array = value;
 472     }
 473 
 474     private volatile Object int16Array;
 475 
 476     /** TypedArray (uint16) */
 477     @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 478     public static Object getUint16Array(final Object self) {
 479         final Global global = Global.instanceFrom(self);
 480         if (global.uint16Array == LAZY_SENTINEL) {
 481             global.uint16Array = global.getBuiltinUint16Array();
 482         }
 483         return global.uint16Array;
 484     }
 485 
 486     @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
 487     public static void setUint16Array(final Object self, final Object value) {
 488         final Global global = Global.instanceFrom(self);
 489         global.uint16Array = value;
 490     }
 491 
 492     private volatile Object uint16Array;
 493 
 494     /** TypedArray (int32) */
 495     @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 496     public static Object getInt32Array(final Object self) {
 497         final Global global = Global.instanceFrom(self);
 498         if (global.int32Array == LAZY_SENTINEL) {
 499             global.int32Array = global.getBuiltinInt32Array();
 500         }
 501         return global.int32Array;
 502     }
 503 
 504     @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
 505     public static void setInt32Array(final Object self, final Object value) {
 506         final Global global = Global.instanceFrom(self);
 507         global.int32Array = value;
 508     }
 509 
 510     private volatile Object int32Array;
 511 
 512     /** TypedArray (uint32) */
 513     @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 514     public static Object getUint32Array(final Object self) {
 515         final Global global = Global.instanceFrom(self);
 516         if (global.uint32Array == LAZY_SENTINEL) {
 517             global.uint32Array = global.getBuiltinUint32Array();
 518         }
 519         return global.uint32Array;
 520     }
 521 
 522     @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
 523     public static void setUint32Array(final Object self, final Object value) {
 524         final Global global = Global.instanceFrom(self);
 525         global.uint32Array = value;
 526     }
 527 
 528     private volatile Object uint32Array;
 529 
 530     /** TypedArray (float32) */
 531     @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 532     public static Object getFloat32Array(final Object self) {
 533         final Global global = Global.instanceFrom(self);
 534         if (global.float32Array == LAZY_SENTINEL) {
 535             global.float32Array = global.getBuiltinFloat32Array();
 536         }
 537         return global.float32Array;
 538     }
 539 
 540     @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
 541     public static void setFloat32Array(final Object self, final Object value) {
 542         final Global global = Global.instanceFrom(self);
 543         global.float32Array = value;
 544     }
 545 
 546     private volatile Object float32Array;
 547 
 548     /** TypedArray (float64) */
 549     @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 550     public static Object getFloat64Array(final Object self) {
 551         final Global global = Global.instanceFrom(self);
 552         if (global.float64Array == LAZY_SENTINEL) {
 553             global.float64Array = global.getBuiltinFloat64Array();
 554         }
 555         return global.float64Array;
 556     }
 557 
 558     @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
 559     public static void setFloat64Array(final Object self, final Object value) {
 560         final Global global = Global.instanceFrom(self);
 561         global.float64Array = value;
 562     }
 563 
 564     private volatile Object float64Array;
 565 
 566     /** Nashorn extension: Java access - global.Packages */
 567     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
 568     public volatile Object packages;
 569 
 570     /** Nashorn extension: Java access - global.com */
 571     @Property(attributes = Attribute.NOT_ENUMERABLE)
 572     public volatile Object com;
 573 
 574     /** Nashorn extension: Java access - global.edu */
 575     @Property(attributes = Attribute.NOT_ENUMERABLE)
 576     public volatile Object edu;
 577 
 578     /** Nashorn extension: Java access - global.java */
 579     @Property(attributes = Attribute.NOT_ENUMERABLE)
 580     public volatile Object java;
 581 
 582     /** Nashorn extension: Java access - global.javafx */
 583     @Property(attributes = Attribute.NOT_ENUMERABLE)
 584     public volatile Object javafx;
 585 
 586     /** Nashorn extension: Java access - global.javax */
 587     @Property(attributes = Attribute.NOT_ENUMERABLE)
 588     public volatile Object javax;
 589 
 590     /** Nashorn extension: Java access - global.org */
 591     @Property(attributes = Attribute.NOT_ENUMERABLE)
 592     public volatile Object org;
 593 
 594     /** Nashorn extension: Java access - global.javaImporter */
 595     @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 596     public static Object getJavaImporter(final Object self) {
 597         final Global global = Global.instanceFrom(self);
 598         if (global.javaImporter == LAZY_SENTINEL) {
 599             global.javaImporter = global.getBuiltinJavaImporter();
 600         }
 601         return global.javaImporter;
 602     }
 603 
 604     @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
 605     public static void setJavaImporter(final Object self, final Object value) {
 606         final Global global = Global.instanceFrom(self);
 607         global.javaImporter = value;
 608     }
 609 
 610     private volatile Object javaImporter;
 611 
 612     /** Nashorn extension: global.Java Object constructor. */
 613     @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 614     public static Object getJavaApi(final Object self) {
 615         final Global global = Global.instanceFrom(self);
 616         if (global.javaApi == LAZY_SENTINEL) {
 617             global.javaApi = global.getBuiltinJavaApi();
 618         }
 619         return global.javaApi;
 620     }
 621 
 622     @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
 623     public static void setJavaApi(final Object self, final Object value) {
 624         final Global global = Global.instanceFrom(self);
 625         global.javaApi = value;
 626     }
 627 
 628     private volatile Object javaApi;
 629 
 630     /** Nashorn extension: current script's file name */
 631     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 632     public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 633 
 634     /** Nashorn extension: current script's directory */
 635     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 636     public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 637 
 638     /** Nashorn extension: current source line number being executed */
 639     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
 640     public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 641 
 642     private volatile NativeDate DEFAULT_DATE;
 643 
 644     /** Used as Date.prototype's default value */
 645     NativeDate getDefaultDate() {
 646         return DEFAULT_DATE;
 647     }
 648 
 649     private volatile NativeRegExp DEFAULT_REGEXP;
 650 
 651     /** Used as RegExp.prototype's default value */
 652     NativeRegExp getDefaultRegExp() {
 653         return DEFAULT_REGEXP;
 654     }
 655 
 656     /*
 657      * Built-in constructor objects: Even if user changes dynamic values of
 658      * "Object", "Array" etc., we still want to keep original values of these
 659      * constructors here. For example, we need to be able to create array,
 660      * regexp literals even after user overwrites global "Array" or "RegExp"
 661      * constructor - see also ECMA 262 spec. Annex D.
 662      */
 663     private ScriptFunction builtinFunction;
 664     private ScriptFunction builtinObject;
 665     private ScriptFunction builtinArray;
 666     private ScriptFunction builtinBoolean;
 667     private ScriptFunction builtinDate;
 668     private ScriptObject   builtinJSON;
 669     private ScriptFunction builtinJSAdapter;
 670     private ScriptObject   builtinMath;
 671     private ScriptFunction builtinNumber;
 672     private ScriptFunction builtinRegExp;
 673     private ScriptFunction builtinString;
 674     private ScriptFunction builtinError;
 675     private ScriptFunction builtinEval;
 676     private ScriptFunction builtinEvalError;
 677     private ScriptFunction builtinRangeError;
 678     private ScriptFunction builtinReferenceError;
 679     private ScriptFunction builtinSyntaxError;
 680     private ScriptFunction builtinTypeError;
 681     private ScriptFunction builtinURIError;
 682     private ScriptObject   builtinPackages;
 683     private ScriptObject   builtinCom;
 684     private ScriptObject   builtinEdu;
 685     private ScriptObject   builtinJava;
 686     private ScriptObject   builtinJavafx;
 687     private ScriptObject   builtinJavax;
 688     private ScriptObject   builtinOrg;
 689     private ScriptFunction builtinJavaImporter;
 690     private ScriptObject   builtinJavaApi;
 691     private ScriptFunction builtinArrayBuffer;
 692     private ScriptFunction builtinDataView;
 693     private ScriptFunction builtinInt8Array;
 694     private ScriptFunction builtinUint8Array;
 695     private ScriptFunction builtinUint8ClampedArray;
 696     private ScriptFunction builtinInt16Array;
 697     private ScriptFunction builtinUint16Array;
 698     private ScriptFunction builtinInt32Array;
 699     private ScriptFunction builtinUint32Array;
 700     private ScriptFunction builtinFloat32Array;
 701     private ScriptFunction builtinFloat64Array;
 702 
 703     /*
 704      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
 705      */
 706     private ScriptFunction typeErrorThrower;
 707 
 708     // Flag to indicate that a split method issued a return statement
 709     private int splitState = -1;
 710 
 711     // Used to store the last RegExp result to support deprecated RegExp constructor properties
 712     private RegExpResult lastRegExpResult;
 713 
 714     private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
 715     private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
 716     private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
 717     private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
 718     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
 719     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
 720     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
 721     private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
 722 
 723     // initialized by nasgen
 724     private static PropertyMap $nasgenmap$;
 725 
 726     // context to which this global belongs to
 727     private final Context context;
 728 
 729     // current ScriptContext to use - can be null.
 730     private ScriptContext scontext;
 731     // current ScriptEngine associated - can be null.
 732     private ScriptEngine engine;
 733 
 734     // ES6 global lexical scope.
 735     private final LexicalScope lexicalScope;
 736 
 737     // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
 738     private SwitchPoint lexicalScopeSwitchPoint;
 739 
 740     /**
 741      * Set the current script context
 742      * @param scontext script context
 743      */
 744     public void setScriptContext(final ScriptContext scontext) {
 745         this.scontext = scontext;
 746     }
 747 
 748     @Override
 749     protected Context getContext() {
 750         return context;
 751     }
 752 
 753     // performs initialization checks for Global constructor and returns the
 754     // PropertyMap, if everything is fine.
 755     private static PropertyMap checkAndGetMap(final Context context) {
 756         // security check first
 757         final SecurityManager sm = System.getSecurityManager();
 758         if (sm != null) {
 759             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
 760         }
 761 
 762         Objects.requireNonNull(context);
 763 
 764         return $nasgenmap$;
 765     }
 766 
 767     /**
 768      * Constructor
 769      *
 770      * @param context the context
 771      */
 772     public Global(final Context context) {
 773         super(checkAndGetMap(context));
 774         this.context = context;
 775         this.setIsScope();
 776         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
 777     }
 778 
 779     /**
 780      * Script access to "current" Global instance
 781      *
 782      * @return the global singleton
 783      */
 784     public static Global instance() {
 785         final Global global = Context.getGlobal();
 786         Objects.requireNonNull(global);
 787         return global;
 788     }
 789 
 790     private static Global instanceFrom(final Object self) {
 791         return self instanceof Global? (Global)self : instance();
 792     }
 793 
 794     /**
 795      * Check if we have a Global instance
 796      * @return true if one exists
 797      */
 798     public static boolean hasInstance() {
 799         return Context.getGlobal() != null;
 800     }
 801 
 802     /**
 803      * Script access to {@link ScriptEnvironment}
 804      *
 805      * @return the script environment
 806      */
 807     static ScriptEnvironment getEnv() {
 808         return instance().getContext().getEnv();
 809     }
 810 
 811     /**
 812      * Script access to {@link Context}
 813      *
 814      * @return the context
 815      */
 816     static Context getThisContext() {
 817         return instance().getContext();
 818     }
 819 
 820     // Runtime interface to Global
 821 
 822     /**
 823      * Is there a class filter in the current Context?
 824      * @return class filter
 825      */
 826     public ClassFilter getClassFilter() {
 827         return context.getClassFilter();
 828     }
 829 
 830     /**
 831      * Is this global of the given Context?
 832      * @param ctxt the context
 833      * @return true if this global belongs to the given Context
 834      */
 835     public boolean isOfContext(final Context ctxt) {
 836         return this.context == ctxt;
 837     }
 838 
 839     /**
 840      * Does this global belong to a strict Context?
 841      * @return true if this global belongs to a strict Context
 842      */
 843     public boolean isStrictContext() {
 844         return context.getEnv()._strict;
 845     }
 846 
 847     /**
 848      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
 849      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
 850      * of the global scope object.
 851      *
 852      * @param eng ScriptEngine to initialize
 853      */
 854     public void initBuiltinObjects(final ScriptEngine eng) {
 855         if (this.builtinObject != null) {
 856             // already initialized, just return
 857             return;
 858         }
 859 
 860         this.engine = eng;
 861         init(eng);
 862     }
 863 
 864     /**
 865      * Wrap a Java object as corresponding script object
 866      *
 867      * @param obj object to wrap
 868      * @return    wrapped object
 869      */
 870     public Object wrapAsObject(final Object obj) {
 871         if (obj instanceof Boolean) {
 872             return new NativeBoolean((Boolean)obj, this);
 873         } else if (obj instanceof Number) {
 874             return new NativeNumber(((Number)obj).doubleValue(), this);
 875         } else if (isString(obj)) {
 876             return new NativeString((CharSequence)obj, this);
 877         } else if (obj instanceof Object[]) { // extension
 878             return new NativeArray(ArrayData.allocate((Object[])obj), this);
 879         } else if (obj instanceof double[]) { // extension
 880             return new NativeArray(ArrayData.allocate((double[])obj), this);
 881         } else if (obj instanceof long[]) {
 882             return new NativeArray(ArrayData.allocate((long[])obj), this);
 883         } else if (obj instanceof int[]) {
 884             return new NativeArray(ArrayData.allocate((int[]) obj), this);
 885         } else if (obj instanceof ArrayData) {
 886             return new NativeArray((ArrayData) obj, this);
 887         } else {
 888             // FIXME: more special cases? Map? List?
 889             return obj;
 890         }
 891     }
 892 
 893     /**
 894      * Lookup helper for JS primitive types
 895      *
 896      * @param request the link request for the dynamic call site.
 897      * @param self     self reference
 898      *
 899      * @return guarded invocation
 900      */
 901     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
 902         if (isString(self)) {
 903             return NativeString.lookupPrimitive(request, self);
 904         } else if (self instanceof Number) {
 905             return NativeNumber.lookupPrimitive(request, self);
 906         } else if (self instanceof Boolean) {
 907             return NativeBoolean.lookupPrimitive(request, self);
 908         }
 909         throw new IllegalArgumentException("Unsupported primitive: " + self);
 910     }
 911 
 912     /**
 913      * Returns a method handle that creates a wrapper object for a JS primitive value.
 914      *
 915      * @param self receiver object
 916      * @return method handle to create wrapper objects for primitive receiver
 917      */
 918     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
 919         if (isString(self)) {
 920             return NativeString.WRAPFILTER;
 921         } else if (self instanceof Number) {
 922             return NativeNumber.WRAPFILTER;
 923         } else if (self instanceof Boolean) {
 924             return NativeBoolean.WRAPFILTER;
 925         }
 926         throw new IllegalArgumentException("Unsupported primitive: " + self);
 927     }
 928 
 929 
 930     /**
 931      * Create a new empty script object
 932      *
 933      * @return the new ScriptObject
 934      */
 935     public ScriptObject newObject() {
 936         return new JO(getObjectPrototype(), JO.getInitialMap());
 937     }
 938 
 939     /**
 940      * Default value of given type
 941      *
 942      * @param sobj     script object
 943      * @param typeHint type hint
 944      *
 945      * @return default value
 946      */
 947     public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
 948         // When the [[DefaultValue]] internal method of O is called with no hint,
 949         // then it behaves as if the hint were Number, unless O is a Date object
 950         // in which case it behaves as if the hint were String.
 951         Class<?> hint = typeHint;
 952         if (hint == null) {
 953             hint = Number.class;
 954         }
 955 
 956         try {
 957             if (hint == String.class) {
 958 
 959                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 960 
 961                 if (Bootstrap.isCallable(toString)) {
 962                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 963                     if (JSType.isPrimitive(value)) {
 964                         return value;
 965                     }
 966                 }
 967 
 968                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 969                 if (Bootstrap.isCallable(valueOf)) {
 970                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 971                     if (JSType.isPrimitive(value)) {
 972                         return value;
 973                     }
 974                 }
 975                 throw typeError(this, "cannot.get.default.string");
 976             }
 977 
 978             if (hint == Number.class) {
 979                 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj);
 980                 if (Bootstrap.isCallable(valueOf)) {
 981                     final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj);
 982                     if (JSType.isPrimitive(value)) {
 983                         return value;
 984                     }
 985                 }
 986 
 987                 final Object toString = TO_STRING.getGetter().invokeExact(sobj);
 988                 if (Bootstrap.isCallable(toString)) {
 989                     final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj);
 990                     if (JSType.isPrimitive(value)) {
 991                         return value;
 992                     }
 993                 }
 994 
 995                 throw typeError(this, "cannot.get.default.number");
 996             }
 997         } catch (final RuntimeException | Error e) {
 998             throw e;
 999         } catch (final Throwable t) {
1000             throw new RuntimeException(t);
1001         }
1002 
1003         return UNDEFINED;
1004     }
1005 
1006     /**
1007      * Is the given ScriptObject an ECMAScript Error object?
1008      *
1009      * @param sobj the object being checked
1010      * @return true if sobj is an Error object
1011      */
1012     public boolean isError(final ScriptObject sobj) {
1013         final ScriptObject errorProto = getErrorPrototype();
1014         ScriptObject proto = sobj.getProto();
1015         while (proto != null) {
1016             if (proto == errorProto) {
1017                 return true;
1018             }
1019             proto = proto.getProto();
1020         }
1021         return false;
1022     }
1023 
1024     /**
1025      * Create a new ECMAScript Error object.
1026      *
1027      * @param msg error message
1028      * @return newly created Error object
1029      */
1030     public ScriptObject newError(final String msg) {
1031         return new NativeError(msg, this);
1032     }
1033 
1034     /**
1035      * Create a new ECMAScript EvalError object.
1036      *
1037      * @param msg error message
1038      * @return newly created EvalError object
1039      */
1040     public ScriptObject newEvalError(final String msg) {
1041         return new NativeEvalError(msg, this);
1042     }
1043 
1044     /**
1045      * Create a new ECMAScript RangeError object.
1046      *
1047      * @param msg error message
1048      * @return newly created RangeError object
1049      */
1050     public ScriptObject newRangeError(final String msg) {
1051         return new NativeRangeError(msg, this);
1052     }
1053 
1054     /**
1055      * Create a new ECMAScript ReferenceError object.
1056      *
1057      * @param msg error message
1058      * @return newly created ReferenceError object
1059      */
1060     public ScriptObject newReferenceError(final String msg) {
1061         return new NativeReferenceError(msg, this);
1062     }
1063 
1064     /**
1065      * Create a new ECMAScript SyntaxError object.
1066      *
1067      * @param msg error message
1068      * @return newly created SyntaxError object
1069      */
1070     public ScriptObject newSyntaxError(final String msg) {
1071         return new NativeSyntaxError(msg, this);
1072     }
1073 
1074     /**
1075      * Create a new ECMAScript TypeError object.
1076      *
1077      * @param msg error message
1078      * @return newly created TypeError object
1079      */
1080     public ScriptObject newTypeError(final String msg) {
1081         return new NativeTypeError(msg, this);
1082     }
1083 
1084     /**
1085      * Create a new ECMAScript URIError object.
1086      *
1087      * @param msg error message
1088      * @return newly created URIError object
1089      */
1090     public ScriptObject newURIError(final String msg) {
1091         return new NativeURIError(msg, this);
1092     }
1093 
1094     /**
1095      * Create a new ECMAScript GenericDescriptor object.
1096      *
1097      * @param configurable is the property configurable?
1098      * @param enumerable is the property enumerable?
1099      * @return newly created GenericDescriptor object
1100      */
1101     public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
1102         return new GenericPropertyDescriptor(configurable, enumerable, this);
1103     }
1104 
1105     /**
1106      * Create a new ECMAScript DatePropertyDescriptor object.
1107      *
1108      * @param value of the data property
1109      * @param configurable is the property configurable?
1110      * @param enumerable is the property enumerable?
1111      * @param writable is the property writable?
1112      * @return newly created DataPropertyDescriptor object
1113      */
1114     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
1115         return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
1116     }
1117 
1118     /**
1119      * Create a new ECMAScript AccessorPropertyDescriptor object.
1120      *
1121      * @param get getter function of the user accessor property
1122      * @param set setter function of the user accessor property
1123      * @param configurable is the property configurable?
1124      * @param enumerable is the property enumerable?
1125      * @return newly created AccessorPropertyDescriptor object
1126      */
1127     public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
1128         final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
1129 
1130         if (get == null) {
1131             desc.delete(PropertyDescriptor.GET, false);
1132         }
1133 
1134         if (set == null) {
1135             desc.delete(PropertyDescriptor.SET, false);
1136         }
1137 
1138         return desc;
1139     }
1140 
1141     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
1142         final T obj = map.get(key);
1143         if (obj != null) {
1144             return obj;
1145         }
1146 
1147         try {
1148             final T newObj = creator.call();
1149             final T existingObj = map.putIfAbsent(key, newObj);
1150             return existingObj != null ? existingObj : newObj;
1151         } catch (final Exception exp) {
1152             throw new RuntimeException(exp);
1153         }
1154     }
1155 
1156     private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
1157 
1158 
1159     /**
1160      * Get cached InvokeByName object for the given key
1161      * @param key key to be associated with InvokeByName object
1162      * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
1163      * @return InvokeByName object associated with the key.
1164      */
1165     public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
1166         return getLazilyCreatedValue(key, creator, namedInvokers);
1167     }
1168 
1169     private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
1170 
1171     /**
1172      * Get cached dynamic method handle for the given key
1173      * @param key key to be associated with dynamic method handle
1174      * @param creator if method handle is absent 'creator' is called to make one (lazy init)
1175      * @return dynamic method handle associated with the key.
1176      */
1177     public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
1178         return getLazilyCreatedValue(key, creator, dynamicInvokers);
1179     }
1180 
1181     /**
1182      * Hook to search missing variables in ScriptContext if available
1183      * @param self used to detect if scope call or not (this function is 'strict')
1184      * @param name name of the variable missing
1185      * @return value of the missing variable or undefined (or TypeError for scope search)
1186      */
1187     public static Object __noSuchProperty__(final Object self, final Object name) {
1188         final Global global = Global.instance();
1189         final ScriptContext sctxt = global.scontext;
1190         final String nameStr = name.toString();
1191 
1192         if (sctxt != null) {
1193             final int scope = sctxt.getAttributesScope(nameStr);
1194             if (scope != -1) {
1195                 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
1196             }
1197         }
1198 
1199         switch (nameStr) {
1200         case "context":
1201             return sctxt;
1202         case "engine":
1203             return global.engine;
1204         default:
1205             break;
1206         }
1207 
1208         if (self == UNDEFINED) {
1209             // scope access and so throw ReferenceError
1210             throw referenceError(global, "not.defined", nameStr);
1211         }
1212 
1213         return UNDEFINED;
1214     }
1215 
1216     /**
1217      * This is the eval used when 'indirect' eval call is made.
1218      *
1219      * var global = this;
1220      * global.eval("print('hello')");
1221      *
1222      * @param self  eval scope
1223      * @param str   eval string
1224      *
1225      * @return the result of eval
1226      */
1227     public static Object eval(final Object self, final Object str) {
1228         return directEval(self, str, UNDEFINED, UNDEFINED, false);
1229     }
1230 
1231     /**
1232      * Direct eval
1233      *
1234      * @param self     The scope of eval passed as 'self'
1235      * @param str      Evaluated code
1236      * @param callThis "this" to be passed to the evaluated code
1237      * @param location location of the eval call
1238      * @param strict   is eval called a strict mode code?
1239      *
1240      * @return the return value of the eval
1241      *
1242      * This is directly invoked from generated when eval(code) is called in user code
1243      */
1244     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
1245         if (!isString(str)) {
1246             return str;
1247         }
1248         final Global global = Global.instanceFrom(self);
1249         final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
1250 
1251         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
1252     }
1253 
1254     /**
1255      * Global print implementation - Nashorn extension
1256      *
1257      * @param self    scope
1258      * @param objects arguments to print
1259      *
1260      * @return result of print (undefined)
1261      */
1262     public static Object print(final Object self, final Object... objects) {
1263         return Global.instanceFrom(self).printImpl(false, objects);
1264     }
1265 
1266     /**
1267      * Global println implementation - Nashorn extension
1268      *
1269      * @param self    scope
1270      * @param objects arguments to print
1271      *
1272      * @return result of println (undefined)
1273      */
1274     public static Object println(final Object self, final Object... objects) {
1275         return Global.instanceFrom(self).printImpl(true, objects);
1276     }
1277 
1278     /**
1279      * Global load implementation - Nashorn extension
1280      *
1281      * @param self    scope
1282      * @param source  source to load
1283      *
1284      * @return result of load (undefined)
1285      *
1286      * @throws IOException if source could not be read
1287      */
1288     public static Object load(final Object self, final Object source) throws IOException {
1289         final Global global = Global.instanceFrom(self);
1290         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
1291         return global.getContext().load(scope, source);
1292     }
1293 
1294     /**
1295      * Global loadWithNewGlobal implementation - Nashorn extension
1296      *
1297      * @param self scope
1298      * @param args from plus (optional) arguments to be passed to the loaded script
1299      *
1300      * @return result of load (may be undefined)
1301      *
1302      * @throws IOException if source could not be read
1303      */
1304     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
1305         final Global global = Global.instanceFrom(self);
1306         final int length = args.length;
1307         final boolean hasArgs = 0 < length;
1308         final Object from = hasArgs ? args[0] : UNDEFINED;
1309         final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
1310 
1311         return global.getContext().loadWithNewGlobal(from, arguments);
1312     }
1313 
1314     /**
1315      * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
1316      *
1317      * @param self  self reference
1318      * @param code  exit code
1319      *
1320      * @return undefined (will never be reached)
1321      */
1322     public static Object exit(final Object self, final Object code) {
1323         System.exit(JSType.toInt32(code));
1324         return UNDEFINED;
1325     }
1326 
1327     // builtin prototype accessors
1328 
1329     /**
1330      * Get the builtin Object prototype.
1331      * @return the object prototype.
1332      */
1333     public ScriptObject getObjectPrototype() {
1334         return ScriptFunction.getPrototype(builtinObject);
1335     }
1336 
1337     ScriptObject getFunctionPrototype() {
1338         return ScriptFunction.getPrototype(builtinFunction);
1339     }
1340 
1341     ScriptObject getArrayPrototype() {
1342         return ScriptFunction.getPrototype(builtinArray);
1343     }
1344 
1345     ScriptObject getBooleanPrototype() {
1346         return ScriptFunction.getPrototype(builtinBoolean);
1347     }
1348 
1349     ScriptObject getNumberPrototype() {
1350         return ScriptFunction.getPrototype(builtinNumber);
1351     }
1352 
1353     ScriptObject getDatePrototype() {
1354         return ScriptFunction.getPrototype(getBuiltinDate());
1355     }
1356 
1357     ScriptObject getRegExpPrototype() {
1358         return ScriptFunction.getPrototype(getBuiltinRegExp());
1359     }
1360 
1361     ScriptObject getStringPrototype() {
1362         return ScriptFunction.getPrototype(builtinString);
1363     }
1364 
1365     ScriptObject getErrorPrototype() {
1366         return ScriptFunction.getPrototype(builtinError);
1367     }
1368 
1369     ScriptObject getEvalErrorPrototype() {
1370         return ScriptFunction.getPrototype(getBuiltinEvalError());
1371     }
1372 
1373     ScriptObject getRangeErrorPrototype() {
1374         return ScriptFunction.getPrototype(getBuiltinRangeError());
1375     }
1376 
1377     ScriptObject getReferenceErrorPrototype() {
1378         return ScriptFunction.getPrototype(builtinReferenceError);
1379     }
1380 
1381     ScriptObject getSyntaxErrorPrototype() {
1382         return ScriptFunction.getPrototype(builtinSyntaxError);
1383     }
1384 
1385     ScriptObject getTypeErrorPrototype() {
1386         return ScriptFunction.getPrototype(builtinTypeError);
1387     }
1388 
1389     ScriptObject getURIErrorPrototype() {
1390         return ScriptFunction.getPrototype(getBuiltinURIError());
1391     }
1392 
1393     ScriptObject getJavaImporterPrototype() {
1394         return ScriptFunction.getPrototype(getBuiltinJavaImporter());
1395     }
1396 
1397     ScriptObject getJSAdapterPrototype() {
1398         return ScriptFunction.getPrototype(getBuiltinJSAdapter());
1399     }
1400 
1401     private synchronized ScriptFunction getBuiltinArrayBuffer() {
1402         if (this.builtinArrayBuffer == null) {
1403             this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
1404         }
1405         return this.builtinArrayBuffer;
1406     }
1407 
1408     ScriptObject getArrayBufferPrototype() {
1409         return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
1410     }
1411 
1412     private synchronized ScriptFunction getBuiltinDataView() {
1413         if (this.builtinDataView == null) {
1414             this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
1415         }
1416         return this.builtinDataView;
1417     }
1418 
1419     ScriptObject getDataViewPrototype() {
1420         return ScriptFunction.getPrototype(getBuiltinDataView());
1421     }
1422 
1423     private synchronized ScriptFunction getBuiltinInt8Array() {
1424         if (this.builtinInt8Array == null) {
1425             this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
1426         }
1427         return this.builtinInt8Array;
1428     }
1429 
1430     ScriptObject getInt8ArrayPrototype() {
1431         return ScriptFunction.getPrototype(getBuiltinInt8Array());
1432     }
1433 
1434     private synchronized ScriptFunction getBuiltinUint8Array() {
1435         if (this.builtinUint8Array == null) {
1436             this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
1437         }
1438         return this.builtinUint8Array;
1439     }
1440 
1441     ScriptObject getUint8ArrayPrototype() {
1442         return ScriptFunction.getPrototype(getBuiltinUint8Array());
1443     }
1444 
1445     private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
1446         if (this.builtinUint8ClampedArray == null) {
1447             this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
1448         }
1449         return this.builtinUint8ClampedArray;
1450     }
1451 
1452     ScriptObject getUint8ClampedArrayPrototype() {
1453         return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
1454     }
1455 
1456     private synchronized ScriptFunction getBuiltinInt16Array() {
1457         if (this.builtinInt16Array == null) {
1458             this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
1459         }
1460         return this.builtinInt16Array;
1461     }
1462 
1463     ScriptObject getInt16ArrayPrototype() {
1464         return ScriptFunction.getPrototype(getBuiltinInt16Array());
1465     }
1466 
1467     private synchronized ScriptFunction getBuiltinUint16Array() {
1468         if (this.builtinUint16Array == null) {
1469             this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
1470         }
1471         return this.builtinUint16Array;
1472     }
1473 
1474     ScriptObject getUint16ArrayPrototype() {
1475         return ScriptFunction.getPrototype(getBuiltinUint16Array());
1476     }
1477 
1478     private synchronized ScriptFunction getBuiltinInt32Array() {
1479         if (this.builtinInt32Array == null) {
1480             this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
1481         }
1482         return this.builtinInt32Array;
1483     }
1484 
1485     ScriptObject getInt32ArrayPrototype() {
1486         return ScriptFunction.getPrototype(getBuiltinInt32Array());
1487     }
1488 
1489     private synchronized ScriptFunction getBuiltinUint32Array() {
1490         if (this.builtinUint32Array == null) {
1491             this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
1492         }
1493         return this.builtinUint32Array;
1494     }
1495 
1496     ScriptObject getUint32ArrayPrototype() {
1497         return ScriptFunction.getPrototype(getBuiltinUint32Array());
1498     }
1499 
1500     private synchronized ScriptFunction getBuiltinFloat32Array() {
1501         if (this.builtinFloat32Array == null) {
1502             this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
1503         }
1504         return this.builtinFloat32Array;
1505     }
1506 
1507     ScriptObject getFloat32ArrayPrototype() {
1508         return ScriptFunction.getPrototype(getBuiltinFloat32Array());
1509     }
1510 
1511     private synchronized ScriptFunction getBuiltinFloat64Array() {
1512         if (this.builtinFloat64Array == null) {
1513             this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
1514         }
1515         return this.builtinFloat64Array;
1516     }
1517 
1518     ScriptObject getFloat64ArrayPrototype() {
1519         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
1520     }
1521 
1522     private ScriptFunction getBuiltinArray() {
1523         return builtinArray;
1524     }
1525 
1526     ScriptFunction getTypeErrorThrower() {
1527         return typeErrorThrower;
1528     }
1529 
1530     /**
1531      * Called from compiled script code to test if builtin has been overridden
1532      *
1533      * @return true if builtin array has not been overridden
1534      */
1535     public static boolean isBuiltinArray() {
1536         final Global instance = Global.instance();
1537         return instance.array == instance.getBuiltinArray();
1538     }
1539 
1540     private ScriptFunction getBuiltinBoolean() {
1541         return builtinBoolean;
1542     }
1543 
1544     /**
1545      * Called from compiled script code to test if builtin has been overridden
1546      *
1547      * @return true if builtin boolean has not been overridden
1548      */
1549     public static boolean isBuiltinBoolean() {
1550         final Global instance = Global.instance();
1551         return instance._boolean == instance.getBuiltinBoolean();
1552     }
1553 
1554     private synchronized ScriptFunction getBuiltinDate() {
1555         if (this.builtinDate == null) {
1556             this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
1557             final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
1558             // initialize default date
1559             this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
1560         }
1561         return this.builtinDate;
1562     }
1563 
1564     /**
1565      * Called from compiled script code to test if builtin has been overridden
1566      *
1567      * @return true if builtin date has not been overridden
1568      */
1569     public static boolean isBuiltinDate() {
1570         final Global instance = Global.instance();
1571         return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
1572     }
1573 
1574     private ScriptFunction getBuiltinError() {
1575         return builtinError;
1576     }
1577 
1578     /**
1579      * Called from compiled script code to test if builtin has been overridden
1580      *
1581      * @return true if builtin error has not been overridden
1582      */
1583     public static boolean isBuiltinError() {
1584         final Global instance = Global.instance();
1585         return instance.error == instance.getBuiltinError();
1586     }
1587 
1588     private synchronized ScriptFunction getBuiltinEvalError() {
1589         if (this.builtinEvalError == null) {
1590             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
1591         }
1592         return this.builtinEvalError;
1593     }
1594 
1595     /**
1596      * Called from compiled script code to test if builtin has been overridden
1597      *
1598      * @return true if builtin eval error has not been overridden
1599      */
1600     public static boolean isBuiltinEvalError() {
1601         final Global instance = Global.instance();
1602         return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
1603     }
1604 
1605     private ScriptFunction getBuiltinFunction() {
1606         return builtinFunction;
1607     }
1608 
1609     /**
1610      * Called from compiled script code to test if builtin has been overridden
1611      *
1612      * @return true if builtin function has not been overridden
1613      */
1614     public static boolean isBuiltinFunction() {
1615         final Global instance = Global.instance();
1616         return instance.function == instance.getBuiltinFunction();
1617     }
1618 
1619     /**
1620      * Get the switchpoint used to check property changes for Function.prototype.apply
1621      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
1622      */
1623     public static SwitchPoint getBuiltinFunctionApplySwitchPoint() {
1624         return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint();
1625     }
1626 
1627     private static boolean isBuiltinFunctionProperty(final String name) {
1628         final Global instance = Global.instance();
1629         final ScriptFunction builtinFunction = instance.getBuiltinFunction();
1630         if (builtinFunction == null) {
1631             return false; //conservative for compile-only mode
1632         }
1633         final boolean isBuiltinFunction = instance.function == builtinFunction;
1634         return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin();
1635     }
1636 
1637     /**
1638      * Check if the Function.prototype.apply has not been replaced
1639      * @return true if Function.prototype.apply has been replaced
1640      */
1641     public static boolean isBuiltinFunctionPrototypeApply() {
1642         return isBuiltinFunctionProperty("apply");
1643     }
1644 
1645     /**
1646      * Check if the Function.prototype.apply has not been replaced
1647      * @return true if Function.prototype.call has been replaced
1648      */
1649     public static boolean isBuiltinFunctionPrototypeCall() {
1650         return isBuiltinFunctionProperty("call");
1651     }
1652 
1653     private synchronized ScriptFunction getBuiltinJSAdapter() {
1654         if (this.builtinJSAdapter == null) {
1655             this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
1656         }
1657         return builtinJSAdapter;
1658     }
1659 
1660     /**
1661      * Called from compiled script code to test if builtin has been overridden
1662      *
1663      * @return true if builtin JSAdapter has not been overridden
1664      */
1665     public static boolean isBuiltinJSAdapter() {
1666         final Global instance = Global.instance();
1667         return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
1668     }
1669 
1670     private synchronized ScriptObject getBuiltinJSON() {
1671         if (this.builtinJSON == null) {
1672             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
1673         }
1674         return this.builtinJSON;
1675     }
1676 
1677     /**
1678      * Called from compiled script code to test if builtin has been overridden
1679      *
1680      * @return true if builtin JSON has has not been overridden
1681      */
1682     public static boolean isBuiltinJSON() {
1683         final Global instance = Global.instance();
1684         return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
1685     }
1686 
1687     private ScriptObject getBuiltinJava() {
1688         return builtinJava;
1689     }
1690 
1691     /**
1692      * Called from compiled script code to test if builtin has been overridden
1693      *
1694      * @return true if builtin Java has not been overridden
1695      */
1696     public static boolean isBuiltinJava() {
1697         final Global instance = Global.instance();
1698         return instance.java == instance.getBuiltinJava();
1699     }
1700 
1701     private ScriptObject getBuiltinJavax() {
1702         return builtinJavax;
1703     }
1704 
1705     /**
1706      * Called from compiled script code to test if builtin has been overridden
1707      *
1708      * @return true if builtin Javax has not been overridden
1709      */
1710     public static boolean isBuiltinJavax() {
1711         final Global instance = Global.instance();
1712         return instance.javax == instance.getBuiltinJavax();
1713     }
1714 
1715     private synchronized ScriptFunction getBuiltinJavaImporter() {
1716         if (this.builtinJavaImporter == null) {
1717             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
1718         }
1719         return this.builtinJavaImporter;
1720     }
1721 
1722     private synchronized ScriptObject getBuiltinJavaApi() {
1723         if (this.builtinJavaApi == null) {
1724             this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
1725         }
1726         return this.builtinJavaApi;
1727     }
1728 
1729     /**
1730      * Called from compiled script code to test if builtin has been overridden
1731      *
1732      * @return true if builtin Java importer has not been overridden
1733      */
1734     public static boolean isBuiltinJavaImporter() {
1735         final Global instance = Global.instance();
1736         return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
1737     }
1738 
1739     /**
1740      * Called from compiled script code to test if builtin has been overridden
1741      *
1742      * @return true if builtin math has not been overridden
1743      */
1744     public static boolean isBuiltinMath() {
1745         final Global instance = Global.instance();
1746         return instance.math == instance.builtinMath;
1747     }
1748 
1749     private ScriptFunction getBuiltinNumber() {
1750         return builtinNumber;
1751     }
1752 
1753     /**
1754      * Called from compiled script code to test if builtin has been overridden
1755      *
1756      * @return true if builtin number has not been overridden
1757      */
1758     public static boolean isBuiltinNumber() {
1759         final Global instance = Global.instance();
1760         return instance.number == instance.getBuiltinNumber();
1761     }
1762 
1763     private ScriptFunction getBuiltinObject() {
1764         return builtinObject;
1765     }
1766 
1767     /**
1768      * Called from compiled script code to test if builtin has been overridden
1769      *
1770      * @return true if builtin object has not been overridden
1771      */
1772     public static boolean isBuiltinObject() {
1773         final Global instance = Global.instance();
1774         return instance.object == instance.getBuiltinObject();
1775     }
1776 
1777     private ScriptObject getBuiltinPackages() {
1778         return builtinPackages;
1779     }
1780 
1781     /**
1782      * Called from compiled script code to test if builtin has been overridden
1783      *
1784      * @return true if builtin package has not been overridden
1785      */
1786     public static boolean isBuiltinPackages() {
1787         final Global instance = Global.instance();
1788         return instance.packages == instance.getBuiltinPackages();
1789     }
1790 
1791     private synchronized ScriptFunction getBuiltinRangeError() {
1792         if (this.builtinRangeError == null) {
1793             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
1794         }
1795         return builtinRangeError;
1796     }
1797 
1798     /**
1799      * Called from compiled script code to test if builtin has been overridden
1800      *
1801      * @return true if builtin range error has not been overridden
1802      */
1803     public static boolean isBuiltinRangeError() {
1804         final Global instance = Global.instance();
1805         return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
1806     }
1807 
1808     private synchronized ScriptFunction getBuiltinReferenceError() {
1809         return builtinReferenceError;
1810     }
1811 
1812     /**
1813      * Called from compiled script code to test if builtin has been overridden
1814      *
1815      * @return true if builtin reference error has not been overridden
1816      */
1817     public static boolean isBuiltinReferenceError() {
1818         final Global instance = Global.instance();
1819         return instance.referenceError == instance.getBuiltinReferenceError();
1820     }
1821 
1822     private synchronized ScriptFunction getBuiltinRegExp() {
1823         if (this.builtinRegExp == null) {
1824             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
1825             final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
1826             // initialize default regexp object
1827             this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
1828             // RegExp.prototype should behave like a RegExp object. So copy the
1829             // properties.
1830             regExpProto.addBoundProperties(DEFAULT_REGEXP);
1831         }
1832         return builtinRegExp;
1833     }
1834 
1835     /**
1836      * Called from compiled script code to test if builtin has been overridden
1837      *
1838      * @return true if builtin regexp has not been overridden
1839      */
1840     public static boolean isBuiltinRegExp() {
1841         final Global instance = Global.instance();
1842         return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
1843     }
1844 
1845     private ScriptFunction getBuiltinString() {
1846         return builtinString;
1847     }
1848 
1849     /**
1850      * Called from compiled script code to test if builtin has been overridden
1851      *
1852      * @return true if builtin Java has not been overridden
1853      */
1854     public static boolean isBuiltinString() {
1855         final Global instance = Global.instance();
1856         return instance.string == instance.getBuiltinString();
1857     }
1858 
1859     private ScriptFunction getBuiltinSyntaxError() {
1860         return builtinSyntaxError;
1861     }
1862 
1863     /**
1864      * Called from compiled script code to test if builtin has been overridden
1865      *
1866      * @return true if builtin syntax error has not been overridden
1867      */
1868     public static boolean isBuiltinSyntaxError() {
1869         final Global instance = Global.instance();
1870         return instance.syntaxError == instance.getBuiltinSyntaxError();
1871     }
1872 
1873     private ScriptFunction getBuiltinTypeError() {
1874         return builtinTypeError;
1875     }
1876 
1877     /**
1878      * Called from compiled script code to test if builtin has been overridden
1879      *
1880      * @return true if builtin type error has not been overridden
1881      */
1882     public static boolean isBuiltinTypeError() {
1883         final Global instance = Global.instance();
1884         return instance.typeError == instance.getBuiltinTypeError();
1885     }
1886 
1887     private synchronized ScriptFunction getBuiltinURIError() {
1888         if (this.builtinURIError == null) {
1889             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
1890         }
1891         return this.builtinURIError;
1892     }
1893 
1894     /**
1895      * Called from compiled script code to test if builtin has been overridden
1896      *
1897      * @return true if builtin URI error has not been overridden
1898      */
1899     public static boolean isBuiltinURIError() {
1900         final Global instance = Global.instance();
1901         return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
1902     }
1903 
1904     @Override
1905     public String getClassName() {
1906         return "global";
1907     }
1908 
1909     /**
1910      * Copy function used to clone NativeRegExp objects.
1911      *
1912      * @param regexp a NativeRegExp to clone
1913      *
1914      * @return copy of the given regexp object
1915      */
1916     public static Object regExpCopy(final Object regexp) {
1917         return new NativeRegExp((NativeRegExp)regexp);
1918     }
1919 
1920     /**
1921      * Convert given object to NativeRegExp type.
1922      *
1923      * @param obj object to be converted
1924      * @return NativeRegExp instance
1925      */
1926     public static NativeRegExp toRegExp(final Object obj) {
1927         if (obj instanceof NativeRegExp) {
1928             return (NativeRegExp)obj;
1929         }
1930         return new NativeRegExp(JSType.toString(obj));
1931     }
1932 
1933     /**
1934      * ECMA 9.9 ToObject implementation
1935      *
1936      * @param obj  an item for which to run ToObject
1937      * @return ToObject version of given item
1938      */
1939     public static Object toObject(final Object obj) {
1940         if (obj == null || obj == UNDEFINED) {
1941             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
1942         }
1943 
1944         if (obj instanceof ScriptObject) {
1945             return obj;
1946         }
1947 
1948         return instance().wrapAsObject(obj);
1949     }
1950 
1951     /**
1952      * Allocate a new object array.
1953      *
1954      * @param initial object values.
1955      * @return the new array
1956      */
1957     public static NativeArray allocate(final Object[] initial) {
1958         ArrayData arrayData = ArrayData.allocate(initial);
1959 
1960         for (int index = 0; index < initial.length; index++) {
1961             final Object value = initial[index];
1962 
1963             if (value == ScriptRuntime.EMPTY) {
1964                 arrayData = arrayData.delete(index);
1965             }
1966         }
1967 
1968         return new NativeArray(arrayData);
1969     }
1970 
1971     /**
1972      * Allocate a new number array.
1973      *
1974      * @param initial number values.
1975      * @return the new array
1976      */
1977     public static NativeArray allocate(final double[] initial) {
1978         return new NativeArray(ArrayData.allocate(initial));
1979     }
1980 
1981     /**
1982      * Allocate a new long array.
1983      *
1984      * @param initial number values.
1985      * @return the new array
1986      */
1987     public static NativeArray allocate(final long[] initial) {
1988         return new NativeArray(ArrayData.allocate(initial));
1989     }
1990 
1991     /**
1992      * Allocate a new integer array.
1993      *
1994      * @param initial number values.
1995      * @return the new array
1996      */
1997     public static NativeArray allocate(final int[] initial) {
1998         return new NativeArray(ArrayData.allocate(initial));
1999     }
2000 
2001     /**
2002      * Allocate a new object array for arguments.
2003      *
2004      * @param arguments initial arguments passed.
2005      * @param callee reference to the function that uses arguments object
2006      * @param numParams actual number of declared parameters
2007      *
2008      * @return the new array
2009      */
2010     public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) {
2011         return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams);
2012     }
2013 
2014     /**
2015      * Called from generated to check if given function is the builtin 'eval'. If
2016      * eval is used in a script, a lot of optimizations and assumptions cannot be done.
2017      *
2018      * @param  fn function object that is checked
2019      * @return true if fn is the builtin eval
2020      */
2021     public static boolean isEval(final Object fn) {
2022         return fn == Global.instance().builtinEval;
2023     }
2024 
2025     /**
2026      * Called from generated to replace a location property placeholder with the actual location property value.
2027      *
2028      * @param  placeholder the value tested for being a placeholder for a location property
2029      * @param  locationProperty the actual value for the location property
2030      * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
2031      */
2032     public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
2033         return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
2034     }
2035 
2036     /**
2037      * Called from runtime internals to check if the passed value is a location property placeholder.
2038      * @param  placeholder the value tested for being a placeholder for a location property
2039      * @return true if the value is a placeholder, false otherwise.
2040      */
2041     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
2042         return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
2043     }
2044 
2045     /**
2046      * Create a new RegExp object.
2047      *
2048      * @param expression Regular expression.
2049      * @param options    Search options.
2050      *
2051      * @return New RegExp object.
2052      */
2053     public static Object newRegExp(final String expression, final String options) {
2054         if (options == null) {
2055             return new NativeRegExp(expression);
2056         }
2057         return new NativeRegExp(expression, options);
2058     }
2059 
2060     /**
2061      * Get the object prototype
2062      *
2063      * @return the object prototype
2064      */
2065     public static ScriptObject objectPrototype() {
2066         return Global.instance().getObjectPrototype();
2067     }
2068 
2069     /**
2070      * Create a new empty object instance.
2071      *
2072      * @return New empty object.
2073      */
2074     public static ScriptObject newEmptyInstance() {
2075         return Global.instance().newObject();
2076     }
2077 
2078     /**
2079      * Check if a given object is a ScriptObject, raises an exception if this is
2080      * not the case
2081      *
2082      * @param obj and object to check
2083      * @return the script object
2084      */
2085     public static ScriptObject checkObject(final Object obj) {
2086         if (!(obj instanceof ScriptObject)) {
2087             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2088         }
2089         return (ScriptObject)obj;
2090     }
2091 
2092     /**
2093      * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception
2094      * if this object is null or undefined.
2095      *
2096      * @param obj an object to check
2097      */
2098     public static void checkObjectCoercible(final Object obj) {
2099         if (obj == null || obj == UNDEFINED) {
2100             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
2101         }
2102     }
2103 
2104     /**
2105      * Get the current split state.
2106      *
2107      * @return current split state
2108      */
2109     @Override
2110     public int getSplitState() {
2111         return splitState;
2112     }
2113 
2114     /**
2115      * Set the current split state.
2116      *
2117      * @param state current split state
2118      */
2119     @Override
2120     public void setSplitState(final int state) {
2121         splitState = state;
2122     }
2123 
2124     /**
2125      * Return the ES6 global scope for lexically declared bindings.
2126      * @return the ES6 lexical global scope.
2127      */
2128     public final ScriptObject getLexicalScope() {
2129         assert context.getEnv()._es6;
2130         return lexicalScope;
2131     }
2132 
2133     @Override
2134     public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
2135         PropertyMap ownMap = getMap();
2136         LexicalScope lexicalScope = null;
2137         PropertyMap lexicalMap = null;
2138         boolean hasLexicalDefinitions = false;
2139 
2140         if (context.getEnv()._es6) {
2141             lexicalScope = (LexicalScope) getLexicalScope();
2142             lexicalMap = lexicalScope.getMap();
2143 
2144             for (final jdk.nashorn.internal.runtime.Property property : properties) {
2145                 if (property.isLexicalBinding()) {
2146                     hasLexicalDefinitions = true;
2147                 }
2148                 // ES6 15.1.8 steps 6. and 7.
2149                 final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
2150                 if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
2151                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2152                 }
2153                 final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
2154                 if (lexicalProperty != null && !property.isConfigurable()) {
2155                     throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
2156                 }
2157             }
2158         }
2159 
2160         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2161             if (property.isLexicalBinding()) {
2162                 assert lexicalScope != null;
2163                 lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
2164 
2165                 if (ownMap.findProperty(property.getKey()) != null) {
2166                     // If property exists in the global object invalidate any global constant call sites.
2167                     invalidateGlobalConstant(property.getKey());
2168                 }
2169             } else {
2170                 ownMap = addBoundProperty(ownMap, source, property);
2171             }
2172         }
2173 
2174         setMap(ownMap);
2175 
2176         if (hasLexicalDefinitions) {
2177             lexicalScope.setMap(lexicalMap);
2178             invalidateLexicalSwitchPoint();
2179         }
2180     }
2181 
2182     @Override
2183     public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2184         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2185         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2186 
2187         if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
2188             if (lexicalScope.hasOwnProperty(name)) {
2189                 return lexicalScope.findGetMethod(desc, request, operator);
2190             }
2191         }
2192 
2193         final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
2194 
2195         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
2196         // because those are invalidated per-key in the addBoundProperties method above.
2197         // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
2198         // assuming this only applies to global constants. If other non-inherited properties will
2199         // start using switchpoints some time in the future we'll have to revisit this.
2200         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
2201             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2202         }
2203 
2204         return invocation;
2205     }
2206 
2207     @Override
2208     protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
2209         if (lexicalScope != null && start != this && start.isScope()) {
2210             final FindProperty find = lexicalScope.findProperty(key, false);
2211             if (find != null) {
2212                 return find;
2213             }
2214         }
2215         return super.findProperty(key, deep, start);
2216     }
2217 
2218     @Override
2219     public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2220         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
2221 
2222         if (lexicalScope != null && isScope) {
2223             final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
2224             if (lexicalScope.hasOwnProperty(name)) {
2225                 return lexicalScope.findSetMethod(desc, request);
2226             }
2227         }
2228 
2229         final GuardedInvocation invocation = super.findSetMethod(desc, request);
2230 
2231         if (isScope && context.getEnv()._es6) {
2232             return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
2233         }
2234 
2235         return invocation;
2236     }
2237 
2238     /**
2239      * Adds jjs shell interactive mode builtin functions to global scope.
2240      */
2241     public void addShellBuiltins() {
2242         Object value = ScriptFunctionImpl.makeFunction("input", ShellFunctions.INPUT);
2243         addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
2244 
2245         value = ScriptFunctionImpl.makeFunction("evalinput", ShellFunctions.EVALINPUT);
2246         addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
2247     }
2248 
2249     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
2250         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
2251         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
2252             switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
2253         }
2254         return switchPoint;
2255     }
2256 
2257     private synchronized void invalidateLexicalSwitchPoint() {
2258         if (lexicalScopeSwitchPoint != null) {
2259             context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
2260             SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
2261         }
2262     }
2263 
2264 
2265     @SuppressWarnings("unused")
2266     private static Object lexicalScopeFilter(final Object self) {
2267         if (self instanceof Global) {
2268             return ((Global) self).getLexicalScope();
2269         }
2270         return self;
2271     }
2272 
2273     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
2274         final T func = initConstructor(name, clazz);
2275         tagBuiltinProperties(name, func);
2276         return func;
2277     }
2278 
2279     private void init(final ScriptEngine eng) {
2280         assert Context.getGlobal() == this : "this global is not set as current";
2281 
2282         final ScriptEnvironment env = getContext().getEnv();
2283 
2284         // initialize Function and Object constructor
2285         initFunctionAndObject();
2286 
2287         // Now fix Global's own proto.
2288         this.setInitialProto(getObjectPrototype());
2289 
2290         // initialize global function properties
2291         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
2292 
2293         this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
2294                     new Specialization[] {
2295                     new Specialization(GlobalFunctions.PARSEINT_Z),
2296                     new Specialization(GlobalFunctions.PARSEINT_I),
2297                     new Specialization(GlobalFunctions.PARSEINT_J),
2298                     new Specialization(GlobalFunctions.PARSEINT_OI),
2299                     new Specialization(GlobalFunctions.PARSEINT_O) });
2300         this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2301         this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
2302                    new Specialization[] {
2303                         new Specialization(GlobalFunctions.IS_NAN_I),
2304                         new Specialization(GlobalFunctions.IS_NAN_J),
2305                         new Specialization(GlobalFunctions.IS_NAN_D) });
2306         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
2307         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
2308         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
2309         this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
2310         this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
2311         this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
2312         this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
2313         this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
2314         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
2315         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
2316         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
2317         this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
2318         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
2319         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
2320 
2321         // built-in constructors
2322         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
2323         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
2324         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
2325         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
2326         this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
2327 
2328         // initialize String.prototype.length to 0
2329         // add String.prototype.length
2330         final ScriptObject stringPrototype = getStringPrototype();
2331         stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0);
2332 
2333         // set isArray flag on Array.prototype
2334         final ScriptObject arrayPrototype = getArrayPrototype();
2335         arrayPrototype.setIsArray();
2336 
2337         // Error stuff
2338         initErrorObjects();
2339 
2340         // java access
2341         if (! env._no_java) {
2342             this.javaApi = LAZY_SENTINEL;
2343             this.javaImporter = LAZY_SENTINEL;
2344             initJavaAccess();
2345         }
2346 
2347         if (! env._no_typed_arrays) {
2348             this.arrayBuffer       = LAZY_SENTINEL;
2349             this.dataView          = LAZY_SENTINEL;
2350             this.int8Array         = LAZY_SENTINEL;
2351             this.uint8Array        = LAZY_SENTINEL;
2352             this.uint8ClampedArray = LAZY_SENTINEL;
2353             this.int16Array        = LAZY_SENTINEL;
2354             this.uint16Array       = LAZY_SENTINEL;
2355             this.int32Array        = LAZY_SENTINEL;
2356             this.uint32Array       = LAZY_SENTINEL;
2357             this.float32Array      = LAZY_SENTINEL;
2358             this.float64Array      = LAZY_SENTINEL;
2359         }
2360 
2361         if (env._scripting) {
2362             initScripting(env);
2363         }
2364 
2365         if (Context.DEBUG) {
2366             boolean debugOkay;
2367             final SecurityManager sm = System.getSecurityManager();
2368             if (sm != null) {
2369                 try {
2370                     sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
2371                     debugOkay = true;
2372                 } catch (final SecurityException ignored) {
2373                     // if no permission, don't initialize Debug object
2374                     debugOkay = false;
2375                 }
2376 
2377             } else {
2378                 debugOkay = true;
2379             }
2380 
2381             if (debugOkay) {
2382                 initDebug();
2383             }
2384         }
2385 
2386         copyBuiltins();
2387 
2388         // expose script (command line) arguments as "arguments" property of global
2389         arguments = wrapAsObject(env.getArguments().toArray());
2390         if (env._scripting) {
2391             // synonym for "arguments" in scripting mode
2392             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
2393         }
2394 
2395         if (eng != null) {
2396             // default file name
2397             addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
2398             // __noSuchProperty__ hook for ScriptContext search of missing variables
2399             final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
2400             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
2401         }
2402     }
2403 
2404     private void initErrorObjects() {
2405         // Error objects
2406         this.builtinError = initConstructor("Error", ScriptFunction.class);
2407         final ScriptObject errorProto = getErrorPrototype();
2408 
2409         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
2410         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
2411         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
2412         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
2413         final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
2414         final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
2415         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
2416         final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
2417         final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
2418         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
2419         final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
2420         final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
2421         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
2422 
2423         // ECMA 15.11.4.2 Error.prototype.name
2424         // Error.prototype.name = "Error";
2425         errorProto.set(NativeError.NAME, "Error", 0);
2426         // ECMA 15.11.4.3 Error.prototype.message
2427         // Error.prototype.message = "";
2428         errorProto.set(NativeError.MESSAGE, "", 0);
2429 
2430         tagBuiltinProperties("Error", builtinError);
2431 
2432         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
2433         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
2434         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
2435     }
2436 
2437     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
2438         final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
2439         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
2440         prototype.set(NativeError.NAME, name, 0);
2441         prototype.set(NativeError.MESSAGE, "", 0);
2442         prototype.setInitialProto(errorProto);
2443         tagBuiltinProperties(name, cons);
2444         return cons;
2445     }
2446 
2447     private void initJavaAccess() {
2448         final ScriptObject objectProto = getObjectPrototype();
2449         this.builtinPackages = new NativeJavaPackage("", objectProto);
2450         this.builtinCom = new NativeJavaPackage("com", objectProto);
2451         this.builtinEdu = new NativeJavaPackage("edu", objectProto);
2452         this.builtinJava = new NativeJavaPackage("java", objectProto);
2453         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
2454         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
2455         this.builtinOrg = new NativeJavaPackage("org", objectProto);
2456     }
2457 
2458     private void initScripting(final ScriptEnvironment scriptEnv) {
2459         Object value;
2460         value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
2461         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
2462 
2463         value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
2464         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
2465 
2466         final String execName = ScriptingFunctions.EXEC_NAME;
2467         value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
2468         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
2469 
2470         // Nashorn extension: global.echo (scripting-mode-only)
2471         // alias for "print"
2472         value = get("print");
2473         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
2474 
2475         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
2476         final ScriptObject options = newObject();
2477         copyOptions(options, scriptEnv);
2478         addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
2479 
2480         // Nashorn extension: global.$ENV (scripting-mode-only)
2481         if (System.getSecurityManager() == null) {
2482             // do not fill $ENV if we have a security manager around
2483             // Retrieve current state of ENV variables.
2484             final ScriptObject env = newObject();
2485             env.putAll(System.getenv(), scriptEnv._strict);
2486             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
2487         } else {
2488             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2489         }
2490 
2491         // add other special properties for exec support
2492         addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2493         addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2494         addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
2495     }
2496 
2497     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
2498         for (final Field f : scriptEnv.getClass().getFields()) {
2499             try {
2500                 options.set(f.getName(), f.get(scriptEnv), 0);
2501             } catch (final IllegalArgumentException | IllegalAccessException exp) {
2502                 throw new RuntimeException(exp);
2503             }
2504         }
2505     }
2506 
2507     private void copyBuiltins() {
2508         this.array             = this.builtinArray;
2509         this._boolean          = this.builtinBoolean;
2510         this.error             = this.builtinError;
2511         this.function          = this.builtinFunction;
2512         this.com               = this.builtinCom;
2513         this.edu               = this.builtinEdu;
2514         this.java              = this.builtinJava;
2515         this.javafx            = this.builtinJavafx;
2516         this.javax             = this.builtinJavax;
2517         this.org               = this.builtinOrg;
2518         this.math              = this.builtinMath;
2519         this.number            = this.builtinNumber;
2520         this.object            = this.builtinObject;
2521         this.packages          = this.builtinPackages;
2522         this.referenceError    = this.builtinReferenceError;
2523         this.string            = this.builtinString;
2524         this.syntaxError       = this.builtinSyntaxError;
2525         this.typeError         = this.builtinTypeError;
2526     }
2527 
2528     private void initDebug() {
2529         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
2530     }
2531 
2532     private Object printImpl(final boolean newLine, final Object... objects) {
2533         @SuppressWarnings("resource")
2534         final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
2535         final StringBuilder sb = new StringBuilder();
2536 
2537         for (final Object obj : objects) {
2538             if (sb.length() != 0) {
2539                 sb.append(' ');
2540             }
2541 
2542             sb.append(JSType.toString(obj));
2543         }
2544 
2545         // Print all at once to ensure thread friendly result.
2546         if (newLine) {
2547             out.println(sb.toString());
2548         } else {
2549             out.print(sb.toString());
2550         }
2551 
2552         out.flush();
2553 
2554         return UNDEFINED;
2555     }
2556 
2557     private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
2558         try {
2559             // Assuming class name pattern for built-in JS constructors.
2560             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
2561 
2562             sb.append("Native");
2563             sb.append(name);
2564             sb.append("$Constructor");
2565 
2566             final Class<?> funcClass = Class.forName(sb.toString());
2567             final T res = clazz.cast(funcClass.newInstance());
2568 
2569             if (res instanceof ScriptFunction) {
2570                 // All global constructor prototypes are not-writable,
2571                 // not-enumerable and not-configurable.
2572                 final ScriptFunction func = (ScriptFunction)res;
2573                 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT);
2574             }
2575 
2576             if (res.getProto() == null) {
2577                 res.setInitialProto(getObjectPrototype());
2578             }
2579 
2580             res.setIsBuiltin();
2581 
2582             return res;
2583         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
2584             throw new RuntimeException(e);
2585         }
2586     }
2587 
2588     private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) {
2589         final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>();
2590 
2591         list.addAll(Arrays.asList(func.getMap().getProperties()));
2592 
2593         if (func instanceof ScriptFunction) {
2594             final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func);
2595             if (proto != null) {
2596                 list.addAll(Arrays.asList(proto.getMap().getProperties()));
2597             }
2598         }
2599 
2600         final jdk.nashorn.internal.runtime.Property prop = getProperty(name);
2601         if (prop != null) {
2602             list.add(prop);
2603         }
2604 
2605         return list;
2606     }
2607 
2608     /**
2609      * Given a builtin object, traverse its properties recursively and associate them with a name that
2610      * will be a key to their invalidation switchpoint.
2611      * @param name name for key
2612      * @param func builtin script object
2613      */
2614     private void tagBuiltinProperties(final String name, final ScriptObject func) {
2615         SwitchPoint sp = context.getBuiltinSwitchPoint(name);
2616         if (sp == null) {
2617             sp = context.newBuiltinSwitchPoint(name);
2618         }
2619 
2620         //get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
2621         //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
2622         for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
2623             prop.setBuiltinSwitchPoint(sp);
2624         }
2625     }
2626 
2627     // Function and Object constructors are inter-dependent. Also,
2628     // Function.prototype
2629     // functions are not properly initialized. We fix the references here.
2630     // NOTE: be careful if you want to re-order the operations here. You may
2631     // have
2632     // to play with object references carefully!!
2633     private void initFunctionAndObject() {
2634         // First-n-foremost is Function
2635 
2636         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
2637 
2638         // create global anonymous function
2639         final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
2640         // need to copy over members of Function.prototype to anon function
2641         anon.addBoundProperties(getFunctionPrototype());
2642 
2643         // Function.prototype === Object.getPrototypeOf(Function) ===
2644         // <anon-function>
2645         builtinFunction.setInitialProto(anon);
2646         builtinFunction.setPrototype(anon);
2647         anon.set("constructor", builtinFunction, 0);
2648         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
2649 
2650         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
2651         this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
2652         typeErrorThrower.setPrototype(UNDEFINED);
2653         // Non-constructor built-in functions do not have "prototype" property
2654         typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
2655         typeErrorThrower.preventExtensions();
2656 
2657         // now initialize Object
2658         this.builtinObject = initConstructor("Object", ScriptFunction.class);
2659         final ScriptObject ObjectPrototype = getObjectPrototype();
2660         // Object.getPrototypeOf(Function.prototype) === Object.prototype
2661         anon.setInitialProto(ObjectPrototype);
2662 
2663         // ES6 draft compliant __proto__ property of Object.prototype
2664         // accessors on Object.prototype for "__proto__"
2665         final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
2666         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
2667         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
2668 
2669         // Function valued properties of Function.prototype were not properly
2670         // initialized. Because, these were created before global.function and
2671         // global.object were not initialized.
2672         jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties();
2673         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2674             final Object key = property.getKey();
2675             final Object value = builtinFunction.get(key);
2676 
2677             if (value instanceof ScriptFunction && value != anon) {
2678                 final ScriptFunction func = (ScriptFunction)value;
2679                 func.setInitialProto(getFunctionPrototype());
2680                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2681                 if (prototype != null) {
2682                     prototype.setInitialProto(ObjectPrototype);
2683                 }
2684             }
2685         }
2686 
2687         // For function valued properties of Object and Object.prototype, make
2688         // sure prototype's proto chain ends with Object.prototype
2689         for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) {
2690             final Object key = property.getKey();
2691             final Object value = builtinObject.get(key);
2692 
2693             if (value instanceof ScriptFunction) {
2694                 final ScriptFunction func = (ScriptFunction)value;
2695                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2696                 if (prototype != null) {
2697                     prototype.setInitialProto(ObjectPrototype);
2698                 }
2699             }
2700         }
2701 
2702         properties = getObjectPrototype().getMap().getProperties();
2703 
2704         for (final jdk.nashorn.internal.runtime.Property property : properties) {
2705             final Object key   = property.getKey();
2706             if (key.equals("constructor")) {
2707                 continue;
2708             }
2709 
2710             final Object value = ObjectPrototype.get(key);
2711             if (value instanceof ScriptFunction) {
2712                 final ScriptFunction func = (ScriptFunction)value;
2713                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
2714                 if (prototype != null) {
2715                     prototype.setInitialProto(ObjectPrototype);
2716                 }
2717             }
2718         }
2719 
2720         tagBuiltinProperties("Object", builtinObject);
2721         tagBuiltinProperties("Function", builtinFunction);
2722         tagBuiltinProperties("Function", anon);
2723     }
2724 
2725     private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
2726         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
2727     }
2728 
2729     RegExpResult getLastRegExpResult() {
2730         return lastRegExpResult;
2731     }
2732 
2733     void setLastRegExpResult(final RegExpResult regExpResult) {
2734         this.lastRegExpResult = regExpResult;
2735     }
2736 
2737     @Override
2738     protected boolean isGlobal() {
2739         return true;
2740     }
2741 
2742     /**
2743      * A class representing the ES6 global lexical scope.
2744      */
2745     private static class LexicalScope extends ScriptObject {
2746 
2747         LexicalScope(final ScriptObject proto) {
2748             super(proto, PropertyMap.newMap());
2749         }
2750 
2751         @Override
2752         protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
2753             return filterInvocation(super.findGetMethod(desc, request, operator));
2754         }
2755 
2756         @Override
2757         protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
2758             return filterInvocation(super.findSetMethod(desc, request));
2759         }
2760 
2761         @Override
2762         protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
2763             // We override this method just to make it callable by Global
2764             return super.addBoundProperty(propMap, source, property);
2765         }
2766 
2767         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
2768             final MethodType type = invocation.getInvocation().type();
2769             return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
2770         }
2771     }
2772 
2773 }
--- EOF ---