/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* ExternalScriptable is an implementation of Scriptable
* backed by a JSR 223 ScriptContext instance.
*
* @author Mike Grogan
* @author A. Sundararajan
* @since 1.6
*/
/* Underlying ScriptContext that we use to store
* named variables of this scope.
*/
/* JavaScript allows variables to be named as numbers (indexed
* properties). This way arrays, objects (scopes) are treated uniformly.
* Note that JSR 223 API supports only String named variables and
* so we can't store these in Bindings. Also, JavaScript allows name
* of the property name to be even empty String! Again, JSR 223 API
* does not support empty name. So, we use the following fallback map
* to store such variables of this scope. This map is not exposed to
* JSR 223 API. We can just script objects "as is" and need not convert.
*/
// my prototype
// my parent scope, if any
}
throw new NullPointerException("context is null");
}
this.indexedProps = indexedProps;
}
return context;
}
}
/**
* Return the name of the class.
*/
return "Global";
}
/**
* Returns the value of the named property or NOT_FOUND.
*
* If the property was created using defineProperty, the
* appropriate getter method is called.
*
* @param name the name of the property
* @param start the object in which the lookup began
* @return the value of the property (may be null), or NOT_FOUND
*/
} else {
return NOT_FOUND;
}
} else {
synchronized (context) {
if (scope != -1) {
} else {
return NOT_FOUND;
}
}
}
}
/**
* Returns the value of the indexed property or NOT_FOUND.
*
* @param index the numeric index for the property
* @param start the object in which the lookup began
* @return the value of the property (may be null), or NOT_FOUND
*/
} else {
return NOT_FOUND;
}
}
/**
* Returns true if the named property is defined.
*
* @param name the name of the property
* @param start the object in which the lookup began
* @return true if and only if the property was found in the object
*/
} else {
synchronized (context) {
}
}
}
/**
* Returns true if the property index is defined.
*
* @param index the numeric index for the property
* @param start the object in which the lookup began
* @return true if and only if the property was found in the object
*/
}
/**
* Sets the value of the named property, creating it if need be.
*
* @param name the name of the property
* @param start the object whose property is being set
* @param value value to set the property to
*/
if (start == this) {
synchronized (this) {
} else {
synchronized (context) {
if (scope == -1) {
}
}
}
}
} else {
}
}
/**
* Sets the value of the indexed property, creating it if need be.
*
* @param index the numeric index for the property
* @param start the object whose property is being set
* @param value value to set the property to
*/
if (start == this) {
synchronized (this) {
}
} else {
}
}
/**
* Removes a named property from the object.
*
* If the property is not found, no action is taken.
*
* @param name the name of the property
*/
} else {
synchronized (context) {
if (scope != -1) {
}
}
}
}
/**
* Removes the indexed property from the object.
*
* If the property is not found, no action is taken.
*
* @param index the numeric index for the property
*/
}
/**
* Get the prototype of the object.
* @return the prototype
*/
return prototype;
}
/**
* Set the prototype of the object.
* @param prototype the prototype to set
*/
}
/**
* Get the parent scope of the object.
* @return the parent scope
*/
return parent;
}
/**
* Set the parent scope of the object.
* @param parent the parent scope to set
*/
}
/**
* Get an array of property ids.
*
* Not all property ids need be returned. Those properties
* whose ids are not returned are considered non-enumerable.
*
* @return an array of Objects. Each entry in the array is either
* a java.lang.String or a java.lang.Number
*/
// now add all indexed properties
}
return res;
}
/**
* Get the default value of the object with a given hint.
* The hints are String.class for type String, Number.class for type
* Number, Scriptable.class for type Object, and Boolean.class for
* type Boolean. <p>
*
* A <code>hint</code> of null means "no hint".
*
* See ECMA 8.6.2.6.
*
* @param hint the type hint
* @return the default value
*/
for (int i=0; i < 2; i++) {
boolean tryToString;
tryToString = (i == 0);
} else {
tryToString = (i == 1);
}
if (tryToString) {
methodName = "toString";
} else {
methodName = "valueOf";
hint = "undefined";
hint = "string";
hint = "object";
hint = "function";
{
hint = "boolean";
{
hint = "number";
} else {
throw Context.reportRuntimeError(
"Invalid JavaScript value of type " +
}
}
if (!(v instanceof Function))
continue;
try {
} finally {
}
if (v != null) {
if (!(v instanceof Scriptable)) {
return v;
}
{
return v;
}
if (tryToString && v instanceof Wrapper) {
// Let a wrapped java.lang.String pass for a primitive
// string.
if (u instanceof String)
return u;
}
}
}
// fall through to error
throw Context.reportRuntimeError(
"Cannot find default value for object " + arg);
}
/**
* Implements the instanceof operator.
*
* @param instance The value that appeared on the LHS of the instanceof
* operator
* @return true if "this" appears in value's prototype chain
*
*/
// Default for JS objects (other than Function) is to do prototype
// chasing.
}
return false;
}
synchronized (context) {
}
}
}
}
return res;
}
/**
* We convert script values to the nearest Java value.
* We unwrap wrapped Java objects so that access from
* Bindings.get() would return "workable" value for Java.
* But, at the same time, we need to make few special cases
* and hence the following function is used.
*/
/* importClass feature of ImporterTopLevel puts
* NativeJavaClass in global scope. If we unwrap
* it, importClass won't work.
*/
if (njb instanceof NativeJavaClass) {
return njb;
}
/* script may use Java primitive wrapper type objects
* (such as java.lang.Integer, java.lang.Boolean etc)
* explicitly. If we unwrap, then these script objects
* will become script primitive types. For example,
*
* var x = new java.lang.Double(3.0); print(typeof x);
*
* will print 'number'. We don't want that to happen.
*/
// special type wrapped -- we just leave it as is.
return njb;
} else {
// return unwrapped object for any other object.
return obj;
}
} else { // not-a-Java-wrapper
return jsObj;
}
}
}