summaryrefslogtreecommitdiffstats
path: root/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java
diff options
context:
space:
mode:
Diffstat (limited to 'infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java')
-rw-r--r--infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java569
1 files changed, 0 insertions, 569 deletions
diff --git a/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java
deleted file mode 100644
index 8fa4e68..0000000
--- a/infrastructure/rhino1_7R1/src/org/mozilla/javascript/FunctionObject.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Rhino code, released
- * May 6, 1999.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1997-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Norris Boyd
- * Igor Bukanov
- * David C. Navas
- * Ted Neward
- *
- * Alternatively, the contents of this file may be used under the terms of
- * the GNU General Public License Version 2 or later (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of those above. If
- * you wish to allow use of your version of this file only under the terms of
- * the GPL and not to allow others to use your version of this file under the
- * MPL, indicate your decision by deleting the provisions above and replacing
- * them with the notice and other provisions required by the GPL. If you do
- * not delete the provisions above, a recipient may use your version of this
- * file under either the MPL or the GPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// API class
-
-package org.mozilla.javascript;
-
-import java.lang.reflect.*;
-import java.io.*;
-
-public class FunctionObject extends BaseFunction
-{
- static final long serialVersionUID = -5332312783643935019L;
-
- /**
- * Create a JavaScript function object from a Java method.
- *
- * <p>The <code>member</code> argument must be either a java.lang.reflect.Method
- * or a java.lang.reflect.Constructor and must match one of two forms.<p>
- *
- * The first form is a member with zero or more parameters
- * of the following types: Object, String, boolean, Scriptable,
- * int, or double. The Long type is not supported
- * because the double representation of a long (which is the
- * EMCA-mandated storage type for Numbers) may lose precision.
- * If the member is a Method, the return value must be void or one
- * of the types allowed for parameters.<p>
- *
- * The runtime will perform appropriate conversions based
- * upon the type of the parameter. A parameter type of
- * Object specifies that no conversions are to be done. A parameter
- * of type String will use Context.toString to convert arguments.
- * Similarly, parameters of type double, boolean, and Scriptable
- * will cause Context.toNumber, Context.toBoolean, and
- * Context.toObject, respectively, to be called.<p>
- *
- * If the method is not static, the Java 'this' value will
- * correspond to the JavaScript 'this' value. Any attempt
- * to call the function with a 'this' value that is not
- * of the right Java type will result in an error.<p>
- *
- * The second form is the variable arguments (or "varargs")
- * form. If the FunctionObject will be used as a constructor,
- * the member must have the following parameters
- * <pre>
- * (Context cx, Object[] args, Function ctorObj,
- * boolean inNewExpr)</pre>
- * and if it is a Method, be static and return an Object result.<p>
- *
- * Otherwise, if the FunctionObject will <i>not</i> be used to define a
- * constructor, the member must be a static Method with parameters
- * (Context cx, Scriptable thisObj, Object[] args,
- * Function funObj) </pre>
- * <pre>
- * and an Object result.<p>
- *
- * When the function varargs form is called as part of a function call,
- * the <code>args</code> parameter contains the
- * arguments, with <code>thisObj</code>
- * set to the JavaScript 'this' value. <code>funObj</code>
- * is the function object for the invoked function.<p>
- *
- * When the constructor varargs form is called or invoked while evaluating
- * a <code>new</code> expression, <code>args</code> contains the
- * arguments, <code>ctorObj</code> refers to this FunctionObject, and
- * <code>inNewExpr</code> is true if and only if a <code>new</code>
- * expression caused the call. This supports defining a function that
- * has different behavior when called as a constructor than when
- * invoked as a normal function call. (For example, the Boolean
- * constructor, when called as a function,
- * will convert to boolean rather than creating a new object.)<p>
- *
- * @param name the name of the function
- * @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor
- * that defines the object
- * @param scope enclosing scope of function
- * @see org.mozilla.javascript.Scriptable
- */
- public FunctionObject(String name, Member methodOrConstructor,
- Scriptable scope)
- {
- if (methodOrConstructor instanceof Constructor) {
- member = new MemberBox((Constructor) methodOrConstructor);
- isStatic = true; // well, doesn't take a 'this'
- } else {
- member = new MemberBox((Method) methodOrConstructor);
- isStatic = member.isStatic();
- }
- String methodName = member.getName();
- this.functionName = name;
- Class[] types = member.argTypes;
- int arity = types.length;
- if (arity == 4 && (types[1].isArray() || types[2].isArray())) {
- // Either variable args or an error.
- if (types[1].isArray()) {
- if (!isStatic ||
- types[0] != ScriptRuntime.ContextClass ||
- types[1].getComponentType() != ScriptRuntime.ObjectClass ||
- types[2] != ScriptRuntime.FunctionClass ||
- types[3] != Boolean.TYPE)
- {
- throw Context.reportRuntimeError1(
- "msg.varargs.ctor", methodName);
- }
- parmsLength = VARARGS_CTOR;
- } else {
- if (!isStatic ||
- types[0] != ScriptRuntime.ContextClass ||
- types[1] != ScriptRuntime.ScriptableClass ||
- types[2].getComponentType() != ScriptRuntime.ObjectClass ||
- types[3] != ScriptRuntime.FunctionClass)
- {
- throw Context.reportRuntimeError1(
- "msg.varargs.fun", methodName);
- }
- parmsLength = VARARGS_METHOD;
- }
- } else {
- parmsLength = arity;
- if (arity > 0) {
- typeTags = new byte[arity];
- for (int i = 0; i != arity; ++i) {
- int tag = getTypeTag(types[i]);
- if (tag == JAVA_UNSUPPORTED_TYPE) {
- throw Context.reportRuntimeError2(
- "msg.bad.parms", types[i].getName(), methodName);
- }
- typeTags[i] = (byte)tag;
- }
- }
- }
-
- if (member.isMethod()) {
- Method method = member.method();
- Class returnType = method.getReturnType();
- if (returnType == Void.TYPE) {
- hasVoidReturn = true;
- } else {
- returnTypeTag = getTypeTag(returnType);
- }
- } else {
- Class ctorType = member.getDeclaringClass();
- if (!ScriptRuntime.ScriptableClass.isAssignableFrom(ctorType)) {
- throw Context.reportRuntimeError1(
- "msg.bad.ctor.return", ctorType.getName());
- }
- }
-
- ScriptRuntime.setFunctionProtoAndParent(this, scope);
- }
-
- /**
- * @return One of <tt>JAVA_*_TYPE</tt> constants to indicate desired type
- * or {@link #JAVA_UNSUPPORTED_TYPE} if the convertion is not
- * possible
- */
- public static int getTypeTag(Class type)
- {
- if (type == ScriptRuntime.StringClass)
- return JAVA_STRING_TYPE;
- if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE)
- return JAVA_INT_TYPE;
- if (type == ScriptRuntime.BooleanClass || type == Boolean.TYPE)
- return JAVA_BOOLEAN_TYPE;
- if (type == ScriptRuntime.DoubleClass || type == Double.TYPE)
- return JAVA_DOUBLE_TYPE;
- if (ScriptRuntime.ScriptableClass.isAssignableFrom(type))
- return JAVA_SCRIPTABLE_TYPE;
- if (type == ScriptRuntime.ObjectClass)
- return JAVA_OBJECT_TYPE;
-
- // Note that the long type is not supported; see the javadoc for
- // the constructor for this class
-
- return JAVA_UNSUPPORTED_TYPE;
- }
-
- public static Object convertArg(Context cx, Scriptable scope,
- Object arg, int typeTag)
- {
- switch (typeTag) {
- case JAVA_STRING_TYPE:
- if (arg instanceof String)
- return arg;
- return ScriptRuntime.toString(arg);
- case JAVA_INT_TYPE:
- if (arg instanceof Integer)
- return arg;
- return new Integer(ScriptRuntime.toInt32(arg));
- case JAVA_BOOLEAN_TYPE:
- if (arg instanceof Boolean)
- return arg;
- return ScriptRuntime.toBoolean(arg) ? Boolean.TRUE
- : Boolean.FALSE;
- case JAVA_DOUBLE_TYPE:
- if (arg instanceof Double)
- return arg;
- return new Double(ScriptRuntime.toNumber(arg));
- case JAVA_SCRIPTABLE_TYPE:
- if (arg instanceof Scriptable)
- return arg;
- return ScriptRuntime.toObject(cx, scope, arg);
- case JAVA_OBJECT_TYPE:
- return arg;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * Return the value defined by the method used to construct the object
- * (number of parameters of the method, or 1 if the method is a "varargs"
- * form).
- */
- public int getArity() {
- return parmsLength < 0 ? 1 : parmsLength;
- }
-
- /**
- * Return the same value as {@link #getArity()}.
- */
- public int getLength() {
- return getArity();
- }
-
- public String getFunctionName()
- {
- return (functionName == null) ? "" : functionName;
- }
-
- /**
- * Get Java method or constructor this function represent.
- */
- public Member getMethodOrConstructor()
- {
- if (member.isMethod()) {
- return member.method();
- } else {
- return member.ctor();
- }
- }
-
- static Method findSingleMethod(Method[] methods, String name)
- {
- Method found = null;
- for (int i = 0, N = methods.length; i != N; ++i) {
- Method method = methods[i];
- if (method != null && name.equals(method.getName())) {
- if (found != null) {
- throw Context.reportRuntimeError2(
- "msg.no.overload", name,
- method.getDeclaringClass().getName());
- }
- found = method;
- }
- }
- return found;
- }
-
- /**
- * Returns all public methods declared by the specified class. This excludes
- * inherited methods.
- *
- * @param clazz the class from which to pull public declared methods
- * @return the public methods declared in the specified class
- * @see Class#getDeclaredMethods()
- */
- static Method[] getMethodList(Class clazz) {
- Method[] methods = null;
- try {
- // getDeclaredMethods may be rejected by the security manager
- // but getMethods is more expensive
- if (!sawSecurityException)
- methods = clazz.getDeclaredMethods();
- } catch (SecurityException e) {
- // If we get an exception once, give up on getDeclaredMethods
- sawSecurityException = true;
- }
- if (methods == null) {
- methods = clazz.getMethods();
- }
- int count = 0;
- for (int i=0; i < methods.length; i++) {
- if (sawSecurityException
- ? methods[i].getDeclaringClass() != clazz
- : !Modifier.isPublic(methods[i].getModifiers()))
- {
- methods[i] = null;
- } else {
- count++;
- }
- }
- Method[] result = new Method[count];
- int j=0;
- for (int i=0; i < methods.length; i++) {
- if (methods[i] != null)
- result[j++] = methods[i];
- }
- return result;
- }
-
- /**
- * Define this function as a JavaScript constructor.
- * <p>
- * Sets up the "prototype" and "constructor" properties. Also
- * calls setParent and setPrototype with appropriate values.
- * Then adds the function object as a property of the given scope, using
- * <code>prototype.getClassName()</code>
- * as the name of the property.
- *
- * @param scope the scope in which to define the constructor (typically
- * the global object)
- * @param prototype the prototype object
- * @see org.mozilla.javascript.Scriptable#setParentScope
- * @see org.mozilla.javascript.Scriptable#setPrototype
- * @see org.mozilla.javascript.Scriptable#getClassName
- */
- public void addAsConstructor(Scriptable scope, Scriptable prototype)
- {
- initAsConstructor(scope, prototype);
- defineProperty(scope, prototype.getClassName(),
- this, ScriptableObject.DONTENUM);
- }
-
- void initAsConstructor(Scriptable scope, Scriptable prototype)
- {
- ScriptRuntime.setFunctionProtoAndParent(this, scope);
- setImmunePrototypeProperty(prototype);
-
- prototype.setParentScope(this);
-
- defineProperty(prototype, "constructor", this,
- ScriptableObject.DONTENUM |
- ScriptableObject.PERMANENT |
- ScriptableObject.READONLY);
- setParentScope(scope);
- }
-
- /**
- * @deprecated Use {@link #getTypeTag(Class)}
- * and {@link #convertArg(Context, Scriptable, Object, int)}
- * for type convertion.
- */
- public static Object convertArg(Context cx, Scriptable scope,
- Object arg, Class desired)
- {
- int tag = getTypeTag(desired);
- if (tag == JAVA_UNSUPPORTED_TYPE) {
- throw Context.reportRuntimeError1
- ("msg.cant.convert", desired.getName());
- }
- return convertArg(cx, scope, arg, tag);
- }
-
- /**
- * Performs conversions on argument types if needed and
- * invokes the underlying Java method or constructor.
- * <p>
- * Implements Function.call.
- *
- * @see org.mozilla.javascript.Function#call(
- * Context, Scriptable, Scriptable, Object[])
- */
- public Object call(Context cx, Scriptable scope, Scriptable thisObj,
- Object[] args)
- {
- Object result;
- boolean checkMethodResult = false;
-
- if (parmsLength < 0) {
- if (parmsLength == VARARGS_METHOD) {
- Object[] invokeArgs = { cx, thisObj, args, this };
- result = member.invoke(null, invokeArgs);
- checkMethodResult = true;
- } else {
- boolean inNewExpr = (thisObj == null);
- Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
- Object[] invokeArgs = { cx, args, this, b };
- result = (member.isCtor())
- ? member.newInstance(invokeArgs)
- : member.invoke(null, invokeArgs);
- }
-
- } else {
- if (!isStatic) {
- Class clazz = member.getDeclaringClass();
- if (!clazz.isInstance(thisObj)) {
- boolean compatible = false;
- if (thisObj == scope) {
- Scriptable parentScope = getParentScope();
- if (scope != parentScope) {
- // Call with dynamic scope for standalone function,
- // use parentScope as thisObj
- compatible = clazz.isInstance(parentScope);
- if (compatible) {
- thisObj = parentScope;
- }
- }
- }
- if (!compatible) {
- // Couldn't find an object to call this on.
- throw ScriptRuntime.typeError1("msg.incompat.call",
- functionName);
- }
- }
- }
-
- Object[] invokeArgs;
- if (parmsLength == args.length) {
- // Do not allocate new argument array if java arguments are
- // the same as the original js ones.
- invokeArgs = args;
- for (int i = 0; i != parmsLength; ++i) {
- Object arg = args[i];
- Object converted = convertArg(cx, scope, arg, typeTags[i]);
- if (arg != converted) {
- if (invokeArgs == args) {
- invokeArgs = args.clone();
- }
- invokeArgs[i] = converted;
- }
- }
- } else if (parmsLength == 0) {
- invokeArgs = ScriptRuntime.emptyArgs;
- } else {
- invokeArgs = new Object[parmsLength];
- for (int i = 0; i != parmsLength; ++i) {
- Object arg = (i < args.length)
- ? args[i]
- : Undefined.instance;
- invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]);
- }
- }
-
- if (member.isMethod()) {
- result = member.invoke(thisObj, invokeArgs);
- checkMethodResult = true;
- } else {
- result = member.newInstance(invokeArgs);
- }
-
- }
-
- if (checkMethodResult) {
- if (hasVoidReturn) {
- result = Undefined.instance;
- } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) {
- result = cx.getWrapFactory().wrap(cx, scope, result, null);
- }
- // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE
- // then the Java method did a proper job of converting the
- // result to JS primitive or Scriptable to avoid
- // potentially costly Context.javaToJS call.
- }
-
- return result;
- }
-
- /**
- * Return new {@link Scriptable} instance using the default
- * constructor for the class of the underlying Java method.
- * Return null to indicate that the call method should be used to create
- * new objects.
- */
- public Scriptable createObject(Context cx, Scriptable scope) {
- if (member.isCtor() || parmsLength == VARARGS_CTOR) {
- return null;
- }
- Scriptable result;
- try {
- result = (Scriptable) member.getDeclaringClass().newInstance();
- } catch (Exception ex) {
- throw Context.throwAsScriptRuntimeEx(ex);
- }
-
- result.setPrototype(getClassPrototype());
- result.setParentScope(getParentScope());
- return result;
- }
-
- boolean isVarArgsMethod() {
- return parmsLength == VARARGS_METHOD;
- }
-
- boolean isVarArgsConstructor() {
- return parmsLength == VARARGS_CTOR;
- }
-
- private void readObject(ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- if (parmsLength > 0) {
- Class[] types = member.argTypes;
- typeTags = new byte[parmsLength];
- for (int i = 0; i != parmsLength; ++i) {
- typeTags[i] = (byte)getTypeTag(types[i]);
- }
- }
- if (member.isMethod()) {
- Method method = member.method();
- Class returnType = method.getReturnType();
- if (returnType == Void.TYPE) {
- hasVoidReturn = true;
- } else {
- returnTypeTag = getTypeTag(returnType);
- }
- }
- }
-
- private static final short VARARGS_METHOD = -1;
- private static final short VARARGS_CTOR = -2;
-
- private static boolean sawSecurityException;
-
- public static final int JAVA_UNSUPPORTED_TYPE = 0;
- public static final int JAVA_STRING_TYPE = 1;
- public static final int JAVA_INT_TYPE = 2;
- public static final int JAVA_BOOLEAN_TYPE = 3;
- public static final int JAVA_DOUBLE_TYPE = 4;
- public static final int JAVA_SCRIPTABLE_TYPE = 5;
- public static final int JAVA_OBJECT_TYPE = 6;
-
- MemberBox member;
- private String functionName;
- private transient byte[] typeTags;
- private int parmsLength;
- private transient boolean hasVoidReturn;
- private transient int returnTypeTag;
- private boolean isStatic;
-}