jlaskey@3: /* jlaskey@7: * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. jlaskey@3: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jlaskey@3: * jlaskey@3: * This code is free software; you can redistribute it and/or modify it jlaskey@3: * under the terms of the GNU General Public License version 2 only, as jlaskey@3: * published by the Free Software Foundation. Oracle designates this jlaskey@3: * particular file as subject to the "Classpath" exception as provided jlaskey@3: * by Oracle in the LICENSE file that accompanied this code. jlaskey@3: * jlaskey@3: * This code is distributed in the hope that it will be useful, but WITHOUT jlaskey@3: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jlaskey@3: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jlaskey@3: * version 2 for more details (a copy is included in the LICENSE file that jlaskey@3: * accompanied this code). jlaskey@3: * jlaskey@3: * You should have received a copy of the GNU General Public License version jlaskey@3: * 2 along with this work; if not, write to the Free Software Foundation, jlaskey@3: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jlaskey@3: * jlaskey@3: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jlaskey@3: * or visit www.oracle.com if you need additional information or have any jlaskey@3: * questions. jlaskey@3: */ jlaskey@3: jlaskey@3: package jdk.nashorn.internal.objects; jlaskey@3: jlaskey@3: import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; jlaskey@3: import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; sundar@133: import static jdk.nashorn.internal.lookup.Lookup.MH; jlaskey@3: jlaskey@3: import java.io.IOException; jlaskey@3: import java.io.PrintWriter; jlaskey@3: import java.lang.invoke.MethodHandle; jlaskey@3: import java.lang.invoke.MethodHandles; jlaskey@3: import java.lang.ref.SoftReference; sundar@136: import java.lang.reflect.Field; sundar@136: import java.security.AccessController; sundar@136: import java.security.PrivilegedAction; jlaskey@3: import java.util.LinkedHashMap; jlaskey@3: import java.util.List; jlaskey@3: import java.util.Map; attila@90: import jdk.internal.dynalink.linker.GuardedInvocation; attila@90: import jdk.internal.dynalink.linker.LinkRequest; jlaskey@3: import jdk.nashorn.internal.objects.annotations.Attribute; jlaskey@3: import jdk.nashorn.internal.objects.annotations.Property; jlaskey@3: import jdk.nashorn.internal.objects.annotations.ScriptClass; jlaskey@3: import jdk.nashorn.internal.runtime.ConsString; jlaskey@3: import jdk.nashorn.internal.runtime.Context; jlaskey@3: import jdk.nashorn.internal.runtime.GlobalFunctions; jlaskey@3: import jdk.nashorn.internal.runtime.GlobalObject; jlaskey@3: import jdk.nashorn.internal.runtime.JSType; jlaskey@3: import jdk.nashorn.internal.runtime.NativeJavaPackage; sundar@118: import jdk.nashorn.internal.runtime.ScriptEnvironment; jlaskey@3: import jdk.nashorn.internal.runtime.PropertyDescriptor; hannesw@114: import jdk.nashorn.internal.runtime.regexp.RegExpResult; jlaskey@3: import jdk.nashorn.internal.runtime.Scope; jlaskey@3: import jdk.nashorn.internal.runtime.ScriptFunction; jlaskey@3: import jdk.nashorn.internal.runtime.ScriptObject; jlaskey@3: import jdk.nashorn.internal.runtime.ScriptRuntime; jlaskey@3: import jdk.nashorn.internal.runtime.ScriptingFunctions; jlaskey@3: import jdk.nashorn.internal.runtime.Source; jlaskey@3: import jdk.nashorn.internal.runtime.linker.InvokeByName; jlaskey@131: import jdk.nashorn.internal.scripts.JO; jlaskey@3: jlaskey@3: /** jlaskey@3: * Representation of global scope. jlaskey@3: */ jlaskey@3: @ScriptClass("Global") jlaskey@3: public final class Global extends ScriptObject implements GlobalObject, Scope { jlaskey@3: private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); jlaskey@3: private static final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); jlaskey@3: jlaskey@3: /** ECMA 15.1.2.2 parseInt (string , radix) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object parseInt; jlaskey@3: jlaskey@3: /** ECMA 15.1.2.3 parseFloat (string) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object parseFloat; jlaskey@3: jlaskey@3: /** ECMA 15.1.2.4 isNaN (number) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object isNaN; jlaskey@3: jlaskey@3: /** ECMA 15.1.2.5 isFinite (number) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object isFinite; jlaskey@3: jlaskey@3: /** ECMA 15.1.3.3 encodeURI */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object encodeURI; jlaskey@3: jlaskey@3: /** ECMA 15.1.3.4 encodeURIComponent */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object encodeURIComponent; jlaskey@3: jlaskey@3: /** ECMA 15.1.3.1 decodeURI */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object decodeURI; jlaskey@3: jlaskey@3: /** ECMA 15.1.3.2 decodeURIComponent */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object decodeURIComponent; jlaskey@3: jlaskey@3: /** ECMA B.2.1 escape (string) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object escape; jlaskey@3: jlaskey@3: /** ECMA B.2.2 unescape (string) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object unescape; jlaskey@3: jlaskey@3: /** Nashorn extension: global.print */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object print; jlaskey@3: jlaskey@3: /** Nashorn extension: global.load */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object load; jlaskey@3: jlaskey@75: /** Nashorn extension: global.exit */ jlaskey@75: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@75: public Object exit; jlaskey@75: jlaskey@75: /** Nashorn extension: global.quit */ jlaskey@75: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@75: public Object quit; jlaskey@75: jlaskey@3: /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */ jlaskey@3: @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public final Object NaN = Double.NaN; jlaskey@3: jlaskey@3: /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */ jlaskey@3: @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public final Object Infinity = Double.POSITIVE_INFINITY; jlaskey@3: jlaskey@3: /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */ jlaskey@3: @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public final Object undefined = UNDEFINED; jlaskey@3: jlaskey@3: /** ECMA 15.1.2.1 eval(x) */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public Object eval; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.1 Object constructor. */ jlaskey@3: @Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object object; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.2 Function constructor. */ jlaskey@3: @Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object function; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.3 Array constructor. */ jlaskey@3: @Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object array; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.4 String constructor */ jlaskey@3: @Property(name = "String", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object string; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.5 Boolean constructor */ jlaskey@3: @Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object _boolean; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.6 - Number constructor */ jlaskey@3: @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object number; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.7 Date constructor */ jlaskey@3: @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object date; jlaskey@3: jlaskey@3: /** ECMA 15.1.4.8 RegExp constructor */ jlaskey@3: @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object regexp; jlaskey@3: jlaskey@3: /** ECMA 15.12 - The JSON object */ jlaskey@3: @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object json; jlaskey@3: jlaskey@3: /** Nashorn extension: global.JSAdapter */ jlaskey@3: @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object jsadapter; jlaskey@3: jlaskey@3: /** ECMA 15.8 - The Math object */ jlaskey@3: @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object math; jlaskey@3: jlaskey@3: /** Error object */ jlaskey@3: @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object error; jlaskey@3: jlaskey@3: /** EvalError object */ jlaskey@3: @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object evalError; jlaskey@3: jlaskey@3: /** RangeError object */ jlaskey@3: @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object rangeError; jlaskey@3: jlaskey@3: /** ReferenceError object */ jlaskey@3: @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object referenceError; jlaskey@3: jlaskey@3: /** SyntaxError object */ jlaskey@3: @Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object syntaxError; jlaskey@3: jlaskey@3: /** TypeError object */ jlaskey@3: @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object typeError; jlaskey@3: jlaskey@3: /** URIError object */ jlaskey@3: @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object uriError; jlaskey@3: jlaskey@3: /** ArrayBuffer object */ jlaskey@3: @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object arrayBuffer; jlaskey@3: jlaskey@3: /** TypedArray (int8) */ jlaskey@3: @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object int8Array; jlaskey@3: jlaskey@3: /** TypedArray (uint8) */ jlaskey@3: @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object uint8Array; jlaskey@3: jlaskey@3: /** TypedArray (uint8) - Clamped */ jlaskey@3: @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object uint8ClampedArray; jlaskey@3: jlaskey@3: /** TypedArray (int16) */ jlaskey@3: @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object int16Array; jlaskey@3: jlaskey@3: /** TypedArray (uint16) */ jlaskey@3: @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object uint16Array; jlaskey@3: jlaskey@3: /** TypedArray (int32) */ jlaskey@3: @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object int32Array; jlaskey@3: jlaskey@3: /** TypedArray (uint32) */ jlaskey@3: @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object uint32Array; jlaskey@3: jlaskey@3: /** TypedArray (float32) */ jlaskey@3: @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object float32Array; jlaskey@3: jlaskey@3: /** TypedArray (float64) */ jlaskey@3: @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object float64Array; jlaskey@3: jlaskey@3: /** Nashorn extension: Java access - global.Packages */ jlaskey@3: @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object packages; jlaskey@3: sundar@146: /** Nashorn extension: Java access - global.com */ sundar@146: @Property(attributes = Attribute.NOT_ENUMERABLE) sundar@146: public volatile Object com; sundar@146: sundar@146: /** Nashorn extension: Java access - global.edu */ sundar@146: @Property(attributes = Attribute.NOT_ENUMERABLE) sundar@146: public volatile Object edu; sundar@146: jlaskey@3: /** Nashorn extension: Java access - global.java */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object java; jlaskey@3: sundar@146: /** Nashorn extension: Java access - global.javafx */ sundar@146: @Property(attributes = Attribute.NOT_ENUMERABLE) sundar@146: public volatile Object javafx; sundar@146: jlaskey@3: /** Nashorn extension: Java access - global.javax */ jlaskey@3: @Property(attributes = Attribute.NOT_ENUMERABLE) sundar@146: public volatile Object javax; sundar@146: sundar@146: /** Nashorn extension: Java access - global.org */ sundar@146: @Property(attributes = Attribute.NOT_ENUMERABLE) sundar@146: public volatile Object org; jlaskey@3: jlaskey@3: /** Nashorn extension: Java access - global.javaImporter */ jlaskey@3: @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object javaImporter; jlaskey@3: jlaskey@3: /** Nashorn extension: global.Java Object constructor. */ jlaskey@3: @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE) jlaskey@3: public volatile Object javaApi; jlaskey@3: jlaskey@3: /** Nashorn extension: current script's file name */ jlaskey@3: @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public Object __FILE__; jlaskey@3: jlaskey@3: /** Nashorn extension: current script's directory */ jlaskey@3: @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public Object __DIR__; jlaskey@3: jlaskey@3: /** Nashorn extension: current source line number being executed */ jlaskey@3: @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) jlaskey@3: public Object __LINE__; jlaskey@3: jlaskey@3: /** Used as Date.prototype's default value */ jlaskey@3: public NativeDate DEFAULT_DATE; jlaskey@3: jlaskey@3: /** Used as RegExp.prototype's default value */ jlaskey@3: public NativeRegExp DEFAULT_REGEXP; jlaskey@3: jlaskey@3: /* jlaskey@3: * Built-in constructor objects: Even if user changes dynamic values of jlaskey@3: * "Object", "Array" etc., we still want to keep original values of these jlaskey@3: * constructors here. For example, we need to be able to create array, jlaskey@3: * regexp literals even after user overwrites global "Array" or "RegExp" jlaskey@3: * constructor - see also ECMA 262 spec. Annex D. jlaskey@3: */ jlaskey@3: private ScriptFunction builtinFunction; jlaskey@3: private ScriptFunction builtinObject; jlaskey@3: private ScriptFunction builtinArray; jlaskey@3: private ScriptFunction builtinBoolean; jlaskey@3: private ScriptFunction builtinDate; jlaskey@3: private ScriptObject builtinJSON; jlaskey@3: private ScriptFunction builtinJSAdapter; jlaskey@3: private ScriptObject builtinMath; jlaskey@3: private ScriptFunction builtinNumber; jlaskey@3: private ScriptFunction builtinRegExp; jlaskey@3: private ScriptFunction builtinString; jlaskey@3: private ScriptFunction builtinError; jlaskey@3: private ScriptFunction builtinEval; jlaskey@3: private ScriptFunction builtinEvalError; jlaskey@3: private ScriptFunction builtinRangeError; jlaskey@3: private ScriptFunction builtinReferenceError; jlaskey@3: private ScriptFunction builtinSyntaxError; jlaskey@3: private ScriptFunction builtinTypeError; jlaskey@3: private ScriptFunction builtinURIError; jlaskey@3: private ScriptObject builtinPackages; sundar@146: private ScriptObject builtinCom; sundar@146: private ScriptObject builtinEdu; jlaskey@3: private ScriptObject builtinJava; sundar@146: private ScriptObject builtinJavafx; jlaskey@3: private ScriptObject builtinJavax; sundar@146: private ScriptObject builtinOrg; jlaskey@3: private ScriptObject builtinJavaImporter; jlaskey@3: private ScriptObject builtinJavaApi; jlaskey@3: private ScriptObject builtinArrayBuffer; jlaskey@3: private ScriptObject builtinInt8Array; jlaskey@3: private ScriptObject builtinUint8Array; jlaskey@3: private ScriptObject builtinUint8ClampedArray; jlaskey@3: private ScriptObject builtinInt16Array; jlaskey@3: private ScriptObject builtinUint16Array; jlaskey@3: private ScriptObject builtinInt32Array; jlaskey@3: private ScriptObject builtinUint32Array; jlaskey@3: private ScriptObject builtinFloat32Array; jlaskey@3: private ScriptObject builtinFloat64Array; jlaskey@3: jlaskey@3: // Flag to indicate that a split method issued a return statement jlaskey@3: private int splitState = -1; jlaskey@3: jlaskey@3: // class cache jlaskey@3: private ClassCache classCache; jlaskey@3: hannesw@79: // Used to store the last RegExp result to support deprecated RegExp constructor properties hannesw@114: private RegExpResult lastRegExpResult; hannesw@79: jlaskey@3: private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class); jlaskey@3: private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class); jlaskey@3: private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class); jlaskey@3: private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class); jlaskey@75: private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class); jlaskey@3: sundar@82: private final Context context; sundar@82: jlaskey@3: /** jlaskey@3: * Constructor lagergren@89: * lagergren@89: * @param context the context jlaskey@3: */ sundar@82: public Global(final Context context) { sundar@82: this.context = context; jlaskey@3: this.setIsScope(); jlaskey@3: /* jlaskey@3: * Duplicate global's map and use it. This way the initial Map filled jlaskey@3: * by nasgen (referenced from static field in this class) is retained jlaskey@3: * 'as is'. This allows multiple globals to be used within a context. jlaskey@3: */ jlaskey@3: this.setMap(getMap().duplicate()); jlaskey@3: sundar@118: final int cacheSize = context.getEnv()._class_cache_size; jlaskey@3: if (cacheSize > 0) { jlaskey@3: classCache = new ClassCache(cacheSize); jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: /** sundar@82: * Script access to "current" Global instance jlaskey@3: * jlaskey@3: * @return the global singleton jlaskey@3: */ jlaskey@3: public static Global instance() { sundar@82: ScriptObject global = Context.getGlobal(); sundar@82: if (! (global instanceof Global)) { sundar@82: throw new IllegalStateException("no current global instance"); sundar@82: } sundar@82: return (Global)global; jlaskey@3: } jlaskey@3: jlaskey@3: /** sundar@118: * Script access to {@link ScriptEnvironment} sundar@118: * sundar@118: * @return the script environment sundar@118: */ sundar@118: static ScriptEnvironment getEnv() { sundar@118: return instance().context.getEnv(); sundar@118: } sundar@118: sundar@118: /** jlaskey@3: * Script access to {@link Context} jlaskey@3: * jlaskey@3: * @return the context jlaskey@3: */ sundar@41: static Context getThisContext() { sundar@82: return instance().context; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Script access check for strict mode jlaskey@3: * jlaskey@3: * @return true if strict mode enabled in {@link Global#getThisContext()} jlaskey@3: */ sundar@41: static boolean isStrict() { sundar@118: return getEnv()._strict; jlaskey@3: } jlaskey@3: jlaskey@3: // GlobalObject interface implementation jlaskey@3: jlaskey@3: @Override jlaskey@3: public void initBuiltinObjects() { jlaskey@3: if (this.builtinObject != null) { jlaskey@3: // already initialized, just return jlaskey@3: return; jlaskey@3: } jlaskey@3: sundar@41: init(); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) { attila@84: return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public Object wrapAsObject(final Object obj) { jlaskey@3: if (obj instanceof Boolean) { jlaskey@3: return new NativeBoolean((Boolean)obj); jlaskey@3: } else if (obj instanceof Number) { jlaskey@3: return new NativeNumber(((Number)obj).doubleValue()); jlaskey@3: } else if (obj instanceof String || obj instanceof ConsString) { jlaskey@3: return new NativeString((CharSequence)obj); jlaskey@3: } else if (obj instanceof Object[]) { // extension jlaskey@3: return new NativeArray((Object[])obj); jlaskey@3: } else if (obj instanceof double[]) { // extension jlaskey@3: return new NativeArray((double[])obj); jlaskey@3: } else if (obj instanceof long[]) { jlaskey@3: return new NativeArray((long[])obj); jlaskey@3: } else if (obj instanceof int[]) { jlaskey@3: return new NativeArray((int[])obj); jlaskey@3: } else { jlaskey@3: // FIXME: more special cases? Map? List? jlaskey@3: return obj; jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: @Override hannesw@51: public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { hannesw@51: if (self instanceof String || self instanceof ConsString) { hannesw@51: return NativeString.lookupPrimitive(request, self); hannesw@51: } else if (self instanceof Number) { hannesw@51: return NativeNumber.lookupPrimitive(request, self); hannesw@51: } else if (self instanceof Boolean) { hannesw@51: return NativeBoolean.lookupPrimitive(request, self); hannesw@51: } hannesw@51: throw new IllegalArgumentException("Unsupported primitive: " + self); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newObject() { jlaskey@3: return newEmptyInstance(); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public Object getDefaultValue(final ScriptObject sobj, final Class typeHint) { jlaskey@3: // When the [[DefaultValue]] internal method of O is called with no hint, jlaskey@3: // then it behaves as if the hint were Number, unless O is a Date object jlaskey@3: // in which case it behaves as if the hint were String. jlaskey@3: Class hint = typeHint; jlaskey@3: if (hint == null) { jlaskey@3: hint = Number.class; jlaskey@3: } jlaskey@3: jlaskey@3: try { jlaskey@3: if (hint == String.class) { jlaskey@3: jlaskey@3: final Object toString = TO_STRING.getGetter().invokeExact(sobj); jlaskey@3: if (toString instanceof ScriptFunction) { jlaskey@3: final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); jlaskey@3: if (JSType.isPrimitive(value)) { jlaskey@3: return value; jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); jlaskey@3: if (valueOf instanceof ScriptFunction) { jlaskey@3: final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); jlaskey@3: if (JSType.isPrimitive(value)) { jlaskey@3: return value; jlaskey@3: } jlaskey@3: } lagergren@112: throw typeError(this, "cannot.get.default.string"); jlaskey@3: } jlaskey@3: jlaskey@3: if (hint == Number.class) { jlaskey@3: final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); jlaskey@3: if (valueOf instanceof ScriptFunction) { jlaskey@3: final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); jlaskey@3: if (JSType.isPrimitive(value)) { jlaskey@3: return value; jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: final Object toString = TO_STRING.getGetter().invokeExact(sobj); jlaskey@3: if (toString instanceof ScriptFunction) { jlaskey@3: final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); jlaskey@3: if (JSType.isPrimitive(value)) { jlaskey@3: return value; jlaskey@3: } jlaskey@3: } jlaskey@3: lagergren@112: throw typeError(this, "cannot.get.default.number"); jlaskey@3: } jlaskey@3: } catch (final RuntimeException | Error e) { jlaskey@3: throw e; jlaskey@3: } catch (final Throwable t) { jlaskey@3: throw new RuntimeException(t); jlaskey@3: } jlaskey@3: jlaskey@3: return UNDEFINED; jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public boolean isError(final ScriptObject sobj) { jlaskey@3: final ScriptObject errorProto = getErrorPrototype(); jlaskey@3: ScriptObject proto = sobj.getProto(); jlaskey@3: while (proto != null) { jlaskey@3: if (proto == errorProto) { jlaskey@3: return true; jlaskey@3: } jlaskey@3: proto = proto.getProto(); jlaskey@3: } jlaskey@3: return false; jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newError(final String msg) { jlaskey@3: return new NativeError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newEvalError(final String msg) { jlaskey@3: return new NativeEvalError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newRangeError(final String msg) { jlaskey@3: return new NativeRangeError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newReferenceError(final String msg) { jlaskey@3: return new NativeReferenceError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newSyntaxError(final String msg) { jlaskey@3: return new NativeSyntaxError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newTypeError(final String msg) { jlaskey@3: return new NativeTypeError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public ScriptObject newURIError(final String msg) { jlaskey@3: return new NativeURIError(msg); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) { jlaskey@3: return new GenericPropertyDescriptor(configurable, enumerable); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) { jlaskey@3: return new DataPropertyDescriptor(configurable, enumerable, writable, value); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) { jlaskey@3: final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set); jlaskey@3: sundar@118: final boolean strict = context.getEnv()._strict; jlaskey@3: jlaskey@3: if (get == null) { jlaskey@3: desc.delete(PropertyDescriptor.GET, strict); jlaskey@3: } jlaskey@3: jlaskey@3: if (set == null) { jlaskey@3: desc.delete(PropertyDescriptor.SET, strict); jlaskey@3: } jlaskey@3: jlaskey@3: return desc; jlaskey@3: } jlaskey@3: jlaskey@3: jlaskey@3: /** jlaskey@3: * Cache for compiled script classes. jlaskey@3: */ jlaskey@3: @SuppressWarnings("serial") jlaskey@3: private static class ClassCache extends LinkedHashMap>> { jlaskey@3: private final int size; jlaskey@3: jlaskey@3: ClassCache(int size) { jlaskey@3: super(size, 0.75f, true); jlaskey@3: this.size = size; jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: protected boolean removeEldestEntry(final Map.Entry>> eldest) { jlaskey@3: return size() >= size; jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: // Class cache management jlaskey@3: @Override jlaskey@3: public Class findCachedClass(final Source source) { jlaskey@3: assert classCache != null : "Class cache used without being initialized"; jlaskey@3: SoftReference> ref = classCache.get(source); jlaskey@3: if (ref != null) { jlaskey@3: final Class clazz = ref.get(); jlaskey@3: if (clazz == null) { jlaskey@3: classCache.remove(source); jlaskey@3: } jlaskey@3: return clazz; jlaskey@3: } jlaskey@3: jlaskey@3: return null; jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public void cacheClass(final Source source, final Class clazz) { jlaskey@3: assert classCache != null : "Class cache used without being initialized"; jlaskey@3: classCache.put(source, new SoftReference>(clazz)); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * This is the eval used when 'indirect' eval call is made. jlaskey@3: * jlaskey@3: * var global = this; jlaskey@3: * global.eval("print('hello')"); jlaskey@3: * jlaskey@3: * @param self eval scope jlaskey@3: * @param str eval string jlaskey@3: * jlaskey@3: * @return the result of eval jlaskey@3: */ jlaskey@3: public static Object eval(final Object self, final Object str) { jlaskey@3: return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Direct eval jlaskey@3: * jlaskey@3: * @param self The scope of eval passed as 'self' jlaskey@3: * @param str Evaluated code jlaskey@3: * @param callThis "this" to be passed to the evaluated code jlaskey@3: * @param location location of the eval call jlaskey@3: * @param strict is eval called a strict mode code? jlaskey@3: * jlaskey@3: * @return the return value of the eval jlaskey@3: * jlaskey@3: * This is directly invoked from generated when eval(code) is called in user code jlaskey@3: */ jlaskey@3: public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) { jlaskey@3: if (!(str instanceof String || str instanceof ConsString)) { jlaskey@3: return str; jlaskey@3: } sundar@41: final Global global = Global.instance(); sundar@41: final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global; jlaskey@3: sundar@82: return global.context.eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict)); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Global print implementation - Nashorn extension jlaskey@3: * jlaskey@3: * @param self scope jlaskey@3: * @param objects arguments to print jlaskey@3: * jlaskey@3: * @return result of print (undefined) jlaskey@3: */ jlaskey@3: public static Object print(final Object self, final Object... objects) { jlaskey@3: return printImpl(false, objects); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Global println implementation - Nashorn extension jlaskey@3: * jlaskey@3: * @param self scope jlaskey@3: * @param objects arguments to print jlaskey@3: * jlaskey@3: * @return result of println (undefined) jlaskey@3: */ jlaskey@3: public static Object println(final Object self, final Object... objects) { jlaskey@3: return printImpl(true, objects); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Global load implementation - Nashorn extension jlaskey@3: * jlaskey@3: * @param self scope jlaskey@3: * @param source source to load jlaskey@3: * jlaskey@3: * @return result of load (undefined) jlaskey@3: * jlaskey@3: * @throws IOException if source could not be read jlaskey@3: */ jlaskey@3: public static Object load(final Object self, final Object source) throws IOException { sundar@41: final Global global = Global.instance(); sundar@41: final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global; sundar@82: return global.context.load(scope, source); jlaskey@3: } jlaskey@3: jlaskey@75: /** jlaskey@75: * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script jlaskey@75: * jlaskey@75: * @param self self reference jlaskey@75: * @param code exit code jlaskey@75: * jlaskey@75: * @return undefined (will never be reacheD) jlaskey@75: */ jlaskey@75: public static Object exit(final Object self, final Object code) { jlaskey@75: System.exit(JSType.toInt32(code)); jlaskey@75: return UNDEFINED; jlaskey@75: } jlaskey@75: jlaskey@3: ScriptObject getFunctionPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinFunction); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getObjectPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinObject); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinArray); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getBooleanPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinBoolean); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getNumberPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinNumber); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getDatePrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinDate); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getRegExpPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinRegExp); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getStringPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinString); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getEvalErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinEvalError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getRangeErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinRangeError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getReferenceErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinReferenceError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getSyntaxErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinSyntaxError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getTypeErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinTypeError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getURIErrorPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinURIError); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getJavaImporterPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinJavaImporter); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getJSAdapterPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinJSAdapter); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getArrayBufferPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinArrayBuffer); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getInt8ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinInt8Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getUint8ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinUint8Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getUint8ClampedArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinUint8ClampedArray); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getInt16ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinInt16Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getUint16ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinUint16Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getInt32ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinInt32Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getUint32ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinUint32Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getFloat32ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinFloat32Array); jlaskey@3: } jlaskey@3: jlaskey@3: ScriptObject getFloat64ArrayPrototype() { jlaskey@3: return ScriptFunction.getPrototype(builtinFloat64Array); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinArray() { jlaskey@3: return builtinArray; jlaskey@3: } jlaskey@3: jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin array has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinArray() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.array == instance.getBuiltinArray(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinBoolean() { jlaskey@3: return builtinBoolean; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin boolean has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinBoolean() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance._boolean == instance.getBuiltinBoolean(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinDate() { jlaskey@3: return builtinDate; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin date has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinDate() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.date == instance.getBuiltinDate(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinError() { jlaskey@3: return builtinError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.error == instance.getBuiltinError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinEvalError() { jlaskey@3: return builtinEvalError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin eval error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinEvalError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.evalError == instance.getBuiltinEvalError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinFunction() { jlaskey@3: return builtinFunction; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin function has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinFunction() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.function == instance.getBuiltinFunction(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinJSAdapter() { jlaskey@3: return builtinJSAdapter; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin JSAdapter has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinJSAdapter() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.jsadapter == instance.getBuiltinJSAdapter(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinJSON() { jlaskey@3: return builtinJSON; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin JSON has has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinJSON() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.json == instance.getBuiltinJSON(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinJava() { jlaskey@3: return builtinJava; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin Java has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinJava() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.java == instance.getBuiltinJava(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinJavax() { jlaskey@3: return builtinJavax; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin Javax has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinJavax() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.javax == instance.getBuiltinJavax(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinJavaImporter() { jlaskey@3: return builtinJavaImporter; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin Java importer has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinJavaImporter() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.javaImporter == instance.getBuiltinJavaImporter(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinMath() { jlaskey@3: return builtinMath; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin math has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinMath() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.math == instance.getBuiltinMath(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinNumber() { jlaskey@3: return builtinNumber; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin number has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinNumber() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.number == instance.getBuiltinNumber(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinObject() { jlaskey@3: return builtinObject; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin object has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinObject() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.object == instance.getBuiltinObject(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptObject getBuiltinPackages() { jlaskey@3: return builtinPackages; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin package has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinPackages() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.packages == instance.getBuiltinPackages(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinRangeError() { jlaskey@3: return builtinRangeError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin range error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinRangeError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.rangeError == instance.getBuiltinRangeError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinReferenceError() { jlaskey@3: return builtinReferenceError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin reference error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinReferenceError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.referenceError == instance.getBuiltinReferenceError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinRegExp() { jlaskey@3: return builtinRegExp; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin regexp has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinRegExp() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.regexp == instance.getBuiltinRegExp(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinString() { jlaskey@3: return builtinString; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin Java has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinString() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.string == instance.getBuiltinString(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinSyntaxError() { jlaskey@3: return builtinSyntaxError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin syntax error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinSyntaxError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.syntaxError == instance.getBuiltinSyntaxError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinTypeError() { jlaskey@3: return builtinTypeError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin type error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinTypeError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.typeError == instance.getBuiltinTypeError(); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction getBuiltinURIError() { jlaskey@3: return builtinURIError; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from compiled script code to test if builtin has been overridden jlaskey@3: * jlaskey@3: * @return true if builtin URI error has not been overridden jlaskey@3: */ jlaskey@3: public static boolean isBuiltinURIError() { jlaskey@3: final Global instance = Global.instance(); jlaskey@3: return instance.uriError == instance.getBuiltinURIError(); jlaskey@3: } jlaskey@3: jlaskey@3: @Override jlaskey@3: public String getClassName() { jlaskey@3: return "global"; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Copy function used to clone NativeRegExp objects. jlaskey@3: * jlaskey@3: * @param regexp a NativeRegExp to clone jlaskey@3: * jlaskey@3: * @return copy of the given regexp object jlaskey@3: */ jlaskey@3: public static Object regExpCopy(final Object regexp) { jlaskey@3: return new NativeRegExp((NativeRegExp)regexp); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Convert given object to NativeRegExp type. jlaskey@3: * jlaskey@3: * @param obj object to be converted jlaskey@3: * @return NativeRegExp instance jlaskey@3: */ jlaskey@3: public static NativeRegExp toRegExp(final Object obj) { jlaskey@3: if (obj instanceof NativeRegExp) { jlaskey@3: return (NativeRegExp)obj; jlaskey@3: } jlaskey@3: return new NativeRegExp(JSType.toString(obj)); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * ECMA 9.9 ToObject implementation jlaskey@3: * jlaskey@3: * @param obj an item for which to run ToObject jlaskey@3: * @return ToObject version of given item jlaskey@3: */ jlaskey@3: public static Object toObject(final Object obj) { jlaskey@3: if (obj == null || obj == UNDEFINED) { lagergren@112: throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); jlaskey@3: } jlaskey@3: jlaskey@3: if (obj instanceof ScriptObject) { jlaskey@3: return obj; jlaskey@3: } jlaskey@3: jlaskey@3: return instance().wrapAsObject(obj); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Allocate a new object array. jlaskey@3: * jlaskey@3: * @param initial object values. jlaskey@3: * @return the new array jlaskey@3: */ lagergren@66: public static NativeArray allocate(final Object[] initial) { jlaskey@3: return new NativeArray(initial); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Allocate a new number array. jlaskey@3: * jlaskey@3: * @param initial number values. jlaskey@3: * @return the new array jlaskey@3: */ lagergren@66: public static NativeArray allocate(final double[] initial) { jlaskey@3: return new NativeArray(initial); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Allocate a new long array. jlaskey@3: * jlaskey@3: * @param initial number values. jlaskey@3: * @return the new array jlaskey@3: */ lagergren@66: public static NativeArray allocate(final long[] initial) { jlaskey@3: return new NativeArray(initial); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Allocate a new integer array. jlaskey@3: * jlaskey@3: * @param initial number values. jlaskey@3: * @return the new array jlaskey@3: */ lagergren@66: public static NativeArray allocate(final int[] initial) { jlaskey@3: return new NativeArray(initial); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Allocate a new object array for arguments. jlaskey@3: * jlaskey@3: * @param arguments initial arguments passed. jlaskey@3: * @param callee reference to the function that uses arguments object jlaskey@3: * @param numParams actual number of declared parameters jlaskey@3: * jlaskey@3: * @return the new array jlaskey@3: */ attila@62: public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { jlaskey@3: return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Called from generated to check if given function is the builtin 'eval'. If jlaskey@3: * eval is used in a script, a lot of optimizations and assumptions cannot be done. jlaskey@3: * jlaskey@3: * @param fn function object that is checked jlaskey@3: * @return true if fn is the builtin eval jlaskey@3: */ jlaskey@3: public static boolean isEval(final Object fn) { jlaskey@3: return fn == Global.instance().builtinEval; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Create a new RegExp object. jlaskey@3: * jlaskey@3: * @param expression Regular expression. jlaskey@3: * @param options Search options. jlaskey@3: * jlaskey@3: * @return New RegExp object. jlaskey@3: */ jlaskey@3: public static Object newRegExp(final String expression, final String options) { jlaskey@3: if (options == null) { jlaskey@3: return new NativeRegExp(expression); jlaskey@3: } jlaskey@3: return new NativeRegExp(expression, options); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Get the object prototype jlaskey@3: * jlaskey@3: * @return the object prototype jlaskey@3: */ jlaskey@3: public static ScriptObject objectPrototype() { jlaskey@3: return Global.instance().getObjectPrototype(); jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Create a new empty object instance. jlaskey@3: * jlaskey@3: * @return New empty object. jlaskey@3: */ jlaskey@3: public static ScriptObject newEmptyInstance() { jlaskey@131: final ScriptObject sobj = new JO(); jlaskey@3: sobj.setProto(objectPrototype()); jlaskey@3: return sobj; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Check if a given object is a ScriptObject, raises an exception if this is jlaskey@3: * not the case jlaskey@3: * jlaskey@3: * @param obj and object to check jlaskey@3: */ jlaskey@3: public static void checkObject(final Object obj) { jlaskey@3: if (!(obj instanceof ScriptObject)) { lagergren@112: throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception jlaskey@3: * if this object is null or undefined. jlaskey@3: * jlaskey@3: * @param obj an object to check jlaskey@3: */ jlaskey@3: public static void checkObjectCoercible(final Object obj) { jlaskey@3: if (obj == null || obj == UNDEFINED) { lagergren@112: throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Get the current split state. jlaskey@3: * jlaskey@3: * @return current split state jlaskey@3: */ jlaskey@3: @Override jlaskey@3: public int getSplitState() { jlaskey@3: return splitState; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * Set the current split state. jlaskey@3: * jlaskey@3: * @param state current split state jlaskey@3: */ jlaskey@3: @Override jlaskey@3: public void setSplitState(final int state) { jlaskey@3: splitState = state; jlaskey@3: } jlaskey@3: jlaskey@3: private void init() { sundar@41: assert Context.getGlobal() == this : "this global is not set as current"; sundar@41: sundar@118: final ScriptEnvironment env = context.getEnv(); jlaskey@3: // initialize Function and Object constructor jlaskey@3: initFunctionAndObject(); jlaskey@3: jlaskey@3: // Now fix Global's own proto. jlaskey@3: this.setProto(getObjectPrototype()); jlaskey@3: jlaskey@3: // initialize global function properties jlaskey@3: this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL); jlaskey@3: jlaskey@3: this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT); jlaskey@3: this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT); jlaskey@3: this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN); jlaskey@3: this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE); jlaskey@3: this.encodeURI = ScriptFunctionImpl.makeFunction("encodeURI", GlobalFunctions.ENCODE_URI); jlaskey@3: this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); jlaskey@3: this.decodeURI = ScriptFunctionImpl.makeFunction("decodeURI", GlobalFunctions.DECODE_URI); jlaskey@3: this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); jlaskey@3: this.escape = ScriptFunctionImpl.makeFunction("escape", GlobalFunctions.ESCAPE); jlaskey@3: this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE); sundar@118: this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN); jlaskey@3: this.load = ScriptFunctionImpl.makeFunction("load", LOAD); jlaskey@75: this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT); jlaskey@75: this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT); jlaskey@3: jlaskey@3: // built-in constructors jlaskey@3: this.builtinArray = (ScriptFunction)initConstructor("Array"); jlaskey@3: this.builtinBoolean = (ScriptFunction)initConstructor("Boolean"); jlaskey@3: this.builtinDate = (ScriptFunction)initConstructor("Date"); jlaskey@3: this.builtinJSON = initConstructor("JSON"); jlaskey@3: this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter"); jlaskey@3: this.builtinMath = initConstructor("Math"); jlaskey@3: this.builtinNumber = (ScriptFunction)initConstructor("Number"); jlaskey@3: this.builtinRegExp = (ScriptFunction)initConstructor("RegExp"); jlaskey@3: this.builtinString = (ScriptFunction)initConstructor("String"); jlaskey@3: jlaskey@3: // initialize String.prototype.length to 0 jlaskey@3: // add String.prototype.length jlaskey@3: final ScriptObject stringPrototype = getStringPrototype(); jlaskey@3: stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); jlaskey@3: jlaskey@3: // add Array.prototype.length jlaskey@3: final ScriptObject arrayPrototype = getArrayPrototype(); sundar@132: arrayPrototype.addOwnProperty("length", Attribute.NOT_ENUMERABLE|Attribute.NOT_CONFIGURABLE, 0.0); jlaskey@3: jlaskey@3: this.DEFAULT_DATE = new NativeDate(Double.NaN); jlaskey@3: jlaskey@3: // initialize default regexp object jlaskey@3: this.DEFAULT_REGEXP = new NativeRegExp("(?:)"); jlaskey@3: jlaskey@3: // RegExp.prototype should behave like a RegExp object. So copy the jlaskey@3: // properties. jlaskey@3: final ScriptObject regExpProto = getRegExpPrototype(); jlaskey@3: regExpProto.addBoundProperties(DEFAULT_REGEXP); jlaskey@3: jlaskey@3: // Error stuff jlaskey@3: initErrorObjects(); jlaskey@3: jlaskey@3: // java access jlaskey@3: initJavaAccess(); jlaskey@3: jlaskey@3: initTypedArray(); jlaskey@3: sundar@118: if (env._scripting) { jlaskey@3: initScripting(); jlaskey@3: } jlaskey@3: sundar@41: if (Context.DEBUG && System.getSecurityManager() == null) { jlaskey@3: initDebug(); jlaskey@3: } jlaskey@3: jlaskey@3: copyBuiltins(); jlaskey@3: jlaskey@3: // initialized with strings so that typeof will work as expected. jlaskey@3: this.__FILE__ = ""; jlaskey@3: this.__DIR__ = ""; jlaskey@3: this.__LINE__ = 0.0; jlaskey@3: jlaskey@3: // expose script (command line) arguments as "arguments" property of global sundar@118: final List arguments = env.getArguments(); jlaskey@3: final Object argsObj = wrapAsObject(arguments.toArray()); jlaskey@3: jlaskey@3: addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj); sundar@118: if (env._scripting) { jlaskey@3: // synonym for "arguments" in scripting mode jlaskey@3: addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj); jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: private void initErrorObjects() { jlaskey@3: // Error objects jlaskey@3: this.builtinError = (ScriptFunction)initConstructor("Error"); jlaskey@3: final ScriptObject errorProto = getErrorPrototype(); jlaskey@3: final boolean strict = Global.isStrict(); jlaskey@3: jlaskey@3: // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName jlaskey@3: final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK); jlaskey@3: final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK); jlaskey@3: errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); jlaskey@3: final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER); jlaskey@3: final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER); jlaskey@3: errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); jlaskey@3: final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER); jlaskey@3: final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER); jlaskey@3: errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); jlaskey@3: final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME); jlaskey@3: final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME); jlaskey@3: errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); jlaskey@3: jlaskey@3: // ECMA 15.11.4.2 Error.prototype.name jlaskey@3: // Error.prototype.name = "Error"; jlaskey@3: errorProto.set(NativeError.NAME, "Error", strict); jlaskey@3: // ECMA 15.11.4.3 Error.prototype.message jlaskey@3: // Error.prototype.message = ""; jlaskey@3: errorProto.set(NativeError.MESSAGE, "", strict); jlaskey@3: jlaskey@3: this.builtinEvalError = initErrorSubtype("EvalError", errorProto); jlaskey@3: this.builtinRangeError = initErrorSubtype("RangeError", errorProto); jlaskey@3: this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); jlaskey@3: this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); jlaskey@3: this.builtinTypeError = initErrorSubtype("TypeError", errorProto); jlaskey@3: this.builtinURIError = initErrorSubtype("URIError", errorProto); jlaskey@3: } jlaskey@3: jlaskey@3: private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { jlaskey@3: final ScriptObject cons = initConstructor(name); jlaskey@3: final ScriptObject prototype = ScriptFunction.getPrototype(cons); jlaskey@3: final boolean strict = Global.isStrict(); jlaskey@3: prototype.set(NativeError.NAME, name, strict); jlaskey@3: prototype.set(NativeError.MESSAGE, "", strict); jlaskey@3: prototype.setProto(errorProto); jlaskey@3: return (ScriptFunction)cons; jlaskey@3: } jlaskey@3: jlaskey@3: private void initJavaAccess() { jlaskey@3: final ScriptObject objectProto = getObjectPrototype(); jlaskey@3: this.builtinPackages = new NativeJavaPackage("", objectProto); sundar@146: this.builtinCom = new NativeJavaPackage("com", objectProto); sundar@146: this.builtinEdu = new NativeJavaPackage("edu", objectProto); jlaskey@3: this.builtinJava = new NativeJavaPackage("java", objectProto); sundar@146: this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); jlaskey@3: this.builtinJavax = new NativeJavaPackage("javax", objectProto); sundar@146: this.builtinOrg = new NativeJavaPackage("org", objectProto); jlaskey@3: this.builtinJavaImporter = initConstructor("JavaImporter"); jlaskey@3: this.builtinJavaApi = initConstructor("Java"); jlaskey@3: } jlaskey@3: jlaskey@3: private void initScripting() { jlaskey@3: Object value; jlaskey@3: value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE); jlaskey@3: addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); jlaskey@3: sundar@52: value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY); sundar@52: addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); jlaskey@3: jlaskey@67: final String execName = ScriptingFunctions.EXEC_NAME; jlaskey@67: value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC); jlaskey@67: addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); jlaskey@67: jlaskey@3: // Nashorn extension: global.echo (scripting-mode-only) jlaskey@3: // alias for "print" jlaskey@3: value = get("print"); jlaskey@3: addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); jlaskey@3: jlaskey@3: // Nashorn extension: global.$OPTIONS (scripting-mode-only) sundar@136: final ScriptObject options = newEmptyInstance(); sundar@136: final ScriptEnvironment scriptEnv = context.getEnv(); sundar@136: copyOptions(options, scriptEnv); sundar@136: addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); jlaskey@67: jlaskey@67: // Nashorn extension: global.$ENV (scripting-mode-only) sundar@69: if (System.getSecurityManager() == null) { sundar@69: // do not fill $ENV if we have a security manager around sundar@69: // Retrieve current state of ENV variables. sundar@69: final ScriptObject env = newEmptyInstance(); sundar@69: env.putAll(System.getenv()); sundar@69: addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); sundar@69: } else { sundar@69: addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); sundar@69: } sundar@69: sundar@69: // add other special properties for exec support sundar@69: addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); sundar@69: addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); sundar@69: addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); jlaskey@3: } jlaskey@3: lagergren@139: private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { sundar@136: AccessController.doPrivileged(new PrivilegedAction() { lagergren@139: @Override sundar@136: public Void run() { sundar@136: for (Field f : scriptEnv.getClass().getFields()) { sundar@136: try { sundar@136: options.set(f.getName(), f.get(scriptEnv), false); sundar@136: } catch (final IllegalArgumentException | IllegalAccessException exp) { sundar@136: throw new RuntimeException(exp); sundar@136: } sundar@136: } sundar@136: return null; sundar@136: } sundar@136: }); sundar@136: } sundar@136: jlaskey@3: private void initTypedArray() { jlaskey@3: this.builtinArrayBuffer = initConstructor("ArrayBuffer"); jlaskey@3: this.builtinInt8Array = initConstructor("Int8Array"); jlaskey@3: this.builtinUint8Array = initConstructor("Uint8Array"); jlaskey@3: this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray"); jlaskey@3: this.builtinInt16Array = initConstructor("Int16Array"); jlaskey@3: this.builtinUint16Array = initConstructor("Uint16Array"); jlaskey@3: this.builtinInt32Array = initConstructor("Int32Array"); jlaskey@3: this.builtinUint32Array = initConstructor("Uint32Array"); jlaskey@3: this.builtinFloat32Array = initConstructor("Float32Array"); jlaskey@3: this.builtinFloat64Array = initConstructor("Float64Array"); jlaskey@3: } jlaskey@3: jlaskey@3: private void copyBuiltins() { jlaskey@3: this.array = this.builtinArray; jlaskey@3: this._boolean = this.builtinBoolean; jlaskey@3: this.date = this.builtinDate; jlaskey@3: this.error = this.builtinError; jlaskey@3: this.evalError = this.builtinEvalError; jlaskey@3: this.function = this.builtinFunction; jlaskey@3: this.jsadapter = this.builtinJSAdapter; jlaskey@3: this.json = this.builtinJSON; sundar@146: this.com = this.builtinCom; sundar@146: this.edu = this.builtinEdu; jlaskey@3: this.java = this.builtinJava; sundar@146: this.javafx = this.builtinJavafx; jlaskey@3: this.javax = this.builtinJavax; sundar@146: this.org = this.builtinOrg; jlaskey@3: this.javaImporter = this.builtinJavaImporter; jlaskey@3: this.javaApi = this.builtinJavaApi; jlaskey@3: this.math = this.builtinMath; jlaskey@3: this.number = this.builtinNumber; jlaskey@3: this.object = this.builtinObject; jlaskey@3: this.packages = this.builtinPackages; jlaskey@3: this.rangeError = this.builtinRangeError; jlaskey@3: this.referenceError = this.builtinReferenceError; jlaskey@3: this.regexp = this.builtinRegExp; jlaskey@3: this.string = this.builtinString; jlaskey@3: this.syntaxError = this.builtinSyntaxError; jlaskey@3: this.typeError = this.builtinTypeError; jlaskey@3: this.uriError = this.builtinURIError; jlaskey@3: this.arrayBuffer = this.builtinArrayBuffer; jlaskey@3: this.int8Array = this.builtinInt8Array; jlaskey@3: this.uint8Array = this.builtinUint8Array; jlaskey@3: this.uint8ClampedArray = this.builtinUint8ClampedArray; jlaskey@3: this.int16Array = this.builtinInt16Array; jlaskey@3: this.uint16Array = this.builtinUint16Array; jlaskey@3: this.int32Array = this.builtinInt32Array; jlaskey@3: this.uint32Array = this.builtinUint32Array; jlaskey@3: this.float32Array = this.builtinFloat32Array; jlaskey@3: this.float64Array = this.builtinFloat64Array; jlaskey@3: } jlaskey@3: jlaskey@3: private void initDebug() { jlaskey@3: this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug")); jlaskey@3: } jlaskey@3: jlaskey@3: @SuppressWarnings("resource") jlaskey@3: private static Object printImpl(final boolean newLine, final Object... objects) { sundar@118: final PrintWriter out = Global.getEnv().getOut(); jlaskey@3: jlaskey@3: boolean first = true; jlaskey@3: for (final Object object : objects) { jlaskey@3: if (first) { jlaskey@3: first = false; jlaskey@3: } else { jlaskey@3: out.print(' '); jlaskey@3: } jlaskey@3: jlaskey@3: out.print(JSType.toString(object)); jlaskey@3: } jlaskey@3: jlaskey@3: if (newLine) { jlaskey@3: out.println(); jlaskey@3: } jlaskey@3: jlaskey@3: out.flush(); jlaskey@3: jlaskey@3: return UNDEFINED; jlaskey@3: } jlaskey@3: jlaskey@3: /** jlaskey@3: * These classes are generated by nasgen tool and so we have to use jlaskey@3: * reflection to load and create new instance of these classes. jlaskey@3: */ jlaskey@3: private ScriptObject initConstructor(final String name) { jlaskey@3: try { jlaskey@3: // Assuming class name pattern for built-in JS constructors. jlaskey@3: final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects."); jlaskey@3: jlaskey@3: sb.append("Native"); jlaskey@3: sb.append(name); jlaskey@3: sb.append("$Constructor"); jlaskey@3: jlaskey@3: final Class funcClass = Class.forName(sb.toString()); jlaskey@3: final ScriptObject res = (ScriptObject)funcClass.newInstance(); jlaskey@3: jlaskey@3: if (res instanceof ScriptFunction) { jlaskey@3: // All global constructor prototypes are not-writable, jlaskey@3: // not-enumerable and not-configurable. jlaskey@3: final ScriptFunction func = (ScriptFunction)res; jlaskey@3: func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); jlaskey@3: } jlaskey@3: jlaskey@3: if (res.getProto() == null) { jlaskey@3: res.setProto(getObjectPrototype()); jlaskey@3: } jlaskey@3: jlaskey@3: return res; jlaskey@3: jlaskey@3: } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) { jlaskey@3: throw new RuntimeException(e); jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: // Function and Object constructors are inter-dependent. Also, jlaskey@3: // Function.prototype jlaskey@3: // functions are not properly initialized. We fix the references here. jlaskey@3: // NOTE: be careful if you want to re-order the operations here. You may jlaskey@3: // have jlaskey@3: // to play with object references carefully!! jlaskey@3: private void initFunctionAndObject() { jlaskey@3: // First-n-foremost is Function jlaskey@3: this.builtinFunction = (ScriptFunction)initConstructor("Function"); jlaskey@3: jlaskey@3: // create global anonymous function jlaskey@3: final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(); jlaskey@3: // need to copy over members of Function.prototype to anon function jlaskey@3: anon.addBoundProperties(getFunctionPrototype()); jlaskey@3: jlaskey@3: // Function.prototype === Object.getPrototypeOf(Function) === jlaskey@3: // jlaskey@3: builtinFunction.setProto(anon); jlaskey@3: builtinFunction.setPrototype(anon); jlaskey@3: anon.set("constructor", builtinFunction, anon.isStrict()); jlaskey@3: anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); jlaskey@3: jlaskey@3: // now initialize Object jlaskey@3: this.builtinObject = (ScriptFunction)initConstructor("Object"); jlaskey@3: final ScriptObject ObjectPrototype = getObjectPrototype(); jlaskey@3: // Object.getPrototypeOf(Function.prototype) === Object.prototype jlaskey@3: anon.setProto(ObjectPrototype); jlaskey@3: jlaskey@3: // Function valued properties of Function.prototype were not properly jlaskey@3: // initialized. Because, these were created before global.function and jlaskey@3: // global.object were not initialized. jlaskey@3: jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); jlaskey@3: for (final jdk.nashorn.internal.runtime.Property property : properties) { jlaskey@3: final Object key = property.getKey(); jlaskey@3: final Object value = builtinFunction.get(key); jlaskey@3: jlaskey@3: if (value instanceof ScriptFunction && value != anon) { jlaskey@3: final ScriptFunction func = (ScriptFunction)value; jlaskey@3: func.setProto(getFunctionPrototype()); jlaskey@3: final ScriptObject prototype = ScriptFunction.getPrototype(func); jlaskey@3: if (prototype != null) { jlaskey@3: prototype.setProto(ObjectPrototype); jlaskey@3: } jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: // For function valued properties of Object and Object.prototype, make jlaskey@3: // sure prototype's proto chain ends with Object.prototype jlaskey@3: for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { jlaskey@3: final Object key = property.getKey(); jlaskey@3: final Object value = builtinObject.get(key); jlaskey@3: jlaskey@3: if (value instanceof ScriptFunction) { jlaskey@3: final ScriptFunction func = (ScriptFunction)value; jlaskey@3: final ScriptObject prototype = ScriptFunction.getPrototype(func); jlaskey@3: if (prototype != null) { jlaskey@3: prototype.setProto(ObjectPrototype); jlaskey@3: } jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: properties = getObjectPrototype().getMap().getProperties(); jlaskey@3: for (final jdk.nashorn.internal.runtime.Property property : properties) { jlaskey@3: final Object key = property.getKey(); jlaskey@3: final Object value = ObjectPrototype.get(key); jlaskey@3: jlaskey@3: if (key.equals("constructor")) { jlaskey@3: continue; jlaskey@3: } jlaskey@3: jlaskey@3: if (value instanceof ScriptFunction) { jlaskey@3: final ScriptFunction func = (ScriptFunction)value; jlaskey@3: final ScriptObject prototype = ScriptFunction.getPrototype(func); jlaskey@3: if (prototype != null) { jlaskey@3: prototype.setProto(ObjectPrototype); jlaskey@3: } jlaskey@3: } jlaskey@3: } jlaskey@3: } jlaskey@3: jlaskey@3: jlaskey@3: private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { sundar@37: return MH.findStatic(MethodHandles.publicLookup(), Global.class, name, MH.type(rtype, types)); jlaskey@3: } hannesw@79: hannesw@114: RegExpResult getLastRegExpResult() { hannesw@114: return lastRegExpResult; hannesw@79: } hannesw@79: hannesw@114: void setLastRegExpResult(final RegExpResult regExpResult) { hannesw@114: this.lastRegExpResult = regExpResult; hannesw@79: } hannesw@79: jlaskey@3: }