Global.java revision 1015:8a4af0397070
150120Swpaul/* 250120Swpaul * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 350120Swpaul * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 450120Swpaul * 550120Swpaul * This code is free software; you can redistribute it and/or modify it 650120Swpaul * under the terms of the GNU General Public License version 2 only, as 750120Swpaul * published by the Free Software Foundation. Oracle designates this 850120Swpaul * particular file as subject to the "Classpath" exception as provided 950120Swpaul * by Oracle in the LICENSE file that accompanied this code. 1050120Swpaul * 1150120Swpaul * This code is distributed in the hope that it will be useful, but WITHOUT 1250120Swpaul * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1350120Swpaul * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1450120Swpaul * version 2 for more details (a copy is included in the LICENSE file that 1550120Swpaul * accompanied this code). 1650120Swpaul * 1750120Swpaul * You should have received a copy of the GNU General Public License version 1850120Swpaul * 2 along with this work; if not, write to the Free Software Foundation, 1950120Swpaul * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2050120Swpaul * 2150120Swpaul * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2250120Swpaul * or visit www.oracle.com if you need additional information or have any 2350120Swpaul * questions. 2450120Swpaul */ 2550120Swpaul 2650120Swpaulpackage jdk.nashorn.internal.objects; 2750120Swpaul 2850120Swpaulimport static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 2950120Swpaulimport static jdk.nashorn.internal.lookup.Lookup.MH; 3050120Swpaulimport static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; 3150120Swpaulimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 3250120Swpaulimport static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 3350120Swpaul 3450120Swpaulimport java.io.IOException; 3550120Swpaulimport java.io.PrintWriter; 3650120Swpaulimport java.lang.invoke.CallSite; 3750120Swpaulimport java.lang.invoke.ConstantCallSite; 3850120Swpaulimport java.lang.invoke.MethodHandle; 3950120Swpaulimport java.lang.invoke.MethodHandles; 4050120Swpaulimport java.lang.invoke.MethodType; 4150120Swpaulimport java.lang.invoke.SwitchPoint; 4250120Swpaulimport java.lang.reflect.Field; 4350120Swpaulimport java.util.Arrays; 4450120Swpaulimport java.util.HashMap; 4550120Swpaulimport java.util.Map; 4650120Swpaulimport java.util.concurrent.Callable; 4750120Swpaulimport java.util.concurrent.ConcurrentHashMap; 4850120Swpaulimport java.util.concurrent.atomic.AtomicReference; 4950120Swpaulimport javax.script.ScriptContext; 5050120Swpaulimport javax.script.ScriptEngine; 5150120Swpaulimport jdk.internal.dynalink.linker.GuardedInvocation; 5250120Swpaulimport jdk.internal.dynalink.linker.LinkRequest; 5350120Swpaulimport jdk.nashorn.api.scripting.ClassFilter; 5450120Swpaulimport jdk.nashorn.api.scripting.ScriptObjectMirror; 5550120Swpaulimport jdk.nashorn.internal.codegen.ApplySpecialization; 5650120Swpaulimport jdk.nashorn.internal.codegen.CompilerConstants.Call; 5750120Swpaulimport jdk.nashorn.internal.lookup.Lookup; 5850120Swpaulimport jdk.nashorn.internal.objects.annotations.Attribute; 5950120Swpaulimport jdk.nashorn.internal.objects.annotations.Property; 6050120Swpaulimport jdk.nashorn.internal.objects.annotations.ScriptClass; 6150120Swpaulimport jdk.nashorn.internal.runtime.ConsString; 6250120Swpaulimport jdk.nashorn.internal.runtime.Context; 6350120Swpaulimport jdk.nashorn.internal.runtime.GlobalConstants; 6450120Swpaulimport jdk.nashorn.internal.runtime.GlobalFunctions; 6550120Swpaulimport jdk.nashorn.internal.runtime.JSType; 6650120Swpaulimport jdk.nashorn.internal.runtime.NativeJavaPackage; 6750120Swpaulimport jdk.nashorn.internal.runtime.PropertyDescriptor; 6850120Swpaulimport jdk.nashorn.internal.runtime.PropertyMap; 6950120Swpaulimport jdk.nashorn.internal.runtime.Scope; 7050120Swpaulimport jdk.nashorn.internal.runtime.ScriptEnvironment; 7150120Swpaulimport jdk.nashorn.internal.runtime.ScriptFunction; 7250120Swpaulimport jdk.nashorn.internal.runtime.ScriptObject; 7350120Swpaulimport jdk.nashorn.internal.runtime.ScriptRuntime; 7450120Swpaulimport jdk.nashorn.internal.runtime.ScriptingFunctions; 7550120Swpaulimport jdk.nashorn.internal.runtime.arrays.ArrayData; 7650120Swpaulimport jdk.nashorn.internal.runtime.linker.Bootstrap; 7750120Swpaulimport jdk.nashorn.internal.runtime.linker.InvokeByName; 7850120Swpaulimport jdk.nashorn.internal.runtime.regexp.RegExpResult; 7950120Swpaulimport jdk.nashorn.internal.scripts.JO; 8050120Swpaul 8150120Swpaul/** 8250120Swpaul * Representation of global scope. 8350120Swpaul */ 8450120Swpaul@ScriptClass("Global") 8550120Swpaulpublic final class Global extends ScriptObject implements Scope { 8650120Swpaul // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__) 8750120Swpaul private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object(); 8850120Swpaul private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 8950120Swpaul private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); 9050120Swpaul 9150120Swpaul /** 9250120Swpaul * Optimistic builtin names that require switchpoint invalidation 9350120Swpaul * upon assignment. Overly conservative, but works for now, to avoid 9450120Swpaul * any complicated scope checks and especially heavy weight guards 9550120Swpaul * like 9650120Swpaul * 9750120Swpaul * <pre> 9850120Swpaul * public boolean setterGuard(final Object receiver) { 9950120Swpaul * final Global global = Global.instance(); 10050120Swpaul * final ScriptObject sobj = global.getFunctionPrototype(); 10150120Swpaul * final Object apply = sobj.get("apply"); 10250120Swpaul * return apply == receiver; 10350120Swpaul * } 10450120Swpaul * </pre> 10550120Swpaul * 10650120Swpaul * Naturally, checking for builtin classes like NativeFunction is cheaper, 10750120Swpaul * it's when you start adding property checks for said builtins you have 10850120Swpaul * problems with guard speed. 10950120Swpaul */ 11050120Swpaul public final Map<String, SwitchPoint> optimisticFunctionMap; 11150120Swpaul 11250120Swpaul /** Name invalidator for things like call/apply */ 11350120Swpaul public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); 11450120Swpaul 11550120Swpaul /** Nashorn extension: arguments array */ 11650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) 11750120Swpaul public Object arguments; 11850120Swpaul 11950120Swpaul /** ECMA 15.1.2.2 parseInt (string , radix) */ 12050120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 12150120Swpaul public Object parseInt; 12250120Swpaul 12350120Swpaul /** ECMA 15.1.2.3 parseFloat (string) */ 12450120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 12550120Swpaul public Object parseFloat; 12650120Swpaul 12750120Swpaul /** ECMA 15.1.2.4 isNaN (number) */ 12850120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 12950120Swpaul public Object isNaN; 13050120Swpaul 13150120Swpaul /** ECMA 15.1.2.5 isFinite (number) */ 13250120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 13350120Swpaul public Object isFinite; 13450120Swpaul 13550120Swpaul /** ECMA 15.1.3.3 encodeURI */ 13650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 13750120Swpaul public Object encodeURI; 13850120Swpaul 13950120Swpaul /** ECMA 15.1.3.4 encodeURIComponent */ 14050120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 14150120Swpaul public Object encodeURIComponent; 14250120Swpaul 14350120Swpaul /** ECMA 15.1.3.1 decodeURI */ 14450120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 14550120Swpaul public Object decodeURI; 14650120Swpaul 14750120Swpaul /** ECMA 15.1.3.2 decodeURIComponent */ 14850120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 14950120Swpaul public Object decodeURIComponent; 15050120Swpaul 15150120Swpaul /** ECMA B.2.1 escape (string) */ 15250120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 15350120Swpaul public Object escape; 15450120Swpaul 15550120Swpaul /** ECMA B.2.2 unescape (string) */ 15650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 15750120Swpaul public Object unescape; 15850120Swpaul 15950120Swpaul /** Nashorn extension: global.print */ 16050120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 16150120Swpaul public Object print; 16250120Swpaul 16350120Swpaul /** Nashorn extension: global.load */ 16450120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 16550120Swpaul public Object load; 16650120Swpaul 16750120Swpaul /** Nashorn extension: global.loadWithNewGlobal */ 16850120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 16950120Swpaul public Object loadWithNewGlobal; 17050120Swpaul 17150120Swpaul /** Nashorn extension: global.exit */ 17250120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 17350120Swpaul public Object exit; 17450120Swpaul 17550120Swpaul /** Nashorn extension: global.quit */ 17650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 17750120Swpaul public Object quit; 17850120Swpaul 17950120Swpaul /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */ 18050120Swpaul @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 18150120Swpaul public final double NaN = Double.NaN; 18250120Swpaul 18350120Swpaul /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */ 18450120Swpaul @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 18550120Swpaul public final double Infinity = Double.POSITIVE_INFINITY; 18650120Swpaul 18750120Swpaul /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */ 18850120Swpaul @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) 18950120Swpaul public final Object undefined = UNDEFINED; 19050120Swpaul 19150120Swpaul /** ECMA 15.1.2.1 eval(x) */ 19250120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 19350120Swpaul public Object eval; 19450120Swpaul 19550120Swpaul /** ECMA 15.1.4.1 Object constructor. */ 19650120Swpaul @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE) 19750120Swpaul public volatile Object object; 19850120Swpaul 19950120Swpaul /** ECMA 15.1.4.2 Function constructor. */ 20050120Swpaul @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE) 20150120Swpaul public volatile Object function; 20250120Swpaul 20350120Swpaul /** ECMA 15.1.4.3 Array constructor. */ 20450120Swpaul @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE) 20550120Swpaul public volatile Object array; 20650120Swpaul 20750120Swpaul /** ECMA 15.1.4.4 String constructor */ 20850120Swpaul @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE) 20950120Swpaul public volatile Object string; 21050120Swpaul 21150120Swpaul /** ECMA 15.1.4.5 Boolean constructor */ 21250120Swpaul @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE) 21350120Swpaul public volatile Object _boolean; 21450120Swpaul 21550120Swpaul /** ECMA 15.1.4.6 - Number constructor */ 21650120Swpaul @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE) 21750120Swpaul public volatile Object number; 21850120Swpaul 21950120Swpaul /** ECMA 15.1.4.7 Date constructor */ 22050120Swpaul @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE) 22150120Swpaul public volatile Object date; 22250120Swpaul 22350120Swpaul /** ECMA 15.1.4.8 RegExp constructor */ 22450120Swpaul @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) 22550120Swpaul public volatile Object regexp; 22650120Swpaul 22750120Swpaul /** ECMA 15.12 - The JSON object */ 22850120Swpaul @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) 22950120Swpaul public volatile Object json; 23050120Swpaul 23150120Swpaul /** Nashorn extension: global.JSAdapter */ 23250120Swpaul @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) 23350120Swpaul public volatile Object jsadapter; 23450120Swpaul 23550120Swpaul /** ECMA 15.8 - The Math object */ 23650120Swpaul @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) 23750120Swpaul public volatile Object math; 23850120Swpaul 23950120Swpaul /** Error object */ 24050120Swpaul @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE) 24150120Swpaul public volatile Object error; 24250120Swpaul 24350120Swpaul /** EvalError object */ 24450120Swpaul @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) 24550120Swpaul public volatile Object evalError; 24650120Swpaul 24750120Swpaul /** RangeError object */ 24850120Swpaul @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) 24950120Swpaul public volatile Object rangeError; 25050120Swpaul 25150120Swpaul /** ReferenceError object */ 25250120Swpaul @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) 25350120Swpaul public volatile Object referenceError; 25450120Swpaul 25550120Swpaul /** SyntaxError object */ 25650120Swpaul @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE) 25750120Swpaul public volatile Object syntaxError; 25850120Swpaul 25950120Swpaul /** TypeError object */ 26050120Swpaul @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE) 26150120Swpaul public volatile Object typeError; 26250120Swpaul 26350120Swpaul /** URIError object */ 26450120Swpaul @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) 26550120Swpaul public volatile Object uriError; 26650120Swpaul 26750120Swpaul /** ArrayBuffer object */ 26850120Swpaul @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) 26950120Swpaul public volatile Object arrayBuffer; 27050120Swpaul 27150120Swpaul /** DataView object */ 27250120Swpaul @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) 27350120Swpaul public volatile Object dataView; 27450120Swpaul 27550120Swpaul /** TypedArray (int8) */ 27650120Swpaul @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) 27750120Swpaul public volatile Object int8Array; 27850120Swpaul 27950120Swpaul /** TypedArray (uint8) */ 28050120Swpaul @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) 28150120Swpaul public volatile Object uint8Array; 28250120Swpaul 28350120Swpaul /** TypedArray (uint8) - Clamped */ 28450120Swpaul @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) 28550120Swpaul public volatile Object uint8ClampedArray; 28650120Swpaul 28750120Swpaul /** TypedArray (int16) */ 28850120Swpaul @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) 28950120Swpaul public volatile Object int16Array; 29050120Swpaul 29150120Swpaul /** TypedArray (uint16) */ 29250120Swpaul @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) 29350120Swpaul public volatile Object uint16Array; 29450120Swpaul 29550120Swpaul /** TypedArray (int32) */ 29650120Swpaul @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) 29750120Swpaul public volatile Object int32Array; 29850120Swpaul 29950120Swpaul /** TypedArray (uint32) */ 30050120Swpaul @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) 30150120Swpaul public volatile Object uint32Array; 30250120Swpaul 30350120Swpaul /** TypedArray (float32) */ 30450120Swpaul @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) 30550120Swpaul public volatile Object float32Array; 30650120Swpaul 30750120Swpaul /** TypedArray (float64) */ 30850120Swpaul @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) 30950120Swpaul public volatile Object float64Array; 31050120Swpaul 31150120Swpaul /** Nashorn extension: Java access - global.Packages */ 31250120Swpaul @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) 31350120Swpaul public volatile Object packages; 31450120Swpaul 31550120Swpaul /** Nashorn extension: Java access - global.com */ 31650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 31750120Swpaul public volatile Object com; 31850120Swpaul 31950120Swpaul /** Nashorn extension: Java access - global.edu */ 32050120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 32150120Swpaul public volatile Object edu; 32250120Swpaul 32350120Swpaul /** Nashorn extension: Java access - global.java */ 32450120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 32550120Swpaul public volatile Object java; 32650120Swpaul 32750120Swpaul /** Nashorn extension: Java access - global.javafx */ 32850120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 32950120Swpaul public volatile Object javafx; 33050120Swpaul 33150120Swpaul /** Nashorn extension: Java access - global.javax */ 33250120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 33350120Swpaul public volatile Object javax; 33450120Swpaul 33550120Swpaul /** Nashorn extension: Java access - global.org */ 33650120Swpaul @Property(attributes = Attribute.NOT_ENUMERABLE) 33750120Swpaul public volatile Object org; 33850120Swpaul 33950120Swpaul /** Nashorn extension: Java access - global.javaImporter */ 34050120Swpaul @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) 34150120Swpaul public volatile Object javaImporter; 34250120Swpaul 34350120Swpaul /** Nashorn extension: global.Java Object constructor. */ 34450120Swpaul @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE) 34550120Swpaul public volatile Object javaApi; 34650120Swpaul 34750120Swpaul /** Nashorn extension: current script's file name */ 34850120Swpaul @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 34950120Swpaul public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER; 35050120Swpaul 35150120Swpaul /** Nashorn extension: current script's directory */ 35250120Swpaul @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 35350120Swpaul public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER; 35450120Swpaul 35550120Swpaul /** Nashorn extension: current source line number being executed */ 35650120Swpaul @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) 35750120Swpaul public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER; 35850120Swpaul 35950120Swpaul /** Used as Date.prototype's default value */ 36050120Swpaul public NativeDate DEFAULT_DATE; 36150120Swpaul 36250120Swpaul /** Used as RegExp.prototype's default value */ 36350120Swpaul public NativeRegExp DEFAULT_REGEXP; 36450120Swpaul 36550120Swpaul /* 36650120Swpaul * Built-in constructor objects: Even if user changes dynamic values of 36750120Swpaul * "Object", "Array" etc., we still want to keep original values of these 36850120Swpaul * constructors here. For example, we need to be able to create array, 36950120Swpaul * regexp literals even after user overwrites global "Array" or "RegExp" 37050120Swpaul * constructor - see also ECMA 262 spec. Annex D. 37150120Swpaul */ 37250120Swpaul private ScriptFunction builtinFunction; 37350120Swpaul private ScriptFunction builtinObject; 37450120Swpaul private ScriptFunction builtinArray; 37550120Swpaul private ScriptFunction builtinBoolean; 37650120Swpaul private ScriptFunction builtinDate; 37750120Swpaul private ScriptObject builtinJSON; 37850120Swpaul private ScriptFunction builtinJSAdapter; 37950120Swpaul private ScriptObject builtinMath; 38050120Swpaul private ScriptFunction builtinNumber; 38150120Swpaul private ScriptFunction builtinRegExp; 38250120Swpaul private ScriptFunction builtinString; 38350120Swpaul private ScriptFunction builtinError; 38450120Swpaul private ScriptFunction builtinEval; 38550120Swpaul private ScriptFunction builtinEvalError; 38650120Swpaul private ScriptFunction builtinRangeError; 38750120Swpaul private ScriptFunction builtinReferenceError; 38850120Swpaul private ScriptFunction builtinSyntaxError; 38950120Swpaul private ScriptFunction builtinTypeError; 39050120Swpaul private ScriptFunction builtinURIError; 39150120Swpaul private ScriptObject builtinPackages; 39250120Swpaul private ScriptObject builtinCom; 39350120Swpaul private ScriptObject builtinEdu; 39450120Swpaul private ScriptObject builtinJava; 39550120Swpaul private ScriptObject builtinJavafx; 39650120Swpaul private ScriptObject builtinJavax; 39750120Swpaul private ScriptObject builtinOrg; 39850120Swpaul private ScriptFunction builtinJavaImporter; 39950120Swpaul private ScriptObject builtinJavaApi; 40050120Swpaul private ScriptFunction builtinArrayBuffer; 40150120Swpaul private ScriptFunction builtinDataView; 40250120Swpaul private ScriptFunction builtinInt8Array; 40350120Swpaul private ScriptFunction builtinUint8Array; 40450120Swpaul private ScriptFunction builtinUint8ClampedArray; 40550120Swpaul private ScriptFunction builtinInt16Array; 40650120Swpaul private ScriptFunction builtinUint16Array; 40750120Swpaul private ScriptFunction builtinInt32Array; 40850120Swpaul private ScriptFunction builtinUint32Array; 40950120Swpaul private ScriptFunction builtinFloat32Array; 41050120Swpaul private ScriptFunction builtinFloat64Array; 41150120Swpaul 41250120Swpaul /* 41350120Swpaul * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object 41450120Swpaul */ 41550120Swpaul private ScriptFunction typeErrorThrower; 41650120Swpaul 41750120Swpaul // Flag to indicate that a split method issued a return statement 41850120Swpaul private int splitState = -1; 41950120Swpaul 42050120Swpaul // Used to store the last RegExp result to support deprecated RegExp constructor properties 42150120Swpaul private RegExpResult lastRegExpResult; 42250120Swpaul 42350120Swpaul private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class); 42450120Swpaul private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class); 42550120Swpaul private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class); 42650120Swpaul private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class); 42750120Swpaul private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class); 42850120Swpaul private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class); 42950120Swpaul private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class); 43050120Swpaul 431 /** Invalidate a reserved name, such as "apply" or "call" if assigned */ 432 public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this); 433 434 // initialized by nasgen 435 private static PropertyMap $nasgenmap$; 436 437 // context to which this global belongs to 438 private final Context context; 439 440 // current ScriptContext to use - can be null. 441 private ScriptContext scontext; 442 // associated Property object for "context" property. 443 private jdk.nashorn.internal.runtime.Property scontextProperty; 444 445 /** 446 * Set the current script context 447 * @param scontext script context 448 */ 449 public void setScriptContext(final ScriptContext scontext) { 450 this.scontext = scontext; 451 scontextProperty.setValue(this, this, scontext, false); 452 } 453 454 // global constants for this global - they can be replaced with MethodHandle.constant until invalidated 455 private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>(); 456 457 @Override 458 protected Context getContext() { 459 return context; 460 } 461 462 // performs initialization checks for Global constructor and returns the 463 // PropertyMap, if everything is fine. 464 private static PropertyMap checkAndGetMap(final Context context) { 465 // security check first 466 final SecurityManager sm = System.getSecurityManager(); 467 if (sm != null) { 468 sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL)); 469 } 470 471 // null check on context 472 context.getClass(); 473 474 return $nasgenmap$; 475 } 476 477 /** 478 * Constructor 479 * 480 * @param context the context 481 */ 482 public Global(final Context context) { 483 super(checkAndGetMap(context)); 484 this.context = context; 485 this.setIsScope(); 486 this.optimisticFunctionMap = new HashMap<>(); 487 //we can only share one instance of Global constants between globals, or we consume way too much 488 //memory - this is good enough for most programs 489 while (gcsInstance.get() == null) { 490 gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class))); 491 } 492 } 493 494 /** 495 * Script access to "current" Global instance 496 * 497 * @return the global singleton 498 */ 499 public static Global instance() { 500 final Global global = Context.getGlobal(); 501 global.getClass(); // null check 502 return global; 503 } 504 505 private static Global instanceFrom(final Object self) { 506 return self instanceof Global? (Global)self : instance(); 507 } 508 509 /** 510 * Return the global constants map for fields that 511 * can be accessed as MethodHandle.constant 512 * @return constant map 513 */ 514 public static GlobalConstants getConstants() { 515 return gcsInstance.get(); 516 } 517 518 /** 519 * Check if we have a Global instance 520 * @return true if one exists 521 */ 522 public static boolean hasInstance() { 523 return Context.getGlobal() != null; 524 } 525 526 /** 527 * Script access to {@link ScriptEnvironment} 528 * 529 * @return the script environment 530 */ 531 static ScriptEnvironment getEnv() { 532 return instance().getContext().getEnv(); 533 } 534 535 /** 536 * Script access to {@link Context} 537 * 538 * @return the context 539 */ 540 static Context getThisContext() { 541 return instance().getContext(); 542 } 543 544 // Runtime interface to Global 545 546 /** 547 * Is there a class filter in the current Context? 548 * @return class filter 549 */ 550 public ClassFilter getClassFilter() { 551 return context.getClassFilter(); 552 } 553 554 /** 555 * Is this global of the given Context? 556 * @param ctxt the context 557 * @return true if this global belongs to the given Context 558 */ 559 public boolean isOfContext(final Context ctxt) { 560 return this.context == ctxt; 561 } 562 563 /** 564 * Does this global belong to a strict Context? 565 * @return true if this global belongs to a strict Context 566 */ 567 public boolean isStrictContext() { 568 return context.getEnv()._strict; 569 } 570 571 /** 572 * Initialize standard builtin objects like "Object", "Array", "Function" etc. 573 * as well as our extension builtin objects like "Java", "JSAdapter" as properties 574 * of the global scope object. 575 * 576 * @param engine ScriptEngine to initialize 577 */ 578 public void initBuiltinObjects(final ScriptEngine engine) { 579 if (this.builtinObject != null) { 580 // already initialized, just return 581 return; 582 } 583 584 init(engine); 585 } 586 587 /** 588 * Wrap a Java object as corresponding script object 589 * 590 * @param obj object to wrap 591 * @return wrapped object 592 */ 593 public Object wrapAsObject(final Object obj) { 594 if (obj instanceof Boolean) { 595 return new NativeBoolean((Boolean)obj, this); 596 } else if (obj instanceof Number) { 597 return new NativeNumber(((Number)obj).doubleValue(), this); 598 } else if (obj instanceof String || obj instanceof ConsString) { 599 return new NativeString((CharSequence)obj, this); 600 } else if (obj instanceof Object[]) { // extension 601 return new NativeArray((Object[])obj); 602 } else if (obj instanceof double[]) { // extension 603 return new NativeArray((double[])obj); 604 } else if (obj instanceof long[]) { 605 return new NativeArray((long[])obj); 606 } else if (obj instanceof int[]) { 607 return new NativeArray((int[])obj); 608 } else { 609 // FIXME: more special cases? Map? List? 610 return obj; 611 } 612 } 613 614 /** 615 * Lookup helper for JS primitive types 616 * 617 * @param request the link request for the dynamic call site. 618 * @param self self reference 619 * 620 * @return guarded invocation 621 */ 622 public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { 623 if (self instanceof String || self instanceof ConsString) { 624 return NativeString.lookupPrimitive(request, self); 625 } else if (self instanceof Number) { 626 return NativeNumber.lookupPrimitive(request, self); 627 } else if (self instanceof Boolean) { 628 return NativeBoolean.lookupPrimitive(request, self); 629 } 630 throw new IllegalArgumentException("Unsupported primitive: " + self); 631 } 632 633 /** 634 * Returns a method handle that creates a wrapper object for a JS primitive value. 635 * 636 * @param self receiver object 637 * @return method handle to create wrapper objects for primitive receiver 638 */ 639 public static MethodHandle getPrimitiveWrapFilter(final Object self) { 640 if (self instanceof String || self instanceof ConsString) { 641 return NativeString.WRAPFILTER; 642 } else if (self instanceof Number) { 643 return NativeNumber.WRAPFILTER; 644 } else if (self instanceof Boolean) { 645 return NativeBoolean.WRAPFILTER; 646 } 647 throw new IllegalArgumentException("Unsupported primitive: " + self); 648 } 649 650 651 /** 652 * Create a new empty script object 653 * 654 * @return the new ScriptObject 655 */ 656 public ScriptObject newObject() { 657 return new JO(getObjectPrototype(), JO.getInitialMap()); 658 } 659 660 /** 661 * Default value of given type 662 * 663 * @param sobj script object 664 * @param typeHint type hint 665 * 666 * @return default value 667 */ 668 public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) { 669 // When the [[DefaultValue]] internal method of O is called with no hint, 670 // then it behaves as if the hint were Number, unless O is a Date object 671 // in which case it behaves as if the hint were String. 672 Class<?> hint = typeHint; 673 if (hint == null) { 674 hint = Number.class; 675 } 676 677 try { 678 if (hint == String.class) { 679 680 final Object toString = TO_STRING.getGetter().invokeExact(sobj); 681 682 if (Bootstrap.isCallable(toString)) { 683 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); 684 if (JSType.isPrimitive(value)) { 685 return value; 686 } 687 } 688 689 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); 690 if (Bootstrap.isCallable(valueOf)) { 691 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); 692 if (JSType.isPrimitive(value)) { 693 return value; 694 } 695 } 696 throw typeError(this, "cannot.get.default.string"); 697 } 698 699 if (hint == Number.class) { 700 final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); 701 if (Bootstrap.isCallable(valueOf)) { 702 final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); 703 if (JSType.isPrimitive(value)) { 704 return value; 705 } 706 } 707 708 final Object toString = TO_STRING.getGetter().invokeExact(sobj); 709 if (Bootstrap.isCallable(toString)) { 710 final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); 711 if (JSType.isPrimitive(value)) { 712 return value; 713 } 714 } 715 716 throw typeError(this, "cannot.get.default.number"); 717 } 718 } catch (final RuntimeException | Error e) { 719 throw e; 720 } catch (final Throwable t) { 721 throw new RuntimeException(t); 722 } 723 724 return UNDEFINED; 725 } 726 727 /** 728 * Is the given ScriptObject an ECMAScript Error object? 729 * 730 * @param sobj the object being checked 731 * @return true if sobj is an Error object 732 */ 733 public boolean isError(final ScriptObject sobj) { 734 final ScriptObject errorProto = getErrorPrototype(); 735 ScriptObject proto = sobj.getProto(); 736 while (proto != null) { 737 if (proto == errorProto) { 738 return true; 739 } 740 proto = proto.getProto(); 741 } 742 return false; 743 } 744 745 /** 746 * Create a new ECMAScript Error object. 747 * 748 * @param msg error message 749 * @return newly created Error object 750 */ 751 public ScriptObject newError(final String msg) { 752 return new NativeError(msg, this); 753 } 754 755 /** 756 * Create a new ECMAScript EvalError object. 757 * 758 * @param msg error message 759 * @return newly created EvalError object 760 */ 761 public ScriptObject newEvalError(final String msg) { 762 return new NativeEvalError(msg, this); 763 } 764 765 /** 766 * Create a new ECMAScript RangeError object. 767 * 768 * @param msg error message 769 * @return newly created RangeError object 770 */ 771 public ScriptObject newRangeError(final String msg) { 772 return new NativeRangeError(msg, this); 773 } 774 775 /** 776 * Create a new ECMAScript ReferenceError object. 777 * 778 * @param msg error message 779 * @return newly created ReferenceError object 780 */ 781 public ScriptObject newReferenceError(final String msg) { 782 return new NativeReferenceError(msg, this); 783 } 784 785 /** 786 * Create a new ECMAScript SyntaxError object. 787 * 788 * @param msg error message 789 * @return newly created SyntaxError object 790 */ 791 public ScriptObject newSyntaxError(final String msg) { 792 return new NativeSyntaxError(msg, this); 793 } 794 795 /** 796 * Create a new ECMAScript TypeError object. 797 * 798 * @param msg error message 799 * @return newly created TypeError object 800 */ 801 public ScriptObject newTypeError(final String msg) { 802 return new NativeTypeError(msg, this); 803 } 804 805 /** 806 * Create a new ECMAScript URIError object. 807 * 808 * @param msg error message 809 * @return newly created URIError object 810 */ 811 public ScriptObject newURIError(final String msg) { 812 return new NativeURIError(msg, this); 813 } 814 815 /** 816 * Create a new ECMAScript GenericDescriptor object. 817 * 818 * @param configurable is the property configurable? 819 * @param enumerable is the property enumerable? 820 * @return newly created GenericDescriptor object 821 */ 822 public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) { 823 return new GenericPropertyDescriptor(configurable, enumerable, this); 824 } 825 826 /** 827 * Create a new ECMAScript DatePropertyDescriptor object. 828 * 829 * @param value of the data property 830 * @param configurable is the property configurable? 831 * @param enumerable is the property enumerable? 832 * @param writable is the property writable? 833 * @return newly created DataPropertyDescriptor object 834 */ 835 public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) { 836 return new DataPropertyDescriptor(configurable, enumerable, writable, value, this); 837 } 838 839 /** 840 * Create a new ECMAScript AccessorPropertyDescriptor object. 841 * 842 * @param get getter function of the user accessor property 843 * @param set setter function of the user accessor property 844 * @param configurable is the property configurable? 845 * @param enumerable is the property enumerable? 846 * @return newly created AccessorPropertyDescriptor object 847 */ 848 public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) { 849 final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this); 850 851 if (get == null) { 852 desc.delete(PropertyDescriptor.GET, false); 853 } 854 855 if (set == null) { 856 desc.delete(PropertyDescriptor.SET, false); 857 } 858 859 return desc; 860 } 861 862 private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) { 863 final T obj = map.get(key); 864 if (obj != null) { 865 return obj; 866 } 867 868 try { 869 final T newObj = creator.call(); 870 final T existingObj = map.putIfAbsent(key, newObj); 871 return existingObj != null ? existingObj : newObj; 872 } catch (final Exception exp) { 873 throw new RuntimeException(exp); 874 } 875 } 876 877 private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>(); 878 879 880 /** 881 * Get cached InvokeByName object for the given key 882 * @param key key to be associated with InvokeByName object 883 * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init) 884 * @return InvokeByName object associated with the key. 885 */ 886 public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) { 887 return getLazilyCreatedValue(key, creator, namedInvokers); 888 } 889 890 private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>(); 891 892 /** 893 * Get cached dynamic method handle for the given key 894 * @param key key to be associated with dynamic method handle 895 * @param creator if method handle is absent 'creator' is called to make one (lazy init) 896 * @return dynamic method handle associated with the key. 897 */ 898 public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) { 899 return getLazilyCreatedValue(key, creator, dynamicInvokers); 900 } 901 902 /** 903 * Hook to search missing variables in ScriptContext if available 904 * @param self used to detect if scope call or not (this function is 'strict') 905 * @param name name of the variable missing 906 * @return value of the missing variable or undefined (or TypeError for scope search) 907 */ 908 public static Object __noSuchProperty__(final Object self, final Object name) { 909 final Global global = Global.instance(); 910 final ScriptContext sctxt = global.scontext; 911 final String nameStr = name.toString(); 912 913 if (sctxt != null) { 914 final int scope = sctxt.getAttributesScope(nameStr); 915 if (scope != -1) { 916 return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global); 917 } 918 } 919 920 if (self == UNDEFINED) { 921 // scope access and so throw ReferenceError 922 throw referenceError(global, "not.defined", nameStr); 923 } 924 925 return UNDEFINED; 926 } 927 928 /** 929 * This is the eval used when 'indirect' eval call is made. 930 * 931 * var global = this; 932 * global.eval("print('hello')"); 933 * 934 * @param self eval scope 935 * @param str eval string 936 * 937 * @return the result of eval 938 */ 939 public static Object eval(final Object self, final Object str) { 940 return directEval(self, str, UNDEFINED, UNDEFINED, false); 941 } 942 943 /** 944 * Direct eval 945 * 946 * @param self The scope of eval passed as 'self' 947 * @param str Evaluated code 948 * @param callThis "this" to be passed to the evaluated code 949 * @param location location of the eval call 950 * @param strict is eval called a strict mode code? 951 * 952 * @return the return value of the eval 953 * 954 * This is directly invoked from generated when eval(code) is called in user code 955 */ 956 public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) { 957 if (!(str instanceof String || str instanceof ConsString)) { 958 return str; 959 } 960 final Global global = Global.instanceFrom(self); 961 final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global; 962 963 return global.getContext().eval(scope, str.toString(), callThis, location, strict, true); 964 } 965 966 /** 967 * Global print implementation - Nashorn extension 968 * 969 * @param self scope 970 * @param objects arguments to print 971 * 972 * @return result of print (undefined) 973 */ 974 public static Object print(final Object self, final Object... objects) { 975 return Global.instanceFrom(self).printImpl(false, objects); 976 } 977 978 /** 979 * Global println implementation - Nashorn extension 980 * 981 * @param self scope 982 * @param objects arguments to print 983 * 984 * @return result of println (undefined) 985 */ 986 public static Object println(final Object self, final Object... objects) { 987 return Global.instanceFrom(self).printImpl(true, objects); 988 } 989 990 /** 991 * Global load implementation - Nashorn extension 992 * 993 * @param self scope 994 * @param source source to load 995 * 996 * @return result of load (undefined) 997 * 998 * @throws IOException if source could not be read 999 */ 1000 public static Object load(final Object self, final Object source) throws IOException { 1001 final Global global = Global.instanceFrom(self); 1002 final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global; 1003 return global.getContext().load(scope, source); 1004 } 1005 1006 /** 1007 * Global loadWithNewGlobal implementation - Nashorn extension 1008 * 1009 * @param self scope 1010 * @param args from plus (optional) arguments to be passed to the loaded script 1011 * 1012 * @return result of load (may be undefined) 1013 * 1014 * @throws IOException if source could not be read 1015 */ 1016 public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException { 1017 final Global global = Global.instanceFrom(self); 1018 final int length = args.length; 1019 final boolean hasArgs = 0 < length; 1020 final Object from = hasArgs ? args[0] : UNDEFINED; 1021 final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args; 1022 1023 return global.getContext().loadWithNewGlobal(from, arguments); 1024 } 1025 1026 /** 1027 * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script 1028 * 1029 * @param self self reference 1030 * @param code exit code 1031 * 1032 * @return undefined (will never be reached) 1033 */ 1034 public static Object exit(final Object self, final Object code) { 1035 System.exit(JSType.toInt32(code)); 1036 return UNDEFINED; 1037 } 1038 1039 // builtin prototype accessors 1040 ScriptObject getFunctionPrototype() { 1041 return ScriptFunction.getPrototype(builtinFunction); 1042 } 1043 1044 ScriptObject getObjectPrototype() { 1045 return ScriptFunction.getPrototype(builtinObject); 1046 } 1047 1048 ScriptObject getArrayPrototype() { 1049 return ScriptFunction.getPrototype(builtinArray); 1050 } 1051 1052 ScriptObject getBooleanPrototype() { 1053 return ScriptFunction.getPrototype(builtinBoolean); 1054 } 1055 1056 ScriptObject getNumberPrototype() { 1057 return ScriptFunction.getPrototype(builtinNumber); 1058 } 1059 1060 ScriptObject getDatePrototype() { 1061 return ScriptFunction.getPrototype(builtinDate); 1062 } 1063 1064 ScriptObject getRegExpPrototype() { 1065 return ScriptFunction.getPrototype(builtinRegExp); 1066 } 1067 1068 ScriptObject getStringPrototype() { 1069 return ScriptFunction.getPrototype(builtinString); 1070 } 1071 1072 ScriptObject getErrorPrototype() { 1073 return ScriptFunction.getPrototype(builtinError); 1074 } 1075 1076 ScriptObject getEvalErrorPrototype() { 1077 return ScriptFunction.getPrototype(builtinEvalError); 1078 } 1079 1080 ScriptObject getRangeErrorPrototype() { 1081 return ScriptFunction.getPrototype(builtinRangeError); 1082 } 1083 1084 ScriptObject getReferenceErrorPrototype() { 1085 return ScriptFunction.getPrototype(builtinReferenceError); 1086 } 1087 1088 ScriptObject getSyntaxErrorPrototype() { 1089 return ScriptFunction.getPrototype(builtinSyntaxError); 1090 } 1091 1092 ScriptObject getTypeErrorPrototype() { 1093 return ScriptFunction.getPrototype(builtinTypeError); 1094 } 1095 1096 ScriptObject getURIErrorPrototype() { 1097 return ScriptFunction.getPrototype(builtinURIError); 1098 } 1099 1100 ScriptObject getJavaImporterPrototype() { 1101 return ScriptFunction.getPrototype(builtinJavaImporter); 1102 } 1103 1104 ScriptObject getJSAdapterPrototype() { 1105 return ScriptFunction.getPrototype(builtinJSAdapter); 1106 } 1107 1108 ScriptObject getArrayBufferPrototype() { 1109 return ScriptFunction.getPrototype(builtinArrayBuffer); 1110 } 1111 1112 ScriptObject getDataViewPrototype() { 1113 return ScriptFunction.getPrototype(builtinDataView); 1114 } 1115 1116 ScriptObject getInt8ArrayPrototype() { 1117 return ScriptFunction.getPrototype(builtinInt8Array); 1118 } 1119 1120 ScriptObject getUint8ArrayPrototype() { 1121 return ScriptFunction.getPrototype(builtinUint8Array); 1122 } 1123 1124 ScriptObject getUint8ClampedArrayPrototype() { 1125 return ScriptFunction.getPrototype(builtinUint8ClampedArray); 1126 } 1127 1128 ScriptObject getInt16ArrayPrototype() { 1129 return ScriptFunction.getPrototype(builtinInt16Array); 1130 } 1131 1132 ScriptObject getUint16ArrayPrototype() { 1133 return ScriptFunction.getPrototype(builtinUint16Array); 1134 } 1135 1136 ScriptObject getInt32ArrayPrototype() { 1137 return ScriptFunction.getPrototype(builtinInt32Array); 1138 } 1139 1140 ScriptObject getUint32ArrayPrototype() { 1141 return ScriptFunction.getPrototype(builtinUint32Array); 1142 } 1143 1144 ScriptObject getFloat32ArrayPrototype() { 1145 return ScriptFunction.getPrototype(builtinFloat32Array); 1146 } 1147 1148 ScriptObject getFloat64ArrayPrototype() { 1149 return ScriptFunction.getPrototype(builtinFloat64Array); 1150 } 1151 1152 private ScriptFunction getBuiltinArray() { 1153 return builtinArray; 1154 } 1155 1156 ScriptFunction getTypeErrorThrower() { 1157 return typeErrorThrower; 1158 } 1159 1160 /** 1161 * Called from compiled script code to test if builtin has been overridden 1162 * 1163 * @return true if builtin array has not been overridden 1164 */ 1165 public static boolean isBuiltinArray() { 1166 final Global instance = Global.instance(); 1167 return instance.array == instance.getBuiltinArray(); 1168 } 1169 1170 private ScriptFunction getBuiltinBoolean() { 1171 return builtinBoolean; 1172 } 1173 1174 /** 1175 * Called from compiled script code to test if builtin has been overridden 1176 * 1177 * @return true if builtin boolean has not been overridden 1178 */ 1179 public static boolean isBuiltinBoolean() { 1180 final Global instance = Global.instance(); 1181 return instance._boolean == instance.getBuiltinBoolean(); 1182 } 1183 1184 private ScriptFunction getBuiltinDate() { 1185 return builtinDate; 1186 } 1187 1188 /** 1189 * Called from compiled script code to test if builtin has been overridden 1190 * 1191 * @return true if builtin date has not been overridden 1192 */ 1193 public static boolean isBuiltinDate() { 1194 final Global instance = Global.instance(); 1195 return instance.date == instance.getBuiltinDate(); 1196 } 1197 1198 private ScriptFunction getBuiltinError() { 1199 return builtinError; 1200 } 1201 1202 /** 1203 * Called from compiled script code to test if builtin has been overridden 1204 * 1205 * @return true if builtin error has not been overridden 1206 */ 1207 public static boolean isBuiltinError() { 1208 final Global instance = Global.instance(); 1209 return instance.error == instance.getBuiltinError(); 1210 } 1211 1212 private ScriptFunction getBuiltinEvalError() { 1213 return builtinEvalError; 1214 } 1215 1216 /** 1217 * Called from compiled script code to test if builtin has been overridden 1218 * 1219 * @return true if builtin eval error has not been overridden 1220 */ 1221 public static boolean isBuiltinEvalError() { 1222 final Global instance = Global.instance(); 1223 return instance.evalError == instance.getBuiltinEvalError(); 1224 } 1225 1226 private ScriptFunction getBuiltinFunction() { 1227 return builtinFunction; 1228 } 1229 1230 /** 1231 * Called from compiled script code to test if builtin has been overridden 1232 * 1233 * @return true if builtin function has not been overridden 1234 */ 1235 public static boolean isBuiltinFunction() { 1236 final Global instance = Global.instance(); 1237 return instance.function == instance.getBuiltinFunction(); 1238 } 1239 1240 private ScriptFunction getBuiltinJSAdapter() { 1241 return builtinJSAdapter; 1242 } 1243 1244 /** 1245 * Called from compiled script code to test if builtin has been overridden 1246 * 1247 * @return true if builtin JSAdapter has not been overridden 1248 */ 1249 public static boolean isBuiltinJSAdapter() { 1250 final Global instance = Global.instance(); 1251 return instance.jsadapter == instance.getBuiltinJSAdapter(); 1252 } 1253 1254 private ScriptObject getBuiltinJSON() { 1255 return builtinJSON; 1256 } 1257 1258 /** 1259 * Called from compiled script code to test if builtin has been overridden 1260 * 1261 * @return true if builtin JSON has has not been overridden 1262 */ 1263 public static boolean isBuiltinJSON() { 1264 final Global instance = Global.instance(); 1265 return instance.json == instance.getBuiltinJSON(); 1266 } 1267 1268 private ScriptObject getBuiltinJava() { 1269 return builtinJava; 1270 } 1271 1272 /** 1273 * Called from compiled script code to test if builtin has been overridden 1274 * 1275 * @return true if builtin Java has not been overridden 1276 */ 1277 public static boolean isBuiltinJava() { 1278 final Global instance = Global.instance(); 1279 return instance.java == instance.getBuiltinJava(); 1280 } 1281 1282 private ScriptObject getBuiltinJavax() { 1283 return builtinJavax; 1284 } 1285 1286 /** 1287 * Called from compiled script code to test if builtin has been overridden 1288 * 1289 * @return true if builtin Javax has not been overridden 1290 */ 1291 public static boolean isBuiltinJavax() { 1292 final Global instance = Global.instance(); 1293 return instance.javax == instance.getBuiltinJavax(); 1294 } 1295 1296 private ScriptObject getBuiltinJavaImporter() { 1297 return builtinJavaImporter; 1298 } 1299 1300 /** 1301 * Called from compiled script code to test if builtin has been overridden 1302 * 1303 * @return true if builtin Java importer has not been overridden 1304 */ 1305 public static boolean isBuiltinJavaImporter() { 1306 final Global instance = Global.instance(); 1307 return instance.javaImporter == instance.getBuiltinJavaImporter(); 1308 } 1309 1310 private ScriptObject getBuiltinMath() { 1311 return builtinMath; 1312 } 1313 1314 /** 1315 * Called from compiled script code to test if builtin has been overridden 1316 * 1317 * @return true if builtin math has not been overridden 1318 */ 1319 public static boolean isBuiltinMath() { 1320 final Global instance = Global.instance(); 1321 return instance.math == instance.getBuiltinMath(); 1322 } 1323 1324 private ScriptFunction getBuiltinNumber() { 1325 return builtinNumber; 1326 } 1327 1328 /** 1329 * Called from compiled script code to test if builtin has been overridden 1330 * 1331 * @return true if builtin number has not been overridden 1332 */ 1333 public static boolean isBuiltinNumber() { 1334 final Global instance = Global.instance(); 1335 return instance.number == instance.getBuiltinNumber(); 1336 } 1337 1338 private ScriptFunction getBuiltinObject() { 1339 return builtinObject; 1340 } 1341 1342 /** 1343 * Called from compiled script code to test if builtin has been overridden 1344 * 1345 * @return true if builtin object has not been overridden 1346 */ 1347 public static boolean isBuiltinObject() { 1348 final Global instance = Global.instance(); 1349 return instance.object == instance.getBuiltinObject(); 1350 } 1351 1352 private ScriptObject getBuiltinPackages() { 1353 return builtinPackages; 1354 } 1355 1356 /** 1357 * Called from compiled script code to test if builtin has been overridden 1358 * 1359 * @return true if builtin package has not been overridden 1360 */ 1361 public static boolean isBuiltinPackages() { 1362 final Global instance = Global.instance(); 1363 return instance.packages == instance.getBuiltinPackages(); 1364 } 1365 1366 private ScriptFunction getBuiltinRangeError() { 1367 return builtinRangeError; 1368 } 1369 1370 /** 1371 * Called from compiled script code to test if builtin has been overridden 1372 * 1373 * @return true if builtin range error has not been overridden 1374 */ 1375 public static boolean isBuiltinRangeError() { 1376 final Global instance = Global.instance(); 1377 return instance.rangeError == instance.getBuiltinRangeError(); 1378 } 1379 1380 private ScriptFunction getBuiltinReferenceError() { 1381 return builtinReferenceError; 1382 } 1383 1384 /** 1385 * Called from compiled script code to test if builtin has been overridden 1386 * 1387 * @return true if builtin reference error has not been overridden 1388 */ 1389 public static boolean isBuiltinReferenceError() { 1390 final Global instance = Global.instance(); 1391 return instance.referenceError == instance.getBuiltinReferenceError(); 1392 } 1393 1394 private ScriptFunction getBuiltinRegExp() { 1395 return builtinRegExp; 1396 } 1397 1398 /** 1399 * Called from compiled script code to test if builtin has been overridden 1400 * 1401 * @return true if builtin regexp has not been overridden 1402 */ 1403 public static boolean isBuiltinRegExp() { 1404 final Global instance = Global.instance(); 1405 return instance.regexp == instance.getBuiltinRegExp(); 1406 } 1407 1408 private ScriptFunction getBuiltinString() { 1409 return builtinString; 1410 } 1411 1412 /** 1413 * Called from compiled script code to test if builtin has been overridden 1414 * 1415 * @return true if builtin Java has not been overridden 1416 */ 1417 public static boolean isBuiltinString() { 1418 final Global instance = Global.instance(); 1419 return instance.string == instance.getBuiltinString(); 1420 } 1421 1422 private ScriptFunction getBuiltinSyntaxError() { 1423 return builtinSyntaxError; 1424 } 1425 1426 /** 1427 * Called from compiled script code to test if builtin has been overridden 1428 * 1429 * @return true if builtin syntax error has not been overridden 1430 */ 1431 public static boolean isBuiltinSyntaxError() { 1432 final Global instance = Global.instance(); 1433 return instance.syntaxError == instance.getBuiltinSyntaxError(); 1434 } 1435 1436 private ScriptFunction getBuiltinTypeError() { 1437 return builtinTypeError; 1438 } 1439 1440 /** 1441 * Called from compiled script code to test if builtin has been overridden 1442 * 1443 * @return true if builtin type error has not been overridden 1444 */ 1445 public static boolean isBuiltinTypeError() { 1446 final Global instance = Global.instance(); 1447 return instance.typeError == instance.getBuiltinTypeError(); 1448 } 1449 1450 private ScriptFunction getBuiltinURIError() { 1451 return builtinURIError; 1452 } 1453 1454 /** 1455 * Called from compiled script code to test if builtin has been overridden 1456 * 1457 * @return true if builtin URI error has not been overridden 1458 */ 1459 public static boolean isBuiltinURIError() { 1460 final Global instance = Global.instance(); 1461 return instance.uriError == instance.getBuiltinURIError(); 1462 } 1463 1464 @Override 1465 public String getClassName() { 1466 return "global"; 1467 } 1468 1469 /** 1470 * Copy function used to clone NativeRegExp objects. 1471 * 1472 * @param regexp a NativeRegExp to clone 1473 * 1474 * @return copy of the given regexp object 1475 */ 1476 public static Object regExpCopy(final Object regexp) { 1477 return new NativeRegExp((NativeRegExp)regexp); 1478 } 1479 1480 /** 1481 * Convert given object to NativeRegExp type. 1482 * 1483 * @param obj object to be converted 1484 * @return NativeRegExp instance 1485 */ 1486 public static NativeRegExp toRegExp(final Object obj) { 1487 if (obj instanceof NativeRegExp) { 1488 return (NativeRegExp)obj; 1489 } 1490 return new NativeRegExp(JSType.toString(obj)); 1491 } 1492 1493 /** 1494 * ECMA 9.9 ToObject implementation 1495 * 1496 * @param obj an item for which to run ToObject 1497 * @return ToObject version of given item 1498 */ 1499 public static Object toObject(final Object obj) { 1500 if (obj == null || obj == UNDEFINED) { 1501 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 1502 } 1503 1504 if (obj instanceof ScriptObject) { 1505 return obj; 1506 } 1507 1508 return instance().wrapAsObject(obj); 1509 } 1510 1511 /** 1512 * Allocate a new object array. 1513 * 1514 * @param initial object values. 1515 * @return the new array 1516 */ 1517 public static NativeArray allocate(final Object[] initial) { 1518 ArrayData arrayData = ArrayData.allocate(initial); 1519 1520 for (int index = 0; index < initial.length; index++) { 1521 final Object value = initial[index]; 1522 1523 if (value == ScriptRuntime.EMPTY) { 1524 arrayData = arrayData.delete(index); 1525 } 1526 } 1527 1528 return new NativeArray(arrayData); 1529 } 1530 1531 /** 1532 * Allocate a new number array. 1533 * 1534 * @param initial number values. 1535 * @return the new array 1536 */ 1537 public static NativeArray allocate(final double[] initial) { 1538 return new NativeArray(ArrayData.allocate(initial)); 1539 } 1540 1541 /** 1542 * Allocate a new long array. 1543 * 1544 * @param initial number values. 1545 * @return the new array 1546 */ 1547 public static NativeArray allocate(final long[] initial) { 1548 return new NativeArray(ArrayData.allocate(initial)); 1549 } 1550 1551 /** 1552 * Allocate a new integer array. 1553 * 1554 * @param initial number values. 1555 * @return the new array 1556 */ 1557 public static NativeArray allocate(final int[] initial) { 1558 return new NativeArray(ArrayData.allocate(initial)); 1559 } 1560 1561 /** 1562 * Allocate a new object array for arguments. 1563 * 1564 * @param arguments initial arguments passed. 1565 * @param callee reference to the function that uses arguments object 1566 * @param numParams actual number of declared parameters 1567 * 1568 * @return the new array 1569 */ 1570 public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { 1571 return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); 1572 } 1573 1574 /** 1575 * Called from generated to check if given function is the builtin 'eval'. If 1576 * eval is used in a script, a lot of optimizations and assumptions cannot be done. 1577 * 1578 * @param fn function object that is checked 1579 * @return true if fn is the builtin eval 1580 */ 1581 public static boolean isEval(final Object fn) { 1582 return fn == Global.instance().builtinEval; 1583 } 1584 1585 /** 1586 * Called from generated to replace a location property placeholder with the actual location property value. 1587 * 1588 * @param placeholder the value tested for being a placeholder for a location property 1589 * @param locationProperty the actual value for the location property 1590 * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise 1591 */ 1592 public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) { 1593 return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder; 1594 } 1595 1596 /** 1597 * Called from runtime internals to check if the passed value is a location property placeholder. 1598 * @param placeholder the value tested for being a placeholder for a location property 1599 * @return true if the value is a placeholder, false otherwise. 1600 */ 1601 public static boolean isLocationPropertyPlaceholder(final Object placeholder) { 1602 return placeholder == LOCATION_PROPERTY_PLACEHOLDER; 1603 } 1604 1605 /** 1606 * Create a new RegExp object. 1607 * 1608 * @param expression Regular expression. 1609 * @param options Search options. 1610 * 1611 * @return New RegExp object. 1612 */ 1613 public static Object newRegExp(final String expression, final String options) { 1614 if (options == null) { 1615 return new NativeRegExp(expression); 1616 } 1617 return new NativeRegExp(expression, options); 1618 } 1619 1620 /** 1621 * Get the object prototype 1622 * 1623 * @return the object prototype 1624 */ 1625 public static ScriptObject objectPrototype() { 1626 return Global.instance().getObjectPrototype(); 1627 } 1628 1629 /** 1630 * Create a new empty object instance. 1631 * 1632 * @return New empty object. 1633 */ 1634 public static ScriptObject newEmptyInstance() { 1635 return Global.instance().newObject(); 1636 } 1637 1638 /** 1639 * Check if a given object is a ScriptObject, raises an exception if this is 1640 * not the case 1641 * 1642 * @param obj and object to check 1643 * @return the script object 1644 */ 1645 public static ScriptObject checkObject(final Object obj) { 1646 if (!(obj instanceof ScriptObject)) { 1647 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 1648 } 1649 return (ScriptObject)obj; 1650 } 1651 1652 /** 1653 * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception 1654 * if this object is null or undefined. 1655 * 1656 * @param obj an object to check 1657 */ 1658 public static void checkObjectCoercible(final Object obj) { 1659 if (obj == null || obj == UNDEFINED) { 1660 throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); 1661 } 1662 } 1663 1664 /** 1665 * Get the current split state. 1666 * 1667 * @return current split state 1668 */ 1669 @Override 1670 public int getSplitState() { 1671 return splitState; 1672 } 1673 1674 /** 1675 * Set the current split state. 1676 * 1677 * @param state current split state 1678 */ 1679 @Override 1680 public void setSplitState(final int state) { 1681 splitState = state; 1682 } 1683 1684 private void init(final ScriptEngine engine) { 1685 assert Context.getGlobal() == this : "this global is not set as current"; 1686 1687 final ScriptEnvironment env = getContext().getEnv(); 1688 1689 // initialize Function and Object constructor 1690 initFunctionAndObject(); 1691 1692 // Now fix Global's own proto. 1693 this.setInitialProto(getObjectPrototype()); 1694 1695 // initialize global function properties 1696 this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); 1697 1698 this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT, 1699 new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O }); 1700 this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); 1701 this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); 1702 this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); 1703 this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI); 1704 this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); 1705 this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI); 1706 this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); 1707 this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE); 1708 this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE); 1709 this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN); 1710 this.load = ScriptFunctionImpl.makeFunction("load", LOAD); 1711 this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL); 1712 this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT); 1713 this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); 1714 1715 // built-in constructors 1716 this.builtinArray = initConstructor("Array", ScriptFunction.class); 1717 this.builtinBoolean = initConstructor("Boolean", ScriptFunction.class); 1718 this.builtinDate = initConstructor("Date", ScriptFunction.class); 1719 this.builtinJSON = initConstructor("JSON", ScriptObject.class); 1720 this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class); 1721 this.builtinMath = initConstructor("Math", ScriptObject.class); 1722 this.builtinNumber = initConstructor("Number", ScriptFunction.class); 1723 this.builtinRegExp = initConstructor("RegExp", ScriptFunction.class); 1724 this.builtinString = initConstructor("String", ScriptFunction.class); 1725 1726 // initialize String.prototype.length to 0 1727 // add String.prototype.length 1728 final ScriptObject stringPrototype = getStringPrototype(); 1729 stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); 1730 1731 // set isArray flag on Array.prototype 1732 final ScriptObject arrayPrototype = getArrayPrototype(); 1733 arrayPrototype.setIsArray(); 1734 1735 this.DEFAULT_DATE = new NativeDate(Double.NaN, this); 1736 1737 // initialize default regexp object 1738 this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this); 1739 1740 // RegExp.prototype should behave like a RegExp object. So copy the 1741 // properties. 1742 final ScriptObject regExpProto = getRegExpPrototype(); 1743 regExpProto.addBoundProperties(DEFAULT_REGEXP); 1744 1745 // Error stuff 1746 initErrorObjects(); 1747 1748 // java access 1749 if (! env._no_java) { 1750 initJavaAccess(); 1751 } 1752 1753 if (! env._no_typed_arrays) { 1754 initTypedArray(); 1755 } 1756 1757 if (env._scripting) { 1758 initScripting(env); 1759 } 1760 1761 if (Context.DEBUG) { 1762 boolean debugOkay; 1763 final SecurityManager sm = System.getSecurityManager(); 1764 if (sm != null) { 1765 try { 1766 sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE)); 1767 debugOkay = true; 1768 } catch (final SecurityException ignored) { 1769 // if no permission, don't initialize Debug object 1770 debugOkay = false; 1771 } 1772 1773 } else { 1774 debugOkay = true; 1775 } 1776 1777 if (debugOkay) { 1778 initDebug(); 1779 } 1780 } 1781 1782 copyBuiltins(); 1783 1784 // expose script (command line) arguments as "arguments" property of global 1785 arguments = wrapAsObject(env.getArguments().toArray()); 1786 if (env._scripting) { 1787 // synonym for "arguments" in scripting mode 1788 addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); 1789 } 1790 1791 if (engine != null) { 1792 final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE; 1793 scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null); 1794 addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine); 1795 // default file name 1796 addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); 1797 // __noSuchProperty__ hook for ScriptContext search of missing variables 1798 final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); 1799 addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); 1800 } 1801 } 1802 1803 private void initErrorObjects() { 1804 // Error objects 1805 this.builtinError = initConstructor("Error", ScriptFunction.class); 1806 final ScriptObject errorProto = getErrorPrototype(); 1807 1808 // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName 1809 final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK); 1810 final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK); 1811 errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); 1812 final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER); 1813 final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER); 1814 errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); 1815 final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER); 1816 final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER); 1817 errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); 1818 final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME); 1819 final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME); 1820 errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); 1821 1822 // ECMA 15.11.4.2 Error.prototype.name 1823 // Error.prototype.name = "Error"; 1824 errorProto.set(NativeError.NAME, "Error", false); 1825 // ECMA 15.11.4.3 Error.prototype.message 1826 // Error.prototype.message = ""; 1827 errorProto.set(NativeError.MESSAGE, "", false); 1828 1829 this.builtinEvalError = initErrorSubtype("EvalError", errorProto); 1830 this.builtinRangeError = initErrorSubtype("RangeError", errorProto); 1831 this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); 1832 this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); 1833 this.builtinTypeError = initErrorSubtype("TypeError", errorProto); 1834 this.builtinURIError = initErrorSubtype("URIError", errorProto); 1835 } 1836 1837 private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { 1838 final ScriptFunction cons = initConstructor(name, ScriptFunction.class); 1839 final ScriptObject prototype = ScriptFunction.getPrototype(cons); 1840 prototype.set(NativeError.NAME, name, false); 1841 prototype.set(NativeError.MESSAGE, "", false); 1842 prototype.setInitialProto(errorProto); 1843 return cons; 1844 } 1845 1846 private void initJavaAccess() { 1847 final ScriptObject objectProto = getObjectPrototype(); 1848 this.builtinPackages = new NativeJavaPackage("", objectProto); 1849 this.builtinCom = new NativeJavaPackage("com", objectProto); 1850 this.builtinEdu = new NativeJavaPackage("edu", objectProto); 1851 this.builtinJava = new NativeJavaPackage("java", objectProto); 1852 this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); 1853 this.builtinJavax = new NativeJavaPackage("javax", objectProto); 1854 this.builtinOrg = new NativeJavaPackage("org", objectProto); 1855 this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); 1856 this.builtinJavaApi = initConstructor("Java", ScriptObject.class); 1857 } 1858 1859 private void initScripting(final ScriptEnvironment scriptEnv) { 1860 Object value; 1861 value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); 1862 addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); 1863 1864 value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY); 1865 addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); 1866 1867 final String execName = ScriptingFunctions.EXEC_NAME; 1868 value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); 1869 addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); 1870 1871 // Nashorn extension: global.echo (scripting-mode-only) 1872 // alias for "print" 1873 value = get("print"); 1874 addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); 1875 1876 // Nashorn extension: global.$OPTIONS (scripting-mode-only) 1877 final ScriptObject options = newObject(); 1878 copyOptions(options, scriptEnv); 1879 addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); 1880 1881 // Nashorn extension: global.$ENV (scripting-mode-only) 1882 if (System.getSecurityManager() == null) { 1883 // do not fill $ENV if we have a security manager around 1884 // Retrieve current state of ENV variables. 1885 final ScriptObject env = newObject(); 1886 env.putAll(System.getenv(), scriptEnv._strict); 1887 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); 1888 } else { 1889 addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 1890 } 1891 1892 // add other special properties for exec support 1893 addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 1894 addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 1895 addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); 1896 } 1897 1898 private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { 1899 for (final Field f : scriptEnv.getClass().getFields()) { 1900 try { 1901 options.set(f.getName(), f.get(scriptEnv), false); 1902 } catch (final IllegalArgumentException | IllegalAccessException exp) { 1903 throw new RuntimeException(exp); 1904 } 1905 } 1906 } 1907 1908 private void initTypedArray() { 1909 this.builtinArrayBuffer = initConstructor("ArrayBuffer", ScriptFunction.class); 1910 this.builtinDataView = initConstructor("DataView", ScriptFunction.class); 1911 this.builtinInt8Array = initConstructor("Int8Array", ScriptFunction.class); 1912 this.builtinUint8Array = initConstructor("Uint8Array", ScriptFunction.class); 1913 this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class); 1914 this.builtinInt16Array = initConstructor("Int16Array", ScriptFunction.class); 1915 this.builtinUint16Array = initConstructor("Uint16Array", ScriptFunction.class); 1916 this.builtinInt32Array = initConstructor("Int32Array", ScriptFunction.class); 1917 this.builtinUint32Array = initConstructor("Uint32Array", ScriptFunction.class); 1918 this.builtinFloat32Array = initConstructor("Float32Array", ScriptFunction.class); 1919 this.builtinFloat64Array = initConstructor("Float64Array", ScriptFunction.class); 1920 } 1921 1922 private void copyBuiltins() { 1923 this.array = this.builtinArray; 1924 this._boolean = this.builtinBoolean; 1925 this.date = this.builtinDate; 1926 this.error = this.builtinError; 1927 this.evalError = this.builtinEvalError; 1928 this.function = this.builtinFunction; 1929 this.jsadapter = this.builtinJSAdapter; 1930 this.json = this.builtinJSON; 1931 this.com = this.builtinCom; 1932 this.edu = this.builtinEdu; 1933 this.java = this.builtinJava; 1934 this.javafx = this.builtinJavafx; 1935 this.javax = this.builtinJavax; 1936 this.org = this.builtinOrg; 1937 this.javaImporter = this.builtinJavaImporter; 1938 this.javaApi = this.builtinJavaApi; 1939 this.math = this.builtinMath; 1940 this.number = this.builtinNumber; 1941 this.object = this.builtinObject; 1942 this.packages = this.builtinPackages; 1943 this.rangeError = this.builtinRangeError; 1944 this.referenceError = this.builtinReferenceError; 1945 this.regexp = this.builtinRegExp; 1946 this.string = this.builtinString; 1947 this.syntaxError = this.builtinSyntaxError; 1948 this.typeError = this.builtinTypeError; 1949 this.uriError = this.builtinURIError; 1950 this.arrayBuffer = this.builtinArrayBuffer; 1951 this.dataView = this.builtinDataView; 1952 this.int8Array = this.builtinInt8Array; 1953 this.uint8Array = this.builtinUint8Array; 1954 this.uint8ClampedArray = this.builtinUint8ClampedArray; 1955 this.int16Array = this.builtinInt16Array; 1956 this.uint16Array = this.builtinUint16Array; 1957 this.int32Array = this.builtinInt32Array; 1958 this.uint32Array = this.builtinUint32Array; 1959 this.float32Array = this.builtinFloat32Array; 1960 this.float64Array = this.builtinFloat64Array; 1961 } 1962 1963 private void initDebug() { 1964 this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class)); 1965 } 1966 1967 private Object printImpl(final boolean newLine, final Object... objects) { 1968 @SuppressWarnings("resource") 1969 final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut(); 1970 final StringBuilder sb = new StringBuilder(); 1971 1972 for (final Object obj : objects) { 1973 if (sb.length() != 0) { 1974 sb.append(' '); 1975 } 1976 1977 sb.append(JSType.toString(obj)); 1978 } 1979 1980 // Print all at once to ensure thread friendly result. 1981 if (newLine) { 1982 out.println(sb.toString()); 1983 } else { 1984 out.print(sb.toString()); 1985 } 1986 1987 out.flush(); 1988 1989 return UNDEFINED; 1990 } 1991 1992 /** 1993 * These classes are generated by nasgen tool and so we have to use 1994 * reflection to load and create new instance of these classes. 1995 */ 1996 private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { 1997 try { 1998 // Assuming class name pattern for built-in JS constructors. 1999 final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects."); 2000 2001 sb.append("Native"); 2002 sb.append(name); 2003 sb.append("$Constructor"); 2004 2005 final Class<?> funcClass = Class.forName(sb.toString()); 2006 final T res = clazz.cast(funcClass.newInstance()); 2007 2008 if (res instanceof ScriptFunction) { 2009 // All global constructor prototypes are not-writable, 2010 // not-enumerable and not-configurable. 2011 final ScriptFunction func = (ScriptFunction)res; 2012 func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); 2013 } 2014 2015 if (res.getProto() == null) { 2016 res.setInitialProto(getObjectPrototype()); 2017 } 2018 2019 res.setIsBuiltin(); 2020 return res; 2021 } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { 2022 throw new RuntimeException(e); 2023 } 2024 } 2025 2026 // Function and Object constructors are inter-dependent. Also, 2027 // Function.prototype 2028 // functions are not properly initialized. We fix the references here. 2029 // NOTE: be careful if you want to re-order the operations here. You may 2030 // have 2031 // to play with object references carefully!! 2032 private void initFunctionAndObject() { 2033 // First-n-foremost is Function 2034 this.builtinFunction = initConstructor("Function", ScriptFunction.class); 2035 2036 // create global anonymous function 2037 final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); 2038 // need to copy over members of Function.prototype to anon function 2039 anon.addBoundProperties(getFunctionPrototype()); 2040 2041 // Function.prototype === Object.getPrototypeOf(Function) === 2042 // <anon-function> 2043 builtinFunction.setInitialProto(anon); 2044 builtinFunction.setPrototype(anon); 2045 anon.set("constructor", builtinFunction, false); 2046 anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); 2047 2048 // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 2049 this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0); 2050 typeErrorThrower.setPrototype(UNDEFINED); 2051 // Non-constructor built-in functions do not have "prototype" property 2052 typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype")); 2053 typeErrorThrower.preventExtensions(); 2054 2055 // now initialize Object 2056 this.builtinObject = initConstructor("Object", ScriptFunction.class); 2057 final ScriptObject ObjectPrototype = getObjectPrototype(); 2058 // Object.getPrototypeOf(Function.prototype) === Object.prototype 2059 anon.setInitialProto(ObjectPrototype); 2060 2061 // ES6 draft compliant __proto__ property of Object.prototype 2062 // accessors on Object.prototype for "__proto__" 2063 final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__); 2064 final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__); 2065 ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); 2066 2067 // Function valued properties of Function.prototype were not properly 2068 // initialized. Because, these were created before global.function and 2069 // global.object were not initialized. 2070 jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); 2071 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2072 final Object key = property.getKey(); 2073 final Object value = builtinFunction.get(key); 2074 2075 if (value instanceof ScriptFunction && value != anon) { 2076 final ScriptFunction func = (ScriptFunction)value; 2077 func.setInitialProto(getFunctionPrototype()); 2078 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2079 if (prototype != null) { 2080 prototype.setInitialProto(ObjectPrototype); 2081 } 2082 } 2083 } 2084 2085 // For function valued properties of Object and Object.prototype, make 2086 // sure prototype's proto chain ends with Object.prototype 2087 for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { 2088 final Object key = property.getKey(); 2089 final Object value = builtinObject.get(key); 2090 2091 if (value instanceof ScriptFunction) { 2092 final ScriptFunction func = (ScriptFunction)value; 2093 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2094 if (prototype != null) { 2095 prototype.setInitialProto(ObjectPrototype); 2096 } 2097 } 2098 } 2099 2100 //make sure apply and call have the same invalidation switchpoint 2101 final SwitchPoint sp = new SwitchPoint(); 2102 optimisticFunctionMap.put("apply", sp); 2103 optimisticFunctionMap.put("call", sp); 2104 getFunctionPrototype().getProperty("apply").setChangeCallback(sp); 2105 getFunctionPrototype().getProperty("call").setChangeCallback(sp); 2106 2107 properties = getObjectPrototype().getMap().getProperties(); 2108 2109 for (final jdk.nashorn.internal.runtime.Property property : properties) { 2110 final Object key = property.getKey(); 2111 if (key.equals("constructor")) { 2112 continue; 2113 } 2114 2115 final Object value = ObjectPrototype.get(key); 2116 if (value instanceof ScriptFunction) { 2117 final ScriptFunction func = (ScriptFunction)value; 2118 final ScriptObject prototype = ScriptFunction.getPrototype(func); 2119 if (prototype != null) { 2120 prototype.setInitialProto(ObjectPrototype); 2121 } 2122 } 2123 } 2124 } 2125 2126 private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) { 2127 return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 2128 } 2129 2130 private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { 2131 return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); 2132 } 2133 2134 RegExpResult getLastRegExpResult() { 2135 return lastRegExpResult; 2136 } 2137 2138 void setLastRegExpResult(final RegExpResult regExpResult) { 2139 this.lastRegExpResult = regExpResult; 2140 } 2141 2142 @Override 2143 protected boolean isGlobal() { 2144 return true; 2145 } 2146 2147 /** 2148 * Check if there is a switchpoint for a reserved name. If there 2149 * is, it must be invalidated upon properties with this name 2150 * @param name property name 2151 * @return switchpoint for invalidating this property, or null if not registered 2152 */ 2153 public SwitchPoint getChangeCallback(final String name) { 2154 return optimisticFunctionMap.get(name); 2155 } 2156 2157 /** 2158 * Is this a special name, that might be subject to invalidation 2159 * on write, such as "apply" or "call" 2160 * @param name name to check 2161 * @return true if special name 2162 */ 2163 public boolean isSpecialName(final String name) { 2164 return getChangeCallback(name) != null; 2165 } 2166 2167 /** 2168 * Check if a reserved property name is invalidated 2169 * @param name property name 2170 * @return true if someone has written to it since Global was instantiated 2171 */ 2172 public boolean isSpecialNameValid(final String name) { 2173 final SwitchPoint sp = getChangeCallback(name); 2174 return sp != null && !sp.hasBeenInvalidated(); 2175 } 2176 2177 /** 2178 * Tag a reserved name as invalidated - used when someone writes 2179 * to a property with this name - overly conservative, but link time 2180 * is too late to apply e.g. apply->call specialization 2181 * @param name property name 2182 */ 2183 public void invalidateReservedName(final String name) { 2184 final SwitchPoint sp = getChangeCallback(name); 2185 if (sp != null) { 2186 getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint"); 2187 SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); 2188 } 2189 } 2190 2191 /** 2192 * Bootstrapper for invalidating a builtin name 2193 * @param lookup lookup 2194 * @param name name to invalidate 2195 * @param type methodhandle type 2196 * @return callsite for invalidator 2197 */ 2198 public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) { 2199 final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name); 2200 return new ConstantCallSite(target); 2201 } 2202 2203 2204} 2205