/*
 * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.objects;

import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.isString;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import jdk.dynalink.CallSiteDescriptor;
import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Setter;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.FindProperty;
import jdk.nashorn.internal.runtime.GlobalConstants;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Specialization;
import jdk.nashorn.internal.runtime.Symbol;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.regexp.RegExpResult;
import jdk.nashorn.internal.scripts.JD;
import jdk.nashorn.internal.scripts.JO;
import jdk.nashorn.tools.ShellFunctions;

Representation of global scope.
/** * Representation of global scope. */
@ScriptClass("Global") public final class Global extends Scope { // This special value is used to flag a lazily initialized global property. private static final Object LAZY_SENTINEL = new Object(); // This serves as placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__) private static final Object LOCATION_PLACEHOLDER = new Object(); private static final String PACKAGE_PREFIX = "jdk.nashorn.internal.objects."; private InvokeByName TO_STRING; private InvokeByName VALUE_OF; /** * Optimistic builtin names that require switchpoint invalidation * upon assignment. Overly conservative, but works for now, to avoid * any complicated scope checks and especially heavy weight guards * like * * <pre> * public boolean setterGuard(final Object receiver) { * final Global global = Global.instance(); * final ScriptObject sobj = global.getFunctionPrototype(); * final Object apply = sobj.get("apply"); * return apply == receiver; * } * </pre> * * Naturally, checking for builtin classes like NativeFunction is cheaper, * it's when you start adding property checks for said builtins you have * problems with guard speed. */
Nashorn extension: arguments array
/** Nashorn extension: arguments array */
@Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public Object arguments;
ECMA 15.1.2.2 parseInt (string , radix)
/** ECMA 15.1.2.2 parseInt (string , radix) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object parseInt;
ECMA 15.1.2.3 parseFloat (string)
/** ECMA 15.1.2.3 parseFloat (string) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object parseFloat;
ECMA 15.1.2.4 isNaN (number)
/** ECMA 15.1.2.4 isNaN (number) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object isNaN;
ECMA 15.1.2.5 isFinite (number)
/** ECMA 15.1.2.5 isFinite (number) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object isFinite;
ECMA 15.1.3.3 encodeURI
/** ECMA 15.1.3.3 encodeURI */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object encodeURI;
ECMA 15.1.3.4 encodeURIComponent
/** ECMA 15.1.3.4 encodeURIComponent */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object encodeURIComponent;
ECMA 15.1.3.1 decodeURI
/** ECMA 15.1.3.1 decodeURI */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object decodeURI;
ECMA 15.1.3.2 decodeURIComponent
/** ECMA 15.1.3.2 decodeURIComponent */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object decodeURIComponent;
ECMA B.2.1 escape (string)
/** ECMA B.2.1 escape (string) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object escape;
ECMA B.2.2 unescape (string)
/** ECMA B.2.2 unescape (string) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object unescape;
Nashorn extension: global.print
/** Nashorn extension: global.print */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object print;
Nashorn extension: global.load
/** Nashorn extension: global.load */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object load;
Nashorn extension: global.loadWithNewGlobal
/** Nashorn extension: global.loadWithNewGlobal */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object loadWithNewGlobal;
Nashorn extension: global.exit
/** Nashorn extension: global.exit */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object exit;
Nashorn extension: global.quit
/** Nashorn extension: global.quit */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object quit;
Value property NaN of the Global Object - ECMA 15.1.1.1 NaN
/** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final double NaN = Double.NaN;
Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity
/** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final double Infinity = Double.POSITIVE_INFINITY;
Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined
/** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final Object undefined = UNDEFINED;
ECMA 15.1.2.1 eval(x)
/** ECMA 15.1.2.1 eval(x) */
@Property(attributes = Attribute.NOT_ENUMERABLE) public Object eval;
ECMA 15.1.4.1 Object constructor.
/** ECMA 15.1.4.1 Object constructor. */
@Property(name = "Object", attributes = Attribute.NOT_ENUMERABLE) public volatile Object object;
ECMA 15.1.4.2 Function constructor.
/** ECMA 15.1.4.2 Function constructor. */
@Property(name = "Function", attributes = Attribute.NOT_ENUMERABLE) public volatile Object function;
ECMA 15.1.4.3 Array constructor.
/** ECMA 15.1.4.3 Array constructor. */
@Property(name = "Array", attributes = Attribute.NOT_ENUMERABLE) public volatile Object array;
ECMA 15.1.4.4 String constructor
/** ECMA 15.1.4.4 String constructor */
@Property(name = "String", attributes = Attribute.NOT_ENUMERABLE) public volatile Object string;
ECMA 15.1.4.5 Boolean constructor
/** ECMA 15.1.4.5 Boolean constructor */
@Property(name = "Boolean", attributes = Attribute.NOT_ENUMERABLE) public volatile Object _boolean;
ECMA 15.1.4.6 - Number constructor
/** ECMA 15.1.4.6 - Number constructor */
@Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE) public volatile Object number;
Getter for ECMA 15.1.4.7 Date property
Params:
  • self – self reference
Returns:Date property value
/** * Getter for ECMA 15.1.4.7 Date property * * @param self self reference * @return Date property value */
@Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) public static Object getDate(final Object self) { final Global global = Global.instanceFrom(self); if (global.date == LAZY_SENTINEL) { global.date = global.getBuiltinDate(); } return global.date; }
Setter for ECMA 15.1.4.7 Date property
Params:
  • self – self reference
  • value – value for the Date property
/** * Setter for ECMA 15.1.4.7 Date property * * @param self self reference * @param value value for the Date property */
@Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE) public static void setDate(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.date = value; } private volatile Object date = LAZY_SENTINEL;
Getter for ECMA 15.1.4.8 RegExp property
Params:
  • self – self reference
Returns:RegExp property value
/** * Getter for ECMA 15.1.4.8 RegExp property * * @param self self reference * @return RegExp property value */
@Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) public static Object getRegExp(final Object self) { final Global global = Global.instanceFrom(self); if (global.regexp == LAZY_SENTINEL) { global.regexp = global.getBuiltinRegExp(); } return global.regexp; }
Setter for ECMA 15.1.4.8 RegExp property
Params:
  • self – self reference
  • value – value for the RegExp property
/** * Setter for ECMA 15.1.4.8 RegExp property * * @param self self reference * @param value value for the RegExp property */
@Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE) public static void setRegExp(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.regexp = value; } private volatile Object regexp = LAZY_SENTINEL;
Getter for ECMA 15.12 - The JSON property
Params:
  • self – self reference
Returns:the value of JSON property
/** * Getter for ECMA 15.12 - The JSON property * @param self self reference * @return the value of JSON property */
@Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) public static Object getJSON(final Object self) { final Global global = Global.instanceFrom(self); if (global.json == LAZY_SENTINEL) { global.json = global.getBuiltinJSON(); } return global.json; }
Setter for ECMA 15.12 - The JSON property
Params:
  • self – self reference
  • value – value for the JSON property
/** * Setter for ECMA 15.12 - The JSON property * @param self self reference * @param value value for the JSON property */
@Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE) public static void setJSON(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.json = value; } private volatile Object json = LAZY_SENTINEL;
Getter for Nashorn extension: global.JSAdapter
Params:
  • self – self reference
Returns:value of the JSAdapter property
/** * Getter for Nashorn extension: global.JSAdapter * @param self self reference * @return value of the JSAdapter property */
@Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) public static Object getJSAdapter(final Object self) { final Global global = Global.instanceFrom(self); if (global.jsadapter == LAZY_SENTINEL) { global.jsadapter = global.getBuiltinJSAdapter(); } return global.jsadapter; }
Setter for Nashorn extension: global.JSAdapter
Params:
  • self – self reference
  • value – value for the JSAdapter property
/** * Setter for Nashorn extension: global.JSAdapter * @param self self reference * @param value value for the JSAdapter property */
@Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE) public static void setJSAdapter(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.jsadapter = value; } private volatile Object jsadapter = LAZY_SENTINEL;
ECMA 15.8 - The Math object
/** ECMA 15.8 - The Math object */
@Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE) public volatile Object math;
Error object
/** Error object */
@Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE) public volatile Object error;
Getter for the EvalError property
Params:
  • self – self reference
Returns:the value of EvalError property
/** * Getter for the EvalError property * @param self self reference * @return the value of EvalError property */
@Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) public static Object getEvalError(final Object self) { final Global global = Global.instanceFrom(self); if (global.evalError == LAZY_SENTINEL) { global.evalError = global.getBuiltinEvalError(); } return global.evalError; }
Setter for the EvalError property
Params:
  • self – self reference
  • value – value of the EvalError property
/** * Setter for the EvalError property * @param self self reference * @param value value of the EvalError property */
@Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE) public static void setEvalError(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.evalError = value; } private volatile Object evalError = LAZY_SENTINEL;
Getter for the RangeError property.
Params:
  • self – self reference
Returns:the value of RangeError property
/** * Getter for the RangeError property. * @param self self reference * @return the value of RangeError property */
@Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) public static Object getRangeError(final Object self) { final Global global = Global.instanceFrom(self); if (global.rangeError == LAZY_SENTINEL) { global.rangeError = global.getBuiltinRangeError(); } return global.rangeError; }
Setter for the RangeError property.
Params:
  • self – self reference
  • value – value for the RangeError property
/** * Setter for the RangeError property. * @param self self reference * @param value value for the RangeError property */
@Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE) public static void setRangeError(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.rangeError = value; } private volatile Object rangeError = LAZY_SENTINEL;
ReferenceError object
/** ReferenceError object */
@Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE) public volatile Object referenceError;
SyntaxError object
/** SyntaxError object */
@Property(name = "SyntaxError", attributes = Attribute.NOT_ENUMERABLE) public volatile Object syntaxError;
TypeError object
/** TypeError object */
@Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE) public volatile Object typeError;
Getter for the URIError property.
Params:
  • self – self reference
Returns:the value of URIError property
/** * Getter for the URIError property. * @param self self reference * @return the value of URIError property */
@Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) public static Object getURIError(final Object self) { final Global global = Global.instanceFrom(self); if (global.uriError == LAZY_SENTINEL) { global.uriError = global.getBuiltinURIError(); } return global.uriError; }
Setter for the URIError property.
Params:
  • self – self reference
  • value – value for the URIError property
/** * Setter for the URIError property. * @param self self reference * @param value value for the URIError property */
@Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE) public static void setURIError(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.uriError = value; } private volatile Object uriError = LAZY_SENTINEL;
Getter for the ArrayBuffer property.
Params:
  • self – self reference
Returns:the value of the ArrayBuffer property
/** * Getter for the ArrayBuffer property. * @param self self reference * @return the value of the ArrayBuffer property */
@Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) public static Object getArrayBuffer(final Object self) { final Global global = Global.instanceFrom(self); if (global.arrayBuffer == LAZY_SENTINEL) { global.arrayBuffer = global.getBuiltinArrayBuffer(); } return global.arrayBuffer; }
Setter for the ArrayBuffer property.
Params:
  • self – self reference
  • value – value of the ArrayBuffer property
/** * Setter for the ArrayBuffer property. * @param self self reference * @param value value of the ArrayBuffer property */
@Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE) public static void setArrayBuffer(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.arrayBuffer = value; } private volatile Object arrayBuffer;
Getter for the DataView property.
Params:
  • self – self reference
Returns:the value of the DataView property
/** * Getter for the DataView property. * @param self self reference * @return the value of the DataView property */
@Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) public static Object getDataView(final Object self) { final Global global = Global.instanceFrom(self); if (global.dataView == LAZY_SENTINEL) { global.dataView = global.getBuiltinDataView(); } return global.dataView; }
Setter for the DataView property.
Params:
  • self – self reference
  • value – value of the DataView property
/** * Setter for the DataView property. * @param self self reference * @param value value of the DataView property */
@Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE) public static void setDataView(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.dataView = value; } private volatile Object dataView;
Getter for the Int8Array property.
Params:
  • self – self reference
Returns:the value of the Int8Array property.
/** * Getter for the Int8Array property. * @param self self reference * @return the value of the Int8Array property. */
@Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getInt8Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.int8Array == LAZY_SENTINEL) { global.int8Array = global.getBuiltinInt8Array(); } return global.int8Array; }
Setter for the Int8Array property.
Params:
  • self – self reference
  • value – value of the Int8Array property
/** * Setter for the Int8Array property. * @param self self reference * @param value value of the Int8Array property */
@Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE) public static void setInt8Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.int8Array = value; } private volatile Object int8Array;
Getter for the Uin8Array property.
Params:
  • self – self reference
Returns:the value of the Uint8Array property
/** * Getter for the Uin8Array property. * @param self self reference * @return the value of the Uint8Array property */
@Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getUint8Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.uint8Array == LAZY_SENTINEL) { global.uint8Array = global.getBuiltinUint8Array(); } return global.uint8Array; }
Setter for the Uin8Array property.
Params:
  • self – self reference
  • value – value of the Uin8Array property
/** * Setter for the Uin8Array property. * @param self self reference * @param value value of the Uin8Array property */
@Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE) public static void setUint8Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.uint8Array = value; } private volatile Object uint8Array;
Getter for the Uint8ClampedArray property.
Params:
  • self – self reference
Returns:the value of the Uint8ClampedArray property
/** * Getter for the Uint8ClampedArray property. * @param self self reference * @return the value of the Uint8ClampedArray property */
@Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) public static Object getUint8ClampedArray(final Object self) { final Global global = Global.instanceFrom(self); if (global.uint8ClampedArray == LAZY_SENTINEL) { global.uint8ClampedArray = global.getBuiltinUint8ClampedArray(); } return global.uint8ClampedArray; }
Setter for the Uint8ClampedArray property.
Params:
  • self – self reference
  • value – value of the Uint8ClampedArray property
/** * Setter for the Uint8ClampedArray property. * @param self self reference * @param value value of the Uint8ClampedArray property */
@Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE) public static void setUint8ClampedArray(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.uint8ClampedArray = value; } private volatile Object uint8ClampedArray;
Getter for the Int16Array property.
Params:
  • self – self reference
Returns:the value of the Int16Array property
/** * Getter for the Int16Array property. * @param self self reference * @return the value of the Int16Array property */
@Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getInt16Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.int16Array == LAZY_SENTINEL) { global.int16Array = global.getBuiltinInt16Array(); } return global.int16Array; }
Setter for the Int16Array property.
Params:
  • self – self reference
  • value – value of the Int16Array property
/** * Setter for the Int16Array property. * @param self self reference * @param value value of the Int16Array property */
@Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE) public static void setInt16Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.int16Array = value; } private volatile Object int16Array;
Getter for the Uint16Array property.
Params:
  • self – self reference
Returns:the value of the Uint16Array property
/** * Getter for the Uint16Array property. * @param self self reference * @return the value of the Uint16Array property */
@Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getUint16Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.uint16Array == LAZY_SENTINEL) { global.uint16Array = global.getBuiltinUint16Array(); } return global.uint16Array; }
Setter for the Uint16Array property.
Params:
  • self – self reference
  • value – value of the Uint16Array property
/** * Setter for the Uint16Array property. * @param self self reference * @param value value of the Uint16Array property */
@Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE) public static void setUint16Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.uint16Array = value; } private volatile Object uint16Array;
Getter for the Int32Array property.
Params:
  • self – self reference
Returns:the value of the Int32Array property
/** * Getter for the Int32Array property. * * @param self self reference * @return the value of the Int32Array property */
@Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getInt32Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.int32Array == LAZY_SENTINEL) { global.int32Array = global.getBuiltinInt32Array(); } return global.int32Array; }
Setter for the Int32Array property.
Params:
  • self – self reference
  • value – value of the Int32Array property
/** * Setter for the Int32Array property. * * @param self self reference * @param value value of the Int32Array property */
@Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE) public static void setInt32Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.int32Array = value; } private volatile Object int32Array;
Getter of the Uint32Array property.
Params:
  • self – self reference
Returns:the value of the Uint32Array property
/** * Getter of the Uint32Array property. * * @param self self reference * @return the value of the Uint32Array property */
@Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getUint32Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.uint32Array == LAZY_SENTINEL) { global.uint32Array = global.getBuiltinUint32Array(); } return global.uint32Array; }
Setter of the Uint32Array property.
Params:
  • self – self reference
  • value – value of the Uint32Array property
/** * Setter of the Uint32Array property. * * @param self self reference * @param value value of the Uint32Array property */
@Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE) public static void setUint32Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.uint32Array = value; } private volatile Object uint32Array;
Getter for the Float32Array property.
Params:
  • self – self reference
Returns:the value of the Float32Array property
/** * Getter for the Float32Array property. * * @param self self reference * @return the value of the Float32Array property */
@Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getFloat32Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.float32Array == LAZY_SENTINEL) { global.float32Array = global.getBuiltinFloat32Array(); } return global.float32Array; }
Setter for the Float32Array property.
Params:
  • self – self reference
  • value – value of the Float32Array property
/** * Setter for the Float32Array property. * * @param self self reference * @param value value of the Float32Array property */
@Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE) public static void setFloat32Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.float32Array = value; } private volatile Object float32Array;
Getter for the Float64Array property.
Params:
  • self – self reference
Returns:the value of the Float64Array property
/** * Getter for the Float64Array property. * * @param self self reference * @return the value of the Float64Array property */
@Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) public static Object getFloat64Array(final Object self) { final Global global = Global.instanceFrom(self); if (global.float64Array == LAZY_SENTINEL) { global.float64Array = global.getBuiltinFloat64Array(); } return global.float64Array; }
Setter for the Float64Array property.
Params:
  • self – self reference
  • value – value of the Float64Array property
/** * Setter for the Float64Array property. * * @param self self reference * @param value value of the Float64Array property */
@Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE) public static void setFloat64Array(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.float64Array = value; } private volatile Object float64Array;
Getter for the Symbol property.
Params:
  • self – self reference
Returns: the value of the Symbol property
/** * Getter for the Symbol property. * * @param self self reference * @return the value of the Symbol property */
@Getter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE) public static Object getSymbol(final Object self) { final Global global = Global.instanceFrom(self); if (global.symbol == LAZY_SENTINEL) { global.symbol = global.getBuiltinSymbol(); } return global.symbol; }
Setter for the Symbol property.
Params:
  • self – self reference
  • value – value of the Symbol property
/** * Setter for the Symbol property. * * @param self self reference * @param value value of the Symbol property */
@Setter(name = "Symbol", attributes = Attribute.NOT_ENUMERABLE) public static void setSymbol(final Object self, final Object value) { Global.instanceFrom(self).symbol = value; } private volatile Object symbol;
Getter for the Map property.
Params:
  • self – self reference
Returns: the value of the Map property
/** * Getter for the Map property. * * @param self self reference * @return the value of the Map property */
@Getter(name = "Map", attributes = Attribute.NOT_ENUMERABLE) public static Object getMap(final Object self) { final Global global = Global.instanceFrom(self); if (global.map == LAZY_SENTINEL) { global.map = global.getBuiltinMap(); } return global.map; }
Setter for the Map property.
Params:
  • self – self reference
  • value – value of the Map property
/** * Setter for the Map property. * * @param self self reference * @param value value of the Map property */
@Setter(name = "Map", attributes = Attribute.NOT_ENUMERABLE) public static void setMap(final Object self, final Object value) { Global.instanceFrom(self).map = value; } private volatile Object map;
Getter for the WeakMap property.
Params:
  • self – self reference
Returns: the value of the WeakMap property
/** * Getter for the WeakMap property. * * @param self self reference * @return the value of the WeakMap property */
@Getter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE) public static Object getWeakMap(final Object self) { final Global global = Global.instanceFrom(self); if (global.weakMap == LAZY_SENTINEL) { global.weakMap = global.getBuiltinWeakMap(); } return global.weakMap; }
Setter for the WeakMap property.
Params:
  • self – self reference
  • value – value of the WeakMap property
/** * Setter for the WeakMap property. * * @param self self reference * @param value value of the WeakMap property */
@Setter(name = "WeakMap", attributes = Attribute.NOT_ENUMERABLE) public static void setWeakMap(final Object self, final Object value) { Global.instanceFrom(self).weakMap = value; } private volatile Object weakMap;
Getter for the Set property.
Params:
  • self – self reference
Returns: the value of the Set property
/** * Getter for the Set property. * * @param self self reference * @return the value of the Set property */
@Getter(name = "Set", attributes = Attribute.NOT_ENUMERABLE) public static Object getSet(final Object self) { final Global global = Global.instanceFrom(self); if (global.set == LAZY_SENTINEL) { global.set = global.getBuiltinSet(); } return global.set; }
Setter for the Set property.
Params:
  • self – self reference
  • value – value of the Set property
/** * Setter for the Set property. * * @param self self reference * @param value value of the Set property */
@Setter(name = "Set", attributes = Attribute.NOT_ENUMERABLE) public static void setSet(final Object self, final Object value) { Global.instanceFrom(self).set = value; } private volatile Object set;
Getter for the WeakSet property.
Params:
  • self – self reference
Returns: the value of the WeakSet property
/** * Getter for the WeakSet property. * * @param self self reference * @return the value of the WeakSet property */
@Getter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE) public static Object getWeakSet(final Object self) { final Global global = Global.instanceFrom(self); if (global.weakSet == LAZY_SENTINEL) { global.weakSet = global.getBuiltinWeakSet(); } return global.weakSet; }
Setter for the WeakSet property.
Params:
  • self – self reference
  • value – value of the WeakSet property
/** * Setter for the WeakSet property. * * @param self self reference * @param value value of the WeakSet property */
@Setter(name = "WeakSet", attributes = Attribute.NOT_ENUMERABLE) public static void setWeakSet(final Object self, final Object value) { Global.instanceFrom(self).weakSet = value; } private volatile Object weakSet;
Nashorn extension: Java access - global.Packages
/** Nashorn extension: Java access - global.Packages */
@Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE) public volatile Object packages;
Nashorn extension: Java access - global.com
/** Nashorn extension: Java access - global.com */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object com;
Nashorn extension: Java access - global.edu
/** Nashorn extension: Java access - global.edu */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object edu;
Nashorn extension: Java access - global.java
/** Nashorn extension: Java access - global.java */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object java;
Nashorn extension: Java access - global.javafx
/** Nashorn extension: Java access - global.javafx */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object javafx;
Nashorn extension: Java access - global.javax
/** Nashorn extension: Java access - global.javax */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object javax;
Nashorn extension: Java access - global.org
/** Nashorn extension: Java access - global.org */
@Property(attributes = Attribute.NOT_ENUMERABLE) public volatile Object org;
Getter for the Nashorn extension: Java access - global.JavaImporter.
Params:
  • self – self reference
Returns:the value of the JavaImporter property
/** * Getter for the Nashorn extension: Java access - global.JavaImporter. * * @param self self reference * @return the value of the JavaImporter property */
@Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) public static Object getJavaImporter(final Object self) { final Global global = Global.instanceFrom(self); if (global.javaImporter == LAZY_SENTINEL) { global.javaImporter = global.getBuiltinJavaImporter(); } return global.javaImporter; }
Setter for the Nashorn extension: Java access - global.JavaImporter.
Params:
  • self – self reference
  • value – value of the JavaImporter property
/** * Setter for the Nashorn extension: Java access - global.JavaImporter. * * @param self self reference * @param value value of the JavaImporter property */
@Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE) public static void setJavaImporter(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.javaImporter = value; } private volatile Object javaImporter;
Getter for the Nashorn extension: global.Java property.
Params:
  • self – self reference
Returns:the value of the Java property
/** * Getter for the Nashorn extension: global.Java property. * * @param self self reference * @return the value of the Java property */
@Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) public static Object getJavaApi(final Object self) { final Global global = Global.instanceFrom(self); if (global.javaApi == LAZY_SENTINEL) { global.javaApi = global.getBuiltinJavaApi(); } return global.javaApi; }
Setter for the Nashorn extension: global.Java property.
Params:
  • self – self reference
  • value – value of the Java property
/** * Setter for the Nashorn extension: global.Java property. * * @param self self reference * @param value value of the Java property */
@Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE) public static void setJavaApi(final Object self, final Object value) { final Global global = Global.instanceFrom(self); global.javaApi = value; } private volatile Object javaApi;
Nashorn extension: current script's file name
/** Nashorn extension: current script's file name */
@Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final Object __FILE__ = LOCATION_PLACEHOLDER;
Nashorn extension: current script's directory
/** Nashorn extension: current script's directory */
@Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final Object __DIR__ = LOCATION_PLACEHOLDER;
Nashorn extension: current source line number being executed
/** Nashorn extension: current source line number being executed */
@Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) public static final Object __LINE__ = LOCATION_PLACEHOLDER; private volatile NativeDate DEFAULT_DATE;
Used as Date.prototype's default value
/** Used as Date.prototype's default value */
NativeDate getDefaultDate() { return DEFAULT_DATE; } private volatile NativeRegExp DEFAULT_REGEXP;
Used as RegExp.prototype's default value
/** Used as RegExp.prototype's default value */
NativeRegExp getDefaultRegExp() { return DEFAULT_REGEXP; } /* * Built-in constructor objects: Even if user changes dynamic values of * "Object", "Array" etc., we still want to keep original values of these * constructors here. For example, we need to be able to create array, * regexp literals even after user overwrites global "Array" or "RegExp" * constructor - see also ECMA 262 spec. Annex D. */ private ScriptFunction builtinFunction; private ScriptFunction builtinObject; private ScriptFunction builtinArray; private ScriptFunction builtinBoolean; private ScriptFunction builtinDate; private ScriptObject builtinJSON; private ScriptFunction builtinJSAdapter; private ScriptObject builtinMath; private ScriptFunction builtinNumber; private ScriptFunction builtinRegExp; private ScriptFunction builtinString; private ScriptFunction builtinError; private ScriptFunction builtinEval; private ScriptFunction builtinEvalError; private ScriptFunction builtinRangeError; private ScriptFunction builtinReferenceError; private ScriptFunction builtinSyntaxError; private ScriptFunction builtinTypeError; private ScriptFunction builtinURIError; private ScriptObject builtinPackages; private ScriptObject builtinCom; private ScriptObject builtinEdu; private ScriptObject builtinJava; private ScriptObject builtinJavafx; private ScriptObject builtinJavax; private ScriptObject builtinOrg; private ScriptFunction builtinJavaImporter; private ScriptObject builtinJavaApi; private ScriptFunction builtinArrayBuffer; private ScriptFunction builtinDataView; private ScriptFunction builtinInt8Array; private ScriptFunction builtinUint8Array; private ScriptFunction builtinUint8ClampedArray; private ScriptFunction builtinInt16Array; private ScriptFunction builtinUint16Array; private ScriptFunction builtinInt32Array; private ScriptFunction builtinUint32Array; private ScriptFunction builtinFloat32Array; private ScriptFunction builtinFloat64Array; private ScriptFunction builtinSymbol; private ScriptFunction builtinMap; private ScriptFunction builtinWeakMap; private ScriptFunction builtinSet; private ScriptFunction builtinWeakSet; private ScriptObject builtinIteratorPrototype; private ScriptObject builtinMapIteratorPrototype; private ScriptObject builtinSetIteratorPrototype; private ScriptObject builtinArrayIteratorPrototype; private ScriptObject builtinStringIteratorPrototype; private ScriptFunction builtInJavaExtend; private ScriptFunction builtInJavaTo; /* * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object */ private ScriptFunction typeErrorThrower; // Used to store the last RegExp result to support deprecated RegExp constructor properties private RegExpResult lastRegExpResult; private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class); private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class); private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class); private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class); private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class); private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class); private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class); private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class); // initialized by nasgen private static PropertyMap $nasgenmap$; // context to which this global belongs to private final Context context; // current ScriptContext to use - can be null. private ThreadLocal<ScriptContext> scontext; // current ScriptEngine associated - can be null. private ScriptEngine engine; // initial ScriptContext - usually null and only used for special case private volatile ScriptContext initscontext; // ES6 global lexical scope. private final LexicalScope lexicalScope; // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope. private SwitchPoint lexicalScopeSwitchPoint;
Set the current script context
Params:
  • ctxt – script context
/** * Set the current script context * @param ctxt script context */
public void setScriptContext(final ScriptContext ctxt) { assert scontext != null; scontext.set(ctxt); }
Get the current script context
Returns:current script context
/** * Get the current script context * @return current script context */
public ScriptContext getScriptContext() { assert scontext != null; return scontext.get(); }
Set the initial script context
Params:
  • ctxt – initial script context
/** * Set the initial script context * @param ctxt initial script context */
public void setInitScriptContext(final ScriptContext ctxt) { this.initscontext = ctxt; } private ScriptContext currentContext() { final ScriptContext sc = scontext != null? scontext.get() : null; if (sc != null) { return sc; } else if (initscontext != null) { return initscontext; } return engine != null? engine.getContext() : null; } @Override protected Context getContext() { return context; } @Override protected boolean useDualFields() { return context.useDualFields(); } // performs initialization checks for Global constructor and returns the // PropertyMap, if everything is fine. private static PropertyMap checkAndGetMap(final Context context) { // security check first final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL)); } Objects.requireNonNull(context); return $nasgenmap$; }
Constructor
Params:
  • context – the context
/** * Constructor * * @param context the context */
public Global(final Context context) { super(checkAndGetMap(context)); this.context = context; this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null; }
Script access to "current" Global instance
Returns:the global singleton
/** * Script access to "current" Global instance * * @return the global singleton */
public static Global instance() { return Objects.requireNonNull(Context.getGlobal()); } private static Global instanceFrom(final Object self) { return self instanceof Global? (Global)self : instance(); }
Check if we have a Global instance
Returns:true if one exists
/** * Check if we have a Global instance * @return true if one exists */
public static boolean hasInstance() { return Context.getGlobal() != null; }
Script access to ScriptEnvironment
Returns:the script environment
/** * Script access to {@link ScriptEnvironment} * * @return the script environment */
static ScriptEnvironment getEnv() { return instance().getContext().getEnv(); }
Script access to Context
Returns:the context
/** * Script access to {@link Context} * * @return the context */
static Context getThisContext() { return instance().getContext(); } // Runtime interface to Global
Is there a class filter in the current Context?
Returns:class filter
/** * Is there a class filter in the current Context? * @return class filter */
public ClassFilter getClassFilter() { return context.getClassFilter(); }
Is this global of the given Context?
Params:
  • ctxt – the context
Returns:true if this global belongs to the given Context
/** * Is this global of the given Context? * @param ctxt the context * @return true if this global belongs to the given Context */
public boolean isOfContext(final Context ctxt) { return this.context == ctxt; }
Does this global belong to a strict Context?
Returns:true if this global belongs to a strict Context
/** * Does this global belong to a strict Context? * @return true if this global belongs to a strict Context */
public boolean isStrictContext() { return context.getEnv()._strict; }
Initialize standard builtin objects like "Object", "Array", "Function" etc. as well as our extension builtin objects like "Java", "JSAdapter" as properties of the global scope object.
Params:
  • eng – ScriptEngine to initialize
/** * Initialize standard builtin objects like "Object", "Array", "Function" etc. * as well as our extension builtin objects like "Java", "JSAdapter" as properties * of the global scope object. * * @param eng ScriptEngine to initialize */
public void initBuiltinObjects(final ScriptEngine eng) { if (this.builtinObject != null) { // already initialized, just return return; } TO_STRING = new InvokeByName("toString", ScriptObject.class); VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); this.engine = eng; if (this.engine != null) { this.scontext = new ThreadLocal<>(); } init(eng); }
Wrap a Java object as corresponding script object
Params:
  • obj – object to wrap
Returns: wrapped object
/** * Wrap a Java object as corresponding script object * * @param obj object to wrap * @return wrapped object */
public Object wrapAsObject(final Object obj) { if (obj instanceof Boolean) { return new NativeBoolean((Boolean)obj, this); } else if (obj instanceof Number) { return new NativeNumber(((Number)obj).doubleValue(), this); } else if (isString(obj)) { return new NativeString((CharSequence)obj, this); } else if (obj instanceof Object[]) { // extension return new NativeArray(ArrayData.allocate((Object[])obj), this); } else if (obj instanceof double[]) { // extension return new NativeArray(ArrayData.allocate((double[])obj), this); } else if (obj instanceof int[]) { return new NativeArray(ArrayData.allocate((int[]) obj), this); } else if (obj instanceof ArrayData) { return new NativeArray((ArrayData) obj, this); } else if (obj instanceof Symbol) { return new NativeSymbol((Symbol) obj, this); } else { // FIXME: more special cases? Map? List? return obj; } }
Lookup helper for JS primitive types
Params:
  • request – the link request for the dynamic call site.
  • self – self reference
Returns:guarded invocation
/** * Lookup helper for JS primitive types * * @param request the link request for the dynamic call site. * @param self self reference * * @return guarded invocation */
public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) { if (isString(self)) { return NativeString.lookupPrimitive(request, self); } else if (self instanceof Number) { return NativeNumber.lookupPrimitive(request, self); } else if (self instanceof Boolean) { return NativeBoolean.lookupPrimitive(request, self); } else if (self instanceof Symbol) { return NativeSymbol.lookupPrimitive(request, self); } throw new IllegalArgumentException("Unsupported primitive: " + self); }
Returns a method handle that creates a wrapper object for a JS primitive value.
Params:
  • self – receiver object
Returns:method handle to create wrapper objects for primitive receiver
/** * Returns a method handle that creates a wrapper object for a JS primitive value. * * @param self receiver object * @return method handle to create wrapper objects for primitive receiver */
public static MethodHandle getPrimitiveWrapFilter(final Object self) { if (isString(self)) { return NativeString.WRAPFILTER; } else if (self instanceof Number) { return NativeNumber.WRAPFILTER; } else if (self instanceof Boolean) { return NativeBoolean.WRAPFILTER; } throw new IllegalArgumentException("Unsupported primitive: " + self); }
Create a new empty script object
Returns:the new ScriptObject
/** * Create a new empty script object * * @return the new ScriptObject */
public ScriptObject newObject() { return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype()); }
Default value of given type
Params:
  • sobj – script object
  • typeHint – type hint
Returns:default value
/** * Default value of given type * * @param sobj script object * @param typeHint type hint * * @return default value */
public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) { // When the [[DefaultValue]] internal method of O is called with no hint, // then it behaves as if the hint were Number, unless O is a Date object // in which case it behaves as if the hint were String. Class<?> hint = typeHint; if (hint == null) { hint = Number.class; } try { if (hint == String.class) { final Object toString = TO_STRING.getGetter().invokeExact(sobj); if (Bootstrap.isCallable(toString)) { final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); if (JSType.isPrimitive(value)) { return value; } } final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); if (Bootstrap.isCallable(valueOf)) { final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); if (JSType.isPrimitive(value)) { return value; } } throw typeError(this, "cannot.get.default.string"); } if (hint == Number.class) { final Object valueOf = VALUE_OF.getGetter().invokeExact(sobj); if (Bootstrap.isCallable(valueOf)) { final Object value = VALUE_OF.getInvoker().invokeExact(valueOf, sobj); if (JSType.isPrimitive(value)) { return value; } } final Object toString = TO_STRING.getGetter().invokeExact(sobj); if (Bootstrap.isCallable(toString)) { final Object value = TO_STRING.getInvoker().invokeExact(toString, sobj); if (JSType.isPrimitive(value)) { return value; } } throw typeError(this, "cannot.get.default.number"); } } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { throw new RuntimeException(t); } return UNDEFINED; }
Is the given ScriptObject an ECMAScript Error object?
Params:
  • sobj – the object being checked
Returns:true if sobj is an Error object
/** * Is the given ScriptObject an ECMAScript Error object? * * @param sobj the object being checked * @return true if sobj is an Error object */
public boolean isError(final ScriptObject sobj) { final ScriptObject errorProto = getErrorPrototype(); ScriptObject proto = sobj.getProto(); while (proto != null) { if (proto == errorProto) { return true; } proto = proto.getProto(); } return false; }
Create a new ECMAScript Error object.
Params:
  • msg – error message
Returns:newly created Error object
/** * Create a new ECMAScript Error object. * * @param msg error message * @return newly created Error object */
public ScriptObject newError(final String msg) { return new NativeError(msg, this); }
Create a new ECMAScript EvalError object.
Params:
  • msg – error message
Returns:newly created EvalError object
/** * Create a new ECMAScript EvalError object. * * @param msg error message * @return newly created EvalError object */
public ScriptObject newEvalError(final String msg) { return new NativeEvalError(msg, this); }
Create a new ECMAScript RangeError object.
Params:
  • msg – error message
Returns:newly created RangeError object
/** * Create a new ECMAScript RangeError object. * * @param msg error message * @return newly created RangeError object */
public ScriptObject newRangeError(final String msg) { return new NativeRangeError(msg, this); }
Create a new ECMAScript ReferenceError object.
Params:
  • msg – error message
Returns:newly created ReferenceError object
/** * Create a new ECMAScript ReferenceError object. * * @param msg error message * @return newly created ReferenceError object */
public ScriptObject newReferenceError(final String msg) { return new NativeReferenceError(msg, this); }
Create a new ECMAScript SyntaxError object.
Params:
  • msg – error message
Returns:newly created SyntaxError object
/** * Create a new ECMAScript SyntaxError object. * * @param msg error message * @return newly created SyntaxError object */
public ScriptObject newSyntaxError(final String msg) { return new NativeSyntaxError(msg, this); }
Create a new ECMAScript TypeError object.
Params:
  • msg – error message
Returns:newly created TypeError object
/** * Create a new ECMAScript TypeError object. * * @param msg error message * @return newly created TypeError object */
public ScriptObject newTypeError(final String msg) { return new NativeTypeError(msg, this); }
Create a new ECMAScript URIError object.
Params:
  • msg – error message
Returns:newly created URIError object
/** * Create a new ECMAScript URIError object. * * @param msg error message * @return newly created URIError object */
public ScriptObject newURIError(final String msg) { return new NativeURIError(msg, this); }
Create a new ECMAScript GenericDescriptor object.
Params:
  • configurable – is the property configurable?
  • enumerable – is the property enumerable?
Returns:newly created GenericDescriptor object
/** * Create a new ECMAScript GenericDescriptor object. * * @param configurable is the property configurable? * @param enumerable is the property enumerable? * @return newly created GenericDescriptor object */
public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) { return new GenericPropertyDescriptor(configurable, enumerable, this); }
Create a new ECMAScript DatePropertyDescriptor object.
Params:
  • value – of the data property
  • configurable – is the property configurable?
  • enumerable – is the property enumerable?
  • writable – is the property writable?
Returns:newly created DataPropertyDescriptor object
/** * Create a new ECMAScript DatePropertyDescriptor object. * * @param value of the data property * @param configurable is the property configurable? * @param enumerable is the property enumerable? * @param writable is the property writable? * @return newly created DataPropertyDescriptor object */
public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) { return new DataPropertyDescriptor(configurable, enumerable, writable, value, this); }
Create a new ECMAScript AccessorPropertyDescriptor object.
Params:
  • get – getter function of the user accessor property
  • set – setter function of the user accessor property
  • configurable – is the property configurable?
  • enumerable – is the property enumerable?
Returns:newly created AccessorPropertyDescriptor object
/** * Create a new ECMAScript AccessorPropertyDescriptor object. * * @param get getter function of the user accessor property * @param set setter function of the user accessor property * @param configurable is the property configurable? * @param enumerable is the property enumerable? * @return newly created AccessorPropertyDescriptor object */
public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) { final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this); if (get == null) { desc.delete(PropertyDescriptor.GET, false); } if (set == null) { desc.delete(PropertyDescriptor.SET, false); } return desc; } private <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) { final T obj = map.get(key); if (obj != null) { return obj; } final Global oldGlobal = Context.getGlobal(); final boolean differentGlobal = oldGlobal != this; try { if (differentGlobal) { Context.setGlobal(this); } final T newObj = creator.call(); final T existingObj = map.putIfAbsent(key, newObj); return existingObj != null ? existingObj : newObj; } catch (final Exception exp) { throw new RuntimeException(exp); } finally { if (differentGlobal) { Context.setGlobal(oldGlobal); } } } private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
Get cached InvokeByName object for the given key
Params:
  • key – key to be associated with InvokeByName object
  • creator – if InvokeByName is absent 'creator' is called to make one (lazy init)
Returns:InvokeByName object associated with the key.
/** * Get cached InvokeByName object for the given key * @param key key to be associated with InvokeByName object * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init) * @return InvokeByName object associated with the key. */
public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) { return getLazilyCreatedValue(key, creator, namedInvokers); } private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
Get cached dynamic method handle for the given key
Params:
  • key – key to be associated with dynamic method handle
  • creator – if method handle is absent 'creator' is called to make one (lazy init)
Returns:dynamic method handle associated with the key.
/** * Get cached dynamic method handle for the given key * @param key key to be associated with dynamic method handle * @param creator if method handle is absent 'creator' is called to make one (lazy init) * @return dynamic method handle associated with the key. */
public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) { return getLazilyCreatedValue(key, creator, dynamicInvokers); }
Hook to search missing variables in ScriptContext if available
Params:
  • self – used to detect if scope call or not (this function is 'strict')
  • name – name of the variable missing
Returns:value of the missing variable or undefined (or TypeError for scope search)
/** * Hook to search missing variables in ScriptContext if available * @param self used to detect if scope call or not (this function is 'strict') * @param name name of the variable missing * @return value of the missing variable or undefined (or TypeError for scope search) */
public static Object __noSuchProperty__(final Object self, final Object name) { final Global global = Global.instance(); final ScriptContext sctxt = global.currentContext(); final String nameStr = name.toString(); if (sctxt != null) { final int scope = sctxt.getAttributesScope(nameStr); if (scope != -1) { return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global); } } if ("context".equals(nameStr)) { return sctxt; } else if ("engine".equals(nameStr)) { // expose "engine" variable only when there is no security manager // or when no class filter is set. if (System.getSecurityManager() == null || global.getClassFilter() == null) { return global.engine; } } if (self == UNDEFINED) { // scope access and so throw ReferenceError throw referenceError(global, "not.defined", nameStr); } return UNDEFINED; }
This is the eval used when 'indirect' eval call is made. var global = this; global.eval("print('hello')");
Params:
  • self – eval scope
  • str – eval string
Returns:the result of eval
/** * This is the eval used when 'indirect' eval call is made. * * var global = this; * global.eval("print('hello')"); * * @param self eval scope * @param str eval string * * @return the result of eval */
public static Object eval(final Object self, final Object str) { return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false); }
Direct eval
Params:
  • self – The scope of eval passed as 'self'
  • str – Evaluated code
  • callThis – "this" to be passed to the evaluated code
  • location – location of the eval call
  • strict – is eval called from a strict mode code?
Returns:the return value of the eval This is directly invoked from generated when eval(code) is called in user code
/** * Direct eval * * @param self The scope of eval passed as 'self' * @param str Evaluated code * @param callThis "this" to be passed to the evaluated code * @param location location of the eval call * @param strict is eval called from a strict mode code? * * @return the return value of the eval * * This is directly invoked from generated when eval(code) is called in user code */
public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) { if (!isString(str)) { return str; } final Global global = Global.instanceFrom(self); final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global; return global.getContext().eval(scope, str.toString(), callThis, location, strict, true); }
Global print implementation - Nashorn extension
Params:
  • self – scope
  • objects – arguments to print
Returns:result of print (undefined)
/** * Global print implementation - Nashorn extension * * @param self scope * @param objects arguments to print * * @return result of print (undefined) */
public static Object print(final Object self, final Object... objects) { return Global.instanceFrom(self).printImpl(false, objects); }
Global println implementation - Nashorn extension
Params:
  • self – scope
  • objects – arguments to print
Returns:result of println (undefined)
/** * Global println implementation - Nashorn extension * * @param self scope * @param objects arguments to print * * @return result of println (undefined) */
public static Object println(final Object self, final Object... objects) { return Global.instanceFrom(self).printImpl(true, objects); }
Global load implementation - Nashorn extension.

load builtin loads the given script. Script source can be a URL or a File or a script object with name and script properties. Evaluated code gets global object "this" and uses global object as scope for evaluation.

If self is undefined or null or global, then global object is used as scope as well as "this" for the evaluated code. If self is any other object, then it is indirect load call. With indirect load call, the properties of scope are available to evaluated script as variables. Also, global scope properties are accessible. Any var, function definition in evaluated script goes into an object that is not accessible to user scripts.

Thus the indirect load call is equivalent to the following:

(function (scope, source) {
   with(scope) {
       eval(<script_from_source>);
   }
})(self, source);

Params:
  • self – scope to use for the script evaluation
  • source – script source
Throws:
Returns:result of load (may be undefined)
/** * Global load implementation - Nashorn extension. * * <p> * load builtin loads the given script. Script source can be a URL or a File * or a script object with name and script properties. Evaluated code gets * global object "this" and uses global object as scope for evaluation. * </p> * <p> * If self is undefined or null or global, then global object is used * as scope as well as "this" for the evaluated code. If self is any other * object, then it is indirect load call. With indirect load call, the * properties of scope are available to evaluated script as variables. Also, * global scope properties are accessible. Any var, function definition in * evaluated script goes into an object that is not accessible to user scripts. * </p> * Thus the indirect load call is equivalent to the following: * <pre> * <code> * (function (scope, source) { * with(scope) { * eval(&lt;script_from_source&gt;); * } * })(self, source); * </code> * </pre> * * @param self scope to use for the script evaluation * @param source script source * * @return result of load (may be undefined) * * @throws IOException if source could not be read */
public static Object load(final Object self, final Object source) throws IOException { final Global global = Global.instanceFrom(self); return global.getContext().load(self, source); }
Global loadWithNewGlobal implementation - Nashorn extension. loadWithNewGlobal builtin loads the given script from a URL or a File or a script object with name and script properties. Evaluated code gets new global object "this" and uses that new global object as scope for evaluation.
Params:
  • self – self This value is ignored by this function
  • args – optional arguments to be passed to the loaded script
Throws:
Returns:result of load (may be undefined)
/** * Global loadWithNewGlobal implementation - Nashorn extension. * * loadWithNewGlobal builtin loads the given script from a URL or a File * or a script object with name and script properties. Evaluated code gets * new global object "this" and uses that new global object as scope for evaluation. * * @param self self This value is ignored by this function * @param args optional arguments to be passed to the loaded script * * @return result of load (may be undefined) * * @throws IOException if source could not be read */
public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException { final Global global = Global.instanceFrom(self); final int length = args.length; final boolean hasArgs = 0 < length; final Object from = hasArgs ? args[0] : UNDEFINED; final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args; return global.getContext().loadWithNewGlobal(from, arguments); }
Global exit and quit implementation - Nashorn extension: perform a System.exit call from the script
Params:
  • self – self reference
  • code – exit code
Returns:undefined (will never be reached)
/** * Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script * * @param self self reference * @param code exit code * * @return undefined (will never be reached) */
public static Object exit(final Object self, final Object code) { System.exit(JSType.toInt32(code)); return UNDEFINED; } // builtin prototype accessors
Get the builtin Object prototype.
Returns:the Object prototype.
/** * Get the builtin Object prototype. * @return the Object prototype. */
public ScriptObject getObjectPrototype() { return ScriptFunction.getPrototype(builtinObject); }
Get the builtin Function prototype.
Returns:the Function prototype.
/** * Get the builtin Function prototype. * @return the Function prototype. */
public ScriptObject getFunctionPrototype() { return ScriptFunction.getPrototype(builtinFunction); }
Get the builtin Array prototype.
Returns:the Array prototype
/** * Get the builtin Array prototype. * @return the Array prototype */
public ScriptObject getArrayPrototype() { return ScriptFunction.getPrototype(builtinArray); } ScriptObject getBooleanPrototype() { return ScriptFunction.getPrototype(builtinBoolean); } ScriptObject getNumberPrototype() { return ScriptFunction.getPrototype(builtinNumber); } ScriptObject getDatePrototype() { return ScriptFunction.getPrototype(getBuiltinDate()); } ScriptObject getRegExpPrototype() { return ScriptFunction.getPrototype(getBuiltinRegExp()); } ScriptObject getStringPrototype() { return ScriptFunction.getPrototype(builtinString); } ScriptObject getErrorPrototype() { return ScriptFunction.getPrototype(builtinError); } ScriptObject getEvalErrorPrototype() { return ScriptFunction.getPrototype(getBuiltinEvalError()); } ScriptObject getRangeErrorPrototype() { return ScriptFunction.getPrototype(getBuiltinRangeError()); } ScriptObject getReferenceErrorPrototype() { return ScriptFunction.getPrototype(builtinReferenceError); } ScriptObject getSyntaxErrorPrototype() { return ScriptFunction.getPrototype(builtinSyntaxError); } ScriptObject getTypeErrorPrototype() { return ScriptFunction.getPrototype(builtinTypeError); } ScriptObject getURIErrorPrototype() { return ScriptFunction.getPrototype(getBuiltinURIError()); } ScriptObject getJavaImporterPrototype() { return ScriptFunction.getPrototype(getBuiltinJavaImporter()); } ScriptObject getJSAdapterPrototype() { return ScriptFunction.getPrototype(getBuiltinJSAdapter()); } ScriptObject getSymbolPrototype() { return ScriptFunction.getPrototype(getBuiltinSymbol()); } ScriptObject getMapPrototype() { return ScriptFunction.getPrototype(getBuiltinMap()); } ScriptObject getWeakMapPrototype() { return ScriptFunction.getPrototype(getBuiltinWeakMap()); } ScriptObject getSetPrototype() { return ScriptFunction.getPrototype(getBuiltinSet()); } ScriptObject getWeakSetPrototype() { return ScriptFunction.getPrototype(getBuiltinWeakSet()); } ScriptObject getIteratorPrototype() { if (builtinIteratorPrototype == null) { builtinIteratorPrototype = initPrototype("AbstractIterator", getObjectPrototype()); } return builtinIteratorPrototype; } ScriptObject getMapIteratorPrototype() { if (builtinMapIteratorPrototype == null) { builtinMapIteratorPrototype = initPrototype("MapIterator", getIteratorPrototype()); } return builtinMapIteratorPrototype; } ScriptObject getSetIteratorPrototype() { if (builtinSetIteratorPrototype == null) { builtinSetIteratorPrototype = initPrototype("SetIterator", getIteratorPrototype()); } return builtinSetIteratorPrototype; } ScriptObject getArrayIteratorPrototype() { if (builtinArrayIteratorPrototype == null) { builtinArrayIteratorPrototype = initPrototype("ArrayIterator", getIteratorPrototype()); } return builtinArrayIteratorPrototype; } ScriptObject getStringIteratorPrototype() { if (builtinStringIteratorPrototype == null) { builtinStringIteratorPrototype = initPrototype("StringIterator", getIteratorPrototype()); } return builtinStringIteratorPrototype; } private synchronized ScriptFunction getBuiltinArrayBuffer() { if (this.builtinArrayBuffer == null) { this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class); } return this.builtinArrayBuffer; } ScriptObject getArrayBufferPrototype() { return ScriptFunction.getPrototype(getBuiltinArrayBuffer()); } private synchronized ScriptFunction getBuiltinDataView() { if (this.builtinDataView == null) { this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class); } return this.builtinDataView; } ScriptObject getDataViewPrototype() { return ScriptFunction.getPrototype(getBuiltinDataView()); } private synchronized ScriptFunction getBuiltinInt8Array() { if (this.builtinInt8Array == null) { this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class); } return this.builtinInt8Array; } ScriptObject getInt8ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinInt8Array()); } private synchronized ScriptFunction getBuiltinUint8Array() { if (this.builtinUint8Array == null) { this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class); } return this.builtinUint8Array; } ScriptObject getUint8ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinUint8Array()); } private synchronized ScriptFunction getBuiltinUint8ClampedArray() { if (this.builtinUint8ClampedArray == null) { this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class); } return this.builtinUint8ClampedArray; } ScriptObject getUint8ClampedArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray()); } private synchronized ScriptFunction getBuiltinInt16Array() { if (this.builtinInt16Array == null) { this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class); } return this.builtinInt16Array; } ScriptObject getInt16ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinInt16Array()); } private synchronized ScriptFunction getBuiltinUint16Array() { if (this.builtinUint16Array == null) { this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class); } return this.builtinUint16Array; } ScriptObject getUint16ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinUint16Array()); } private synchronized ScriptFunction getBuiltinInt32Array() { if (this.builtinInt32Array == null) { this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class); } return this.builtinInt32Array; } ScriptObject getInt32ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinInt32Array()); } private synchronized ScriptFunction getBuiltinUint32Array() { if (this.builtinUint32Array == null) { this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class); } return this.builtinUint32Array; } ScriptObject getUint32ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinUint32Array()); } private synchronized ScriptFunction getBuiltinFloat32Array() { if (this.builtinFloat32Array == null) { this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class); } return this.builtinFloat32Array; } ScriptObject getFloat32ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinFloat32Array()); } private synchronized ScriptFunction getBuiltinFloat64Array() { if (this.builtinFloat64Array == null) { this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class); } return this.builtinFloat64Array; } ScriptObject getFloat64ArrayPrototype() { return ScriptFunction.getPrototype(getBuiltinFloat64Array()); }
Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties.
Returns:the TypeError throwing function
/** * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties. * * @return the TypeError throwing function */
public ScriptFunction getTypeErrorThrower() { return typeErrorThrower; } private synchronized ScriptFunction getBuiltinDate() { if (this.builtinDate == null) { this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate); // initialize default date this.DEFAULT_DATE = new NativeDate(NaN, dateProto); } return this.builtinDate; } private synchronized ScriptFunction getBuiltinEvalError() { if (this.builtinEvalError == null) { this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); } return this.builtinEvalError; } private ScriptFunction getBuiltinFunction() { return builtinFunction; }
Get the switchpoint used to check property changes for Function.prototype.apply
Returns:the switchpoint guarding apply (same as guarding call, and everything else in function)
/** * Get the switchpoint used to check property changes for Function.prototype.apply * @return the switchpoint guarding apply (same as guarding call, and everything else in function) */
public static SwitchPoint getBuiltinFunctionApplySwitchPoint() { return ScriptFunction.getPrototype(Global.instance().getBuiltinFunction()).getProperty("apply").getBuiltinSwitchPoint(); } private static boolean isBuiltinFunctionProperty(final String name) { final Global instance = Global.instance(); final ScriptFunction builtinFunction = instance.getBuiltinFunction(); if (builtinFunction == null) { return false; //conservative for compile-only mode } final boolean isBuiltinFunction = instance.function == builtinFunction; return isBuiltinFunction && ScriptFunction.getPrototype(builtinFunction).getProperty(name).isBuiltin(); }
Check if the Function.prototype.apply has not been replaced
Returns:true if Function.prototype.apply has been replaced
/** * Check if the Function.prototype.apply has not been replaced * @return true if Function.prototype.apply has been replaced */
public static boolean isBuiltinFunctionPrototypeApply() { return isBuiltinFunctionProperty("apply"); }
Check if the Function.prototype.apply has not been replaced
Returns:true if Function.prototype.call has been replaced
/** * Check if the Function.prototype.apply has not been replaced * @return true if Function.prototype.call has been replaced */
public static boolean isBuiltinFunctionPrototypeCall() { return isBuiltinFunctionProperty("call"); } private synchronized ScriptFunction getBuiltinJSAdapter() { if (this.builtinJSAdapter == null) { this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class); } return builtinJSAdapter; } private synchronized ScriptObject getBuiltinJSON() { if (this.builtinJSON == null) { this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); } return this.builtinJSON; } private synchronized ScriptFunction getBuiltinJavaImporter() { if (getContext().getEnv()._no_java) { throw new IllegalStateException(); } if (this.builtinJavaImporter == null) { this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); } return this.builtinJavaImporter; } private synchronized ScriptObject getBuiltinJavaApi() { if (getContext().getEnv()._no_java) { throw new IllegalStateException(); } if (this.builtinJavaApi == null) { this.builtinJavaApi = initConstructor("Java", ScriptObject.class); this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend"); this.builtInJavaTo = (ScriptFunction)builtinJavaApi.get("to"); } return this.builtinJavaApi; }
Returns true if the passed function is the built-in "Java.extend".
Params:
  • fn – the function in question
Returns:true if the function is built-in "Java.extend"
/** * Returns true if the passed function is the built-in "Java.extend". * @param fn the function in question * @return true if the function is built-in "Java.extend" */
public static boolean isBuiltInJavaExtend(final ScriptFunction fn) { if(!"extend".equals(fn.getName())) { // Avoid hitting the thread local if the name doesn't match. return false; } return fn == Context.getGlobal().builtInJavaExtend; }
Returns true if the passed function is the built-in "Java.to".
Params:
  • fn – the function in question
Returns:true if the function is built-in "Java.to"
/** * Returns true if the passed function is the built-in "Java.to". * @param fn the function in question * @return true if the function is built-in "Java.to" */
public static boolean isBuiltInJavaTo(final ScriptFunction fn) { if(!"to".equals(fn.getName())) { // Avoid hitting the thread local if the name doesn't match. return false; } return fn == Context.getGlobal().builtInJavaTo; } private synchronized ScriptFunction getBuiltinRangeError() { if (this.builtinRangeError == null) { this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); } return builtinRangeError; } private synchronized ScriptFunction getBuiltinRegExp() { if (this.builtinRegExp == null) { this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp); // initialize default regexp object this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto); // RegExp.prototype should behave like a RegExp object. So copy the // properties. regExpProto.addBoundProperties(DEFAULT_REGEXP); } return builtinRegExp; } private synchronized ScriptFunction getBuiltinURIError() { if (this.builtinURIError == null) { this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); } return this.builtinURIError; } private synchronized ScriptFunction getBuiltinSymbol() { if (this.builtinSymbol == null) { this.builtinSymbol = initConstructorAndSwitchPoint("Symbol", ScriptFunction.class); } return this.builtinSymbol; } private synchronized ScriptFunction getBuiltinMap() { if (this.builtinMap == null) { this.builtinMap = initConstructorAndSwitchPoint("Map", ScriptFunction.class); } return this.builtinMap; } private synchronized ScriptFunction getBuiltinWeakMap() { if (this.builtinWeakMap == null) { this.builtinWeakMap = initConstructorAndSwitchPoint("WeakMap", ScriptFunction.class); } return this.builtinWeakMap; } private synchronized ScriptFunction getBuiltinSet() { if (this.builtinSet == null) { this.builtinSet = initConstructorAndSwitchPoint("Set", ScriptFunction.class); } return this.builtinSet; } private synchronized ScriptFunction getBuiltinWeakSet() { if (this.builtinWeakSet == null) { this.builtinWeakSet = initConstructorAndSwitchPoint("WeakSet", ScriptFunction.class); } return this.builtinWeakSet; } @Override public String getClassName() { return "global"; }
Copy function used to clone NativeRegExp objects.
Params:
  • regexp – a NativeRegExp to clone
Returns:copy of the given regexp object
/** * Copy function used to clone NativeRegExp objects. * * @param regexp a NativeRegExp to clone * * @return copy of the given regexp object */
public static Object regExpCopy(final Object regexp) { return new NativeRegExp((NativeRegExp)regexp); }
Convert given object to NativeRegExp type.
Params:
  • obj – object to be converted
Returns:NativeRegExp instance
/** * Convert given object to NativeRegExp type. * * @param obj object to be converted * @return NativeRegExp instance */
public static NativeRegExp toRegExp(final Object obj) { if (obj instanceof NativeRegExp) { return (NativeRegExp)obj; } return new NativeRegExp(JSType.toString(obj)); }
ECMA 9.9 ToObject implementation
Params:
  • obj – an item for which to run ToObject
Returns:ToObject version of given item
/** * ECMA 9.9 ToObject implementation * * @param obj an item for which to run ToObject * @return ToObject version of given item */
public static Object toObject(final Object obj) { if (obj == null || obj == UNDEFINED) { throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); } if (obj instanceof ScriptObject) { return obj; } return instance().wrapAsObject(obj); }
Allocate a new object array.
Params:
  • initial – object values.
Returns:the new array
/** * Allocate a new object array. * * @param initial object values. * @return the new array */
public static NativeArray allocate(final Object[] initial) { ArrayData arrayData = ArrayData.allocate(initial); for (int index = 0; index < initial.length; index++) { final Object value = initial[index]; if (value == ScriptRuntime.EMPTY) { arrayData = arrayData.delete(index); } } return new NativeArray(arrayData); }
Allocate a new number array.
Params:
  • initial – number values.
Returns:the new array
/** * Allocate a new number array. * * @param initial number values. * @return the new array */
public static NativeArray allocate(final double[] initial) { return new NativeArray(ArrayData.allocate(initial)); }
Allocate a new integer array.
Params:
  • initial – number values.
Returns:the new array
/** * Allocate a new integer array. * * @param initial number values. * @return the new array */
public static NativeArray allocate(final int[] initial) { return new NativeArray(ArrayData.allocate(initial)); }
Allocate a new object array for arguments.
Params:
  • arguments – initial arguments passed.
  • callee – reference to the function that uses arguments object
  • numParams – actual number of declared parameters
Returns:the new array
/** * Allocate a new object array for arguments. * * @param arguments initial arguments passed. * @param callee reference to the function that uses arguments object * @param numParams actual number of declared parameters * * @return the new array */
public static ScriptObject allocateArguments(final Object[] arguments, final Object callee, final int numParams) { return NativeArguments.allocate(arguments, (ScriptFunction)callee, numParams); }
Called from generated to check if given function is the builtin 'eval'. If eval is used in a script, a lot of optimizations and assumptions cannot be done.
Params:
  • fn – function object that is checked
Returns:true if fn is the builtin eval
/** * Called from generated to check if given function is the builtin 'eval'. If * eval is used in a script, a lot of optimizations and assumptions cannot be done. * * @param fn function object that is checked * @return true if fn is the builtin eval */
public static boolean isEval(final Object fn) { return fn == Global.instance().builtinEval; }
Called from generated to replace a location property placeholder with the actual location property value.
Params:
  • placeholder – the value tested for being a placeholder for a location property
  • locationProperty – the actual value for the location property
Returns:locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
/** * Called from generated to replace a location property placeholder with the actual location property value. * * @param placeholder the value tested for being a placeholder for a location property * @param locationProperty the actual value for the location property * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise */
public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) { return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder; }
Called from runtime internals to check if the passed value is a location property placeholder.
Params:
  • placeholder – the value tested for being a placeholder for a location property
Returns:true if the value is a placeholder, false otherwise.
/** * Called from runtime internals to check if the passed value is a location property placeholder. * @param placeholder the value tested for being a placeholder for a location property * @return true if the value is a placeholder, false otherwise. */
public static boolean isLocationPropertyPlaceholder(final Object placeholder) { return placeholder == LOCATION_PLACEHOLDER; }
Create a new RegExp object.
Params:
  • expression – Regular expression.
  • options – Search options.
Returns:New RegExp object.
/** * Create a new RegExp object. * * @param expression Regular expression. * @param options Search options. * * @return New RegExp object. */
public static Object newRegExp(final String expression, final String options) { if (options == null) { return new NativeRegExp(expression); } return new NativeRegExp(expression, options); }
Get the object prototype
Returns:the object prototype
/** * Get the object prototype * * @return the object prototype */
public static ScriptObject objectPrototype() { return Global.instance().getObjectPrototype(); }
Create a new empty object instance.
Returns:New empty object.
/** * Create a new empty object instance. * * @return New empty object. */
public static ScriptObject newEmptyInstance() { return Global.instance().newObject(); }
Check if a given object is a ScriptObject, raises an exception if this is not the case
Params:
  • obj – and object to check
Returns:the script object
/** * Check if a given object is a ScriptObject, raises an exception if this is * not the case * * @param obj and object to check * @return the script object */
public static ScriptObject checkObject(final Object obj) { if (!(obj instanceof ScriptObject)) { throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); } return (ScriptObject)obj; }
ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception if this object is null or undefined.
Params:
  • obj – an object to check
/** * ECMA 9.10 - implementation of CheckObjectCoercible, i.e. raise an exception * if this object is null or undefined. * * @param obj an object to check */
public static void checkObjectCoercible(final Object obj) { if (obj == null || obj == UNDEFINED) { throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); } }
Return the ES6 global scope for lexically declared bindings.
Returns:the ES6 lexical global scope.
/** * Return the ES6 global scope for lexically declared bindings. * @return the ES6 lexical global scope. */
public final ScriptObject getLexicalScope() { assert context.getEnv()._es6; return lexicalScope; } @Override public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) { PropertyMap ownMap = getMap(); LexicalScope lexScope = null; PropertyMap lexicalMap = null; boolean hasLexicalDefinitions = false; if (context.getEnv()._es6) { lexScope = (LexicalScope) getLexicalScope(); lexicalMap = lexScope.getMap(); for (final jdk.nashorn.internal.runtime.Property property : properties) { if (property.isLexicalBinding()) { hasLexicalDefinitions = true; } // ES6 15.1.8 steps 6. and 7. final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey()); if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) { throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); } final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey()); if (lexicalProperty != null && !property.isConfigurable()) { throw ECMAErrors.syntaxError("redeclare.variable", property.getKey().toString()); } } } final boolean extensible = isExtensible(); for (final jdk.nashorn.internal.runtime.Property property : properties) { if (property.isLexicalBinding()) { assert lexScope != null; lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true); if (ownMap.findProperty(property.getKey()) != null) { // If property exists in the global object invalidate any global constant call sites. invalidateGlobalConstant(property.getKey()); } } else { ownMap = addBoundProperty(ownMap, source, property, extensible); } } setMap(ownMap); if (hasLexicalDefinitions) { assert lexScope != null; lexScope.setMap(lexicalMap); invalidateLexicalSwitchPoint(); } } @Override public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { final String name = NashornCallSiteDescriptor.getOperand(desc); final boolean isScope = NashornCallSiteDescriptor.isScope(desc); if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) { if (lexicalScope.hasOwnProperty(name)) { return lexicalScope.findGetMethod(desc, request); } } final GuardedInvocation invocation = super.findGetMethod(desc, request); // We want to avoid adding our generic lexical scope switchpoint to global constant invocations, // because those are invalidated per-key in the addBoundProperties method above. // We therefore check if the invocation does already have a switchpoint and the property is non-inherited, // assuming this only applies to global constants. If other non-inherited properties will // start using switchpoints some time in the future we'll have to revisit this. if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) { return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); } return invocation; } @Override protected FindProperty findProperty(final Object key, final boolean deep, final boolean isScope, final ScriptObject start) { if (lexicalScope != null && isScope) { final FindProperty find = lexicalScope.findProperty(key, false); if (find != null) { return find; } } return super.findProperty(key, deep, isScope, start); } @Override public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { final boolean isScope = NashornCallSiteDescriptor.isScope(desc); if (lexicalScope != null && isScope) { final String name = NashornCallSiteDescriptor.getOperand(desc); if (lexicalScope.hasOwnProperty(name)) { return lexicalScope.findSetMethod(desc, request); } } final GuardedInvocation invocation = super.findSetMethod(desc, request); if (isScope && context.getEnv()._es6) { return invocation.addSwitchPoint(getLexicalScopeSwitchPoint()); } return invocation; }
Adds jjs shell interactive mode builtin functions to global scope.
/** * Adds jjs shell interactive mode builtin functions to global scope. */
public void addShellBuiltins() { Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT); addOwnProperty("input", Attribute.NOT_ENUMERABLE, value); value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT); addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value); } private synchronized SwitchPoint getLexicalScopeSwitchPoint() { SwitchPoint switchPoint = lexicalScopeSwitchPoint; if (switchPoint == null || switchPoint.hasBeenInvalidated()) { switchPoint = lexicalScopeSwitchPoint = new SwitchPoint(); } return switchPoint; } private synchronized void invalidateLexicalSwitchPoint() { if (lexicalScopeSwitchPoint != null) { context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update"); SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint }); } } @SuppressWarnings("unused") private static Object lexicalScopeFilter(final Object self) { if (self instanceof Global) { return ((Global) self).getLexicalScope(); } return self; } private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) { final T func = initConstructor(name, clazz); tagBuiltinProperties(name, func); return func; } private void init(final ScriptEngine eng) { assert Context.getGlobal() == this : "this global is not set as current"; final ScriptEnvironment env = getContext().getEnv(); // initialize Function and Object constructor initFunctionAndObject(); // Now fix Global's own proto. this.setInitialProto(getObjectPrototype()); // initialize global function properties this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL); this.parseInt = ScriptFunction.createBuiltin("parseInt", GlobalFunctions.PARSEINT, new Specialization[] { new Specialization(GlobalFunctions.PARSEINT_Z), new Specialization(GlobalFunctions.PARSEINT_I), new Specialization(GlobalFunctions.PARSEINT_OI), new Specialization(GlobalFunctions.PARSEINT_O) }); this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN, new Specialization[] { new Specialization(GlobalFunctions.IS_NAN_I), new Specialization(GlobalFunctions.IS_NAN_J), new Specialization(GlobalFunctions.IS_NAN_D) }); this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); this.isNaN = ScriptFunction.createBuiltin("isNaN", GlobalFunctions.IS_NAN); this.isFinite = ScriptFunction.createBuiltin("isFinite", GlobalFunctions.IS_FINITE); this.encodeURI = ScriptFunction.createBuiltin("encodeURI", GlobalFunctions.ENCODE_URI); this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT); this.decodeURI = ScriptFunction.createBuiltin("decodeURI", GlobalFunctions.DECODE_URI); this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT); this.escape = ScriptFunction.createBuiltin("escape", GlobalFunctions.ESCAPE); this.unescape = ScriptFunction.createBuiltin("unescape", GlobalFunctions.UNESCAPE); this.print = ScriptFunction.createBuiltin("print", env._print_no_newline ? PRINT : PRINTLN); this.load = ScriptFunction.createBuiltin("load", LOAD); this.loadWithNewGlobal = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL); this.exit = ScriptFunction.createBuiltin("exit", EXIT); this.quit = ScriptFunction.createBuiltin("quit", EXIT); // built-in constructors this.builtinArray = initConstructorAndSwitchPoint("Array", ScriptFunction.class); this.builtinBoolean = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class); this.builtinNumber = initConstructorAndSwitchPoint("Number", ScriptFunction.class); this.builtinString = initConstructorAndSwitchPoint("String", ScriptFunction.class); this.builtinMath = initConstructorAndSwitchPoint("Math", ScriptObject.class); // initialize String.prototype.length to 0 // add String.prototype.length final ScriptObject stringPrototype = getStringPrototype(); stringPrototype.addOwnProperty("length", Attribute.NON_ENUMERABLE_CONSTANT, 0.0); // set isArray flag on Array.prototype final ScriptObject arrayPrototype = getArrayPrototype(); arrayPrototype.setIsArray(); if (env._es6) { this.symbol = LAZY_SENTINEL; this.map = LAZY_SENTINEL; this.weakMap = LAZY_SENTINEL; this.set = LAZY_SENTINEL; this.weakSet = LAZY_SENTINEL; } else { // We need to manually delete nasgen-generated properties we don't want this.delete("Symbol", false); this.delete("Map", false); this.delete("WeakMap", false); this.delete("Set", false); this.delete("WeakSet", false); builtinObject.delete("getOwnPropertySymbols", false); arrayPrototype.delete("entries", false); arrayPrototype.delete("keys", false); arrayPrototype.delete("values", false); } // Error stuff initErrorObjects(); // java access if (! env._no_java) { this.javaApi = LAZY_SENTINEL; this.javaImporter = LAZY_SENTINEL; initJavaAccess(); } else { // delete nasgen-created global properties related to java access this.delete("Java", false); this.delete("JavaImporter", false); this.delete("Packages", false); this.delete("com", false); this.delete("edu", false); this.delete("java", false); this.delete("javafx", false); this.delete("javax", false); this.delete("org", false); } if (! env._no_typed_arrays) { this.arrayBuffer = LAZY_SENTINEL; this.dataView = LAZY_SENTINEL; this.int8Array = LAZY_SENTINEL; this.uint8Array = LAZY_SENTINEL; this.uint8ClampedArray = LAZY_SENTINEL; this.int16Array = LAZY_SENTINEL; this.uint16Array = LAZY_SENTINEL; this.int32Array = LAZY_SENTINEL; this.uint32Array = LAZY_SENTINEL; this.float32Array = LAZY_SENTINEL; this.float64Array = LAZY_SENTINEL; } if (env._scripting) { initScripting(env); } if (Context.DEBUG) { boolean debugOkay; final SecurityManager sm = System.getSecurityManager(); if (sm != null) { try { sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE)); debugOkay = true; } catch (final SecurityException ignored) { // if no permission, don't initialize Debug object debugOkay = false; } } else { debugOkay = true; } if (debugOkay) { initDebug(); } } copyBuiltins(); // expose script (command line) arguments as "arguments" property of global arguments = wrapAsObject(env.getArguments().toArray()); if (env._scripting) { // synonym for "arguments" in scripting mode addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments); } if (eng != null) { // default file name addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null); // __noSuchProperty__ hook for ScriptContext search of missing variables final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY); addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp); } } private void initErrorObjects() { // Error objects this.builtinError = initConstructor("Error", ScriptFunction.class); final ScriptObject errorProto = getErrorPrototype(); // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK); final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK); errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack); final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER); final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER); errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber); final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER); final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER); errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber); final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME); final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME); errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName); // ECMA 15.11.4.2 Error.prototype.name // Error.prototype.name = "Error"; errorProto.set(NativeError.NAME, "Error", 0); // ECMA 15.11.4.3 Error.prototype.message // Error.prototype.message = ""; errorProto.set(NativeError.MESSAGE, "", 0); tagBuiltinProperties("Error", builtinError); this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto); this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto); this.builtinTypeError = initErrorSubtype("TypeError", errorProto); } private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) { final ScriptFunction cons = initConstructor(name, ScriptFunction.class); final ScriptObject prototype = ScriptFunction.getPrototype(cons); prototype.set(NativeError.NAME, name, 0); prototype.set(NativeError.MESSAGE, "", 0); prototype.setInitialProto(errorProto); tagBuiltinProperties(name, cons); return cons; } private void initJavaAccess() { final ScriptObject objectProto = getObjectPrototype(); this.builtinPackages = new NativeJavaPackage("", objectProto); this.builtinCom = new NativeJavaPackage("com", objectProto); this.builtinEdu = new NativeJavaPackage("edu", objectProto); this.builtinJava = new NativeJavaPackage("java", objectProto); this.builtinJavafx = new NativeJavaPackage("javafx", objectProto); this.builtinJavax = new NativeJavaPackage("javax", objectProto); this.builtinOrg = new NativeJavaPackage("org", objectProto); } private void initScripting(final ScriptEnvironment scriptEnv) { ScriptObject value; value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE); addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value); value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY); addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value); final String execName = ScriptingFunctions.EXEC_NAME; value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC); addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value); // Nashorn extension: global.echo (scripting-mode-only) // alias for "print" value = (ScriptObject)get("print"); addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value); // Nashorn extension: global.$OPTIONS (scripting-mode-only) final ScriptObject options = newObject(); copyOptions(options, scriptEnv); addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options); // Nashorn extension: global.$ENV (scripting-mode-only) final ScriptObject env = newObject(); if (System.getSecurityManager() == null) { // do not fill $ENV if we have a security manager around // Retrieve current state of ENV variables. env.putAll(System.getenv(), scriptEnv._strict); // Set the PWD variable to a value that is guaranteed to be understood // by the underlying platform. env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); } addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); // add other special properties for exec support addOwnProperty(ScriptingFunctions.OUT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); addOwnProperty(ScriptingFunctions.ERR_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); } private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { for (final Field f : scriptEnv.getClass().getFields()) { try { options.set(f.getName(), f.get(scriptEnv), 0); } catch (final IllegalArgumentException | IllegalAccessException exp) { throw new RuntimeException(exp); } } } private void copyBuiltins() { this.array = this.builtinArray; this._boolean = this.builtinBoolean; this.error = this.builtinError; this.function = this.builtinFunction; this.com = this.builtinCom; this.edu = this.builtinEdu; this.java = this.builtinJava; this.javafx = this.builtinJavafx; this.javax = this.builtinJavax; this.org = this.builtinOrg; this.math = this.builtinMath; this.number = this.builtinNumber; this.object = this.builtinObject; this.packages = this.builtinPackages; this.referenceError = this.builtinReferenceError; this.string = this.builtinString; this.syntaxError = this.builtinSyntaxError; this.typeError = this.builtinTypeError; } private void initDebug() { this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class)); } private Object printImpl(final boolean newLine, final Object... objects) { final ScriptContext sc = currentContext(); @SuppressWarnings("resource") final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut(); final StringBuilder sb = new StringBuilder(); for (final Object obj : objects) { if (sb.length() != 0) { sb.append(' '); } sb.append(JSType.toString(obj)); } // Print all at once to ensure thread friendly result. if (newLine) { out.println(sb.toString()); } else { out.print(sb.toString()); } out.flush(); return UNDEFINED; } private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) { try { // Assuming class name pattern for built-in JS constructors. final StringBuilder sb = new StringBuilder(PACKAGE_PREFIX); sb.append("Native"); sb.append(name); sb.append("$Constructor"); final Class<?> funcClass = Class.forName(sb.toString()); final T res = clazz.cast(funcClass.getDeclaredConstructor().newInstance()); if (res instanceof ScriptFunction) { // All global constructor prototypes are not-writable, // not-enumerable and not-configurable. final ScriptFunction func = (ScriptFunction)res; func.modifyOwnProperty(func.getProperty("prototype"), Attribute.NON_ENUMERABLE_CONSTANT); } if (res.getProto() == null) { res.setInitialProto(getObjectPrototype()); } res.setIsBuiltin(); return res; } catch (final Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RuntimeException(e); } } } private ScriptObject initPrototype(final String name, final ScriptObject prototype) { try { // Assuming class name pattern for JS prototypes final String className = PACKAGE_PREFIX + name + "$Prototype"; final Class<?> funcClass = Class.forName(className); final ScriptObject res = (ScriptObject) funcClass.getDeclaredConstructor().newInstance(); res.setIsBuiltin(); res.setInitialProto(prototype); return res; } catch (final Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RuntimeException(e); } } } private List<jdk.nashorn.internal.runtime.Property> extractBuiltinProperties(final String name, final ScriptObject func) { final List<jdk.nashorn.internal.runtime.Property> list = new ArrayList<>(); list.addAll(Arrays.asList(func.getMap().getProperties())); if (func instanceof ScriptFunction) { final ScriptObject proto = ScriptFunction.getPrototype((ScriptFunction)func); if (proto != null) { list.addAll(Arrays.asList(proto.getMap().getProperties())); } } final jdk.nashorn.internal.runtime.Property prop = getProperty(name); if (prop != null) { list.add(prop); } return list; }
Given a builtin object, traverse its properties recursively and associate them with a name that will be a key to their invalidation switchpoint.
Params:
  • name – name for key
  • func – builtin script object
/** * Given a builtin object, traverse its properties recursively and associate them with a name that * will be a key to their invalidation switchpoint. * @param name name for key * @param func builtin script object */
private void tagBuiltinProperties(final String name, final ScriptObject func) { SwitchPoint sp = context.getBuiltinSwitchPoint(name); if (sp == null) { sp = context.newBuiltinSwitchPoint(name); } //get all builtin properties in this builtin object and register switchpoints keyed on the propery name, //one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) { prop.setBuiltinSwitchPoint(sp); } } // Function and Object constructors are inter-dependent. Also, // Function.prototype // functions are not properly initialized. We fix the references here. // NOTE: be careful if you want to re-order the operations here. You may // have // to play with object references carefully!! private void initFunctionAndObject() { // First-n-foremost is Function this.builtinFunction = initConstructor("Function", ScriptFunction.class); // create global anonymous function final ScriptFunction anon = ScriptFunction.createAnonymous(); // need to copy over members of Function.prototype to anon function anon.addBoundProperties(getFunctionPrototype()); // Function.prototype === Object.getPrototypeOf(Function) === // <anon-function> builtinFunction.setInitialProto(anon); builtinFunction.setPrototype(anon); anon.set("constructor", builtinFunction, 0); anon.deleteOwnProperty(anon.getMap().findProperty("prototype")); // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3 this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER); typeErrorThrower.preventExtensions(); // now initialize Object this.builtinObject = initConstructor("Object", ScriptFunction.class); final ScriptObject ObjectPrototype = getObjectPrototype(); // Object.getPrototypeOf(Function.prototype) === Object.prototype anon.setInitialProto(ObjectPrototype); // ES6 draft compliant __proto__ property of Object.prototype // accessors on Object.prototype for "__proto__" final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__); final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__); ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto); // Function valued properties of Function.prototype were not properly // initialized. Because, these were created before global.function and // global.object were not initialized. jdk.nashorn.internal.runtime.Property[] properties = getFunctionPrototype().getMap().getProperties(); for (final jdk.nashorn.internal.runtime.Property property : properties) { final Object key = property.getKey(); final Object value = builtinFunction.get(key); if (value instanceof ScriptFunction && value != anon) { final ScriptFunction func = (ScriptFunction)value; func.setInitialProto(getFunctionPrototype()); final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { prototype.setInitialProto(ObjectPrototype); } } } // For function valued properties of Object and Object.prototype, make // sure prototype's proto chain ends with Object.prototype for (final jdk.nashorn.internal.runtime.Property property : builtinObject.getMap().getProperties()) { final Object key = property.getKey(); final Object value = builtinObject.get(key); if (value instanceof ScriptFunction) { final ScriptFunction func = (ScriptFunction)value; final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { prototype.setInitialProto(ObjectPrototype); } } } properties = getObjectPrototype().getMap().getProperties(); for (final jdk.nashorn.internal.runtime.Property property : properties) { final Object key = property.getKey(); if (key.equals("constructor")) { continue; } final Object value = ObjectPrototype.get(key); if (value instanceof ScriptFunction) { final ScriptFunction func = (ScriptFunction)value; final ScriptObject prototype = ScriptFunction.getPrototype(func); if (prototype != null) { prototype.setInitialProto(ObjectPrototype); } } } tagBuiltinProperties("Object", builtinObject); tagBuiltinProperties("Function", builtinFunction); tagBuiltinProperties("Function", anon); } private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types)); } RegExpResult getLastRegExpResult() { return lastRegExpResult; } void setLastRegExpResult(final RegExpResult regExpResult) { this.lastRegExpResult = regExpResult; } @Override protected boolean isGlobal() { return true; }
A class representing the ES6 global lexical scope.
/** * A class representing the ES6 global lexical scope. */
private static class LexicalScope extends ScriptObject { LexicalScope(final Global global) { super(global, PropertyMap.newMap()); setIsInternal(); } @Override protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) { return filterInvocation(super.findGetMethod(desc, request)); } @Override protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) { return filterInvocation(super.findSetMethod(desc, request)); } @Override protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) { // We override this method just to make it callable by Global return super.addBoundProperty(propMap, source, property, extensible); } private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) { final MethodType type = invocation.getInvocation().type(); return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER); } } }