Can use Constructor.newInstance with parameters javac
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 28 Sep 2013 12:03:59 +0200
branchjavac
changeset 13217a78a84ab583
parent 1320 e49c4c2c3737
child 1322 1bf52dbf783e
Can use Constructor.newInstance with parameters
rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java
rt/emul/mini/src/main/java/java/lang/Class.java
rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java
rt/emul/mini/src/main/java/java/lang/reflect/Method.java
rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java
     1.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Sat Sep 28 02:45:17 2013 +0200
     1.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Sat Sep 28 12:03:59 2013 +0200
     1.3 @@ -19,6 +19,7 @@
     1.4  
     1.5  import java.lang.annotation.Retention;
     1.6  import java.lang.annotation.RetentionPolicy;
     1.7 +import java.lang.reflect.Constructor;
     1.8  import java.lang.reflect.Method;
     1.9  import java.util.Arrays;
    1.10  import java.util.Collections;
    1.11 @@ -77,6 +78,10 @@
    1.12          return Runnable.class.getDeclaredMethod("run").getName();
    1.13      }
    1.14      
    1.15 +    @Compare public String intValue() throws Exception {
    1.16 +        return Integer.class.getConstructor(int.class).newInstance(10).toString();
    1.17 +    }
    1.18 +    
    1.19      @Compare public String namesOfMethods() {
    1.20          StringBuilder sb = new StringBuilder();
    1.21          String[] arr = new String[20];
    1.22 @@ -90,6 +95,19 @@
    1.23          return sb.toString();
    1.24      }
    1.25  
    1.26 +    @Compare public String paramsOfConstructors() {
    1.27 +        StringBuilder sb = new StringBuilder();
    1.28 +        String[] arr = new String[20];
    1.29 +        int i = 0;
    1.30 +        for (Constructor<?> m : StaticUse.class.getConstructors()) {
    1.31 +            arr[i++] = m.getName();
    1.32 +        }
    1.33 +        for (String s : sort(arr, i)) {
    1.34 +            sb.append(s).append("\n");
    1.35 +        }
    1.36 +        return sb.toString();
    1.37 +    }
    1.38 +
    1.39      @Compare public String namesOfDeclaringClassesOfMethods() {
    1.40          StringBuilder sb = new StringBuilder();
    1.41          String[] arr = new String[20];
     2.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java	Sat Sep 28 02:45:17 2013 +0200
     2.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java	Sat Sep 28 12:03:59 2013 +0200
     2.3 @@ -29,6 +29,7 @@
     2.4  import org.apidesign.bck2brwsr.emul.reflect.AnnotationImpl;
     2.5  import java.io.InputStream;
     2.6  import java.lang.annotation.Annotation;
     2.7 +import java.lang.reflect.Constructor;
     2.8  import java.lang.reflect.Field;
     2.9  import java.lang.reflect.Method;
    2.10  import java.lang.reflect.TypeVariable;
    2.11 @@ -1106,6 +1107,188 @@
    2.12      }
    2.13      
    2.14      /**
    2.15 +     * Returns an array containing {@code Constructor} objects reflecting
    2.16 +     * all the public constructors of the class represented by this
    2.17 +     * {@code Class} object.  An array of length 0 is returned if the
    2.18 +     * class has no public constructors, or if the class is an array class, or
    2.19 +     * if the class reflects a primitive type or void.
    2.20 +     *
    2.21 +     * Note that while this method returns an array of {@code
    2.22 +     * Constructor<T>} objects (that is an array of constructors from
    2.23 +     * this class), the return type of this method is {@code
    2.24 +     * Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as
    2.25 +     * might be expected.  This less informative return type is
    2.26 +     * necessary since after being returned from this method, the
    2.27 +     * array could be modified to hold {@code Constructor} objects for
    2.28 +     * different classes, which would violate the type guarantees of
    2.29 +     * {@code Constructor<T>[]}.
    2.30 +     *
    2.31 +     * @return the array of {@code Constructor} objects representing the
    2.32 +     *  public constructors of this class
    2.33 +     * @exception  SecurityException
    2.34 +     *             If a security manager, <i>s</i>, is present and any of the
    2.35 +     *             following conditions is met:
    2.36 +     *
    2.37 +     *             <ul>
    2.38 +     *
    2.39 +     *             <li> invocation of
    2.40 +     *             {@link SecurityManager#checkMemberAccess
    2.41 +     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
    2.42 +     *             access to the constructors within this class
    2.43 +     *
    2.44 +     *             <li> the caller's class loader is not the same as or an
    2.45 +     *             ancestor of the class loader for the current class and
    2.46 +     *             invocation of {@link SecurityManager#checkPackageAccess
    2.47 +     *             s.checkPackageAccess()} denies access to the package
    2.48 +     *             of this class
    2.49 +     *
    2.50 +     *             </ul>
    2.51 +     *
    2.52 +     * @since JDK1.1
    2.53 +     */
    2.54 +    public Constructor<?>[] getConstructors() throws SecurityException {
    2.55 +        return MethodImpl.findConstructors(this, 0x01);
    2.56 +    }
    2.57 +
    2.58 +    /**
    2.59 +     * Returns a {@code Constructor} object that reflects the specified
    2.60 +     * public constructor of the class represented by this {@code Class}
    2.61 +     * object. The {@code parameterTypes} parameter is an array of
    2.62 +     * {@code Class} objects that identify the constructor's formal
    2.63 +     * parameter types, in declared order.
    2.64 +     *
    2.65 +     * If this {@code Class} object represents an inner class
    2.66 +     * declared in a non-static context, the formal parameter types
    2.67 +     * include the explicit enclosing instance as the first parameter.
    2.68 +     *
    2.69 +     * <p> The constructor to reflect is the public constructor of the class
    2.70 +     * represented by this {@code Class} object whose formal parameter
    2.71 +     * types match those specified by {@code parameterTypes}.
    2.72 +     *
    2.73 +     * @param parameterTypes the parameter array
    2.74 +     * @return the {@code Constructor} object of the public constructor that
    2.75 +     * matches the specified {@code parameterTypes}
    2.76 +     * @exception NoSuchMethodException if a matching method is not found.
    2.77 +     * @exception  SecurityException
    2.78 +     *             If a security manager, <i>s</i>, is present and any of the
    2.79 +     *             following conditions is met:
    2.80 +     *
    2.81 +     *             <ul>
    2.82 +     *
    2.83 +     *             <li> invocation of
    2.84 +     *             {@link SecurityManager#checkMemberAccess
    2.85 +     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
    2.86 +     *             access to the constructor
    2.87 +     *
    2.88 +     *             <li> the caller's class loader is not the same as or an
    2.89 +     *             ancestor of the class loader for the current class and
    2.90 +     *             invocation of {@link SecurityManager#checkPackageAccess
    2.91 +     *             s.checkPackageAccess()} denies access to the package
    2.92 +     *             of this class
    2.93 +     *
    2.94 +     *             </ul>
    2.95 +     *
    2.96 +     * @since JDK1.1
    2.97 +     */
    2.98 +    public Constructor<T> getConstructor(Class<?>... parameterTypes)
    2.99 +    throws NoSuchMethodException, SecurityException {
   2.100 +        Constructor c = MethodImpl.findConstructor(this, parameterTypes);
   2.101 +        if (c == null) {
   2.102 +            StringBuilder sb = new StringBuilder();
   2.103 +            sb.append(getName()).append('(');
   2.104 +            String sep = "";
   2.105 +            for (int i = 0; i < parameterTypes.length; i++) {
   2.106 +                sb.append(sep).append(parameterTypes[i].getName());
   2.107 +                sep = ", ";
   2.108 +            }
   2.109 +            sb.append(')');
   2.110 +            throw new NoSuchMethodException(sb.toString());
   2.111 +        }
   2.112 +        return c;
   2.113 +    }
   2.114 +
   2.115 +    /**
   2.116 +     * Returns an array of {@code Constructor} objects reflecting all the
   2.117 +     * constructors declared by the class represented by this
   2.118 +     * {@code Class} object. These are public, protected, default
   2.119 +     * (package) access, and private constructors.  The elements in the array
   2.120 +     * returned are not sorted and are not in any particular order.  If the
   2.121 +     * class has a default constructor, it is included in the returned array.
   2.122 +     * This method returns an array of length 0 if this {@code Class}
   2.123 +     * object represents an interface, a primitive type, an array class, or
   2.124 +     * void.
   2.125 +     *
   2.126 +     * <p> See <em>The Java Language Specification</em>, section 8.2.
   2.127 +     *
   2.128 +     * @return    the array of {@code Constructor} objects representing all the
   2.129 +     * declared constructors of this class
   2.130 +     * @exception  SecurityException
   2.131 +     *             If a security manager, <i>s</i>, is present and any of the
   2.132 +     *             following conditions is met:
   2.133 +     *
   2.134 +     *             <ul>
   2.135 +     *
   2.136 +     *             <li> invocation of
   2.137 +     *             {@link SecurityManager#checkMemberAccess
   2.138 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
   2.139 +     *             access to the declared constructors within this class
   2.140 +     *
   2.141 +     *             <li> the caller's class loader is not the same as or an
   2.142 +     *             ancestor of the class loader for the current class and
   2.143 +     *             invocation of {@link SecurityManager#checkPackageAccess
   2.144 +     *             s.checkPackageAccess()} denies access to the package
   2.145 +     *             of this class
   2.146 +     *
   2.147 +     *             </ul>
   2.148 +     *
   2.149 +     * @since JDK1.1
   2.150 +     */
   2.151 +    public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
   2.152 +        throw new SecurityException();
   2.153 +    }
   2.154 +    /**
   2.155 +     * Returns a {@code Constructor} object that reflects the specified
   2.156 +     * constructor of the class or interface represented by this
   2.157 +     * {@code Class} object.  The {@code parameterTypes} parameter is
   2.158 +     * an array of {@code Class} objects that identify the constructor's
   2.159 +     * formal parameter types, in declared order.
   2.160 +     *
   2.161 +     * If this {@code Class} object represents an inner class
   2.162 +     * declared in a non-static context, the formal parameter types
   2.163 +     * include the explicit enclosing instance as the first parameter.
   2.164 +     *
   2.165 +     * @param parameterTypes the parameter array
   2.166 +     * @return    The {@code Constructor} object for the constructor with the
   2.167 +     * specified parameter list
   2.168 +     * @exception NoSuchMethodException if a matching method is not found.
   2.169 +     * @exception  SecurityException
   2.170 +     *             If a security manager, <i>s</i>, is present and any of the
   2.171 +     *             following conditions is met:
   2.172 +     *
   2.173 +     *             <ul>
   2.174 +     *
   2.175 +     *             <li> invocation of
   2.176 +     *             {@link SecurityManager#checkMemberAccess
   2.177 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
   2.178 +     *             access to the declared constructor
   2.179 +     *
   2.180 +     *             <li> the caller's class loader is not the same as or an
   2.181 +     *             ancestor of the class loader for the current class and
   2.182 +     *             invocation of {@link SecurityManager#checkPackageAccess
   2.183 +     *             s.checkPackageAccess()} denies access to the package
   2.184 +     *             of this class
   2.185 +     *
   2.186 +     *             </ul>
   2.187 +     *
   2.188 +     * @since JDK1.1
   2.189 +     */
   2.190 +    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
   2.191 +    throws NoSuchMethodException, SecurityException {
   2.192 +        return getConstructor(parameterTypes);
   2.193 +    }
   2.194 +    
   2.195 +    
   2.196 +    /**
   2.197       * Character.isDigit answers {@code true} to some non-ascii
   2.198       * digits.  This one does not.
   2.199       */
     3.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Sat Sep 28 02:45:17 2013 +0200
     3.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Sat Sep 28 12:03:59 2013 +0200
     3.3 @@ -26,6 +26,10 @@
     3.4  package java.lang.reflect;
     3.5  
     3.6  import java.lang.annotation.Annotation;
     3.7 +import static java.lang.reflect.Method.fromPrimitive;
     3.8 +import static java.lang.reflect.Method.getAccess;
     3.9 +import static java.lang.reflect.Method.getParameterTypes;
    3.10 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    3.11  import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
    3.12  
    3.13  /**
    3.14 @@ -53,44 +57,20 @@
    3.15                                                      GenericDeclaration,
    3.16                                                      Member {
    3.17  
    3.18 -    private Class<T>            clazz;
    3.19 -    private int                 slot;
    3.20 -    private Class<?>[]          parameterTypes;
    3.21 -    private Class<?>[]          exceptionTypes;
    3.22 -    private int                 modifiers;
    3.23 -    // Generics and annotations support
    3.24 -    private transient String    signature;
    3.25 -    private byte[]              annotations;
    3.26 -    private byte[]              parameterAnnotations;
    3.27 -
    3.28 -
    3.29 -    // For sharing of ConstructorAccessors. This branching structure
    3.30 -    // is currently only two levels deep (i.e., one root Constructor
    3.31 -    // and potentially many Constructor objects pointing to it.)
    3.32 -    private Constructor<T>      root;
    3.33 +    private final Class<T> clazz;
    3.34 +    private final Object data;
    3.35 +    private final String sig;
    3.36  
    3.37      /**
    3.38       * Package-private constructor used by ReflectAccess to enable
    3.39       * instantiation of these objects in Java code from the java.lang
    3.40       * package via sun.reflect.LangReflectAccess.
    3.41       */
    3.42 -    Constructor(Class<T> declaringClass,
    3.43 -                Class<?>[] parameterTypes,
    3.44 -                Class<?>[] checkedExceptions,
    3.45 -                int modifiers,
    3.46 -                int slot,
    3.47 -                String signature,
    3.48 -                byte[] annotations,
    3.49 -                byte[] parameterAnnotations)
    3.50 +    Constructor(Class<T> declaringClass, Object data, String sig)
    3.51      {
    3.52          this.clazz = declaringClass;
    3.53 -        this.parameterTypes = parameterTypes;
    3.54 -        this.exceptionTypes = checkedExceptions;
    3.55 -        this.modifiers = modifiers;
    3.56 -        this.slot = slot;
    3.57 -        this.signature = signature;
    3.58 -        this.annotations = annotations;
    3.59 -        this.parameterAnnotations = parameterAnnotations;
    3.60 +        this.data = data;
    3.61 +        this.sig = sig;
    3.62      }
    3.63  
    3.64      /**
    3.65 @@ -126,7 +106,7 @@
    3.66       * @see Modifier
    3.67       */
    3.68      public int getModifiers() {
    3.69 -        return modifiers;
    3.70 +        return getAccess(data);
    3.71      }
    3.72  
    3.73      /**
    3.74 @@ -159,7 +139,7 @@
    3.75       * represents
    3.76       */
    3.77      public Class<?>[] getParameterTypes() {
    3.78 -        return (Class<?>[]) parameterTypes.clone();
    3.79 +        return Method.getParameterTypes(sig);
    3.80      }
    3.81  
    3.82  
    3.83 @@ -205,7 +185,7 @@
    3.84       * constructor this object represents
    3.85       */
    3.86      public Class<?>[] getExceptionTypes() {
    3.87 -        return (Class<?>[])exceptionTypes.clone();
    3.88 +        throw new UnsupportedOperationException();
    3.89      }
    3.90  
    3.91  
    3.92 @@ -242,20 +222,9 @@
    3.93       * same formal parameter types.
    3.94       */
    3.95      public boolean equals(Object obj) {
    3.96 -        if (obj != null && obj instanceof Constructor) {
    3.97 -            Constructor<?> other = (Constructor<?>)obj;
    3.98 -            if (getDeclaringClass() == other.getDeclaringClass()) {
    3.99 -                /* Avoid unnecessary cloning */
   3.100 -                Class<?>[] params1 = parameterTypes;
   3.101 -                Class<?>[] params2 = other.parameterTypes;
   3.102 -                if (params1.length == params2.length) {
   3.103 -                    for (int i = 0; i < params1.length; i++) {
   3.104 -                        if (params1[i] != params2[i])
   3.105 -                            return false;
   3.106 -                    }
   3.107 -                    return true;
   3.108 -                }
   3.109 -            }
   3.110 +        if (obj instanceof Constructor) {
   3.111 +            Constructor other = (Constructor)obj;
   3.112 +            return data == other.data;
   3.113          }
   3.114          return false;
   3.115      }
   3.116 @@ -293,13 +262,14 @@
   3.117              }
   3.118              sb.append(Field.getTypeName(getDeclaringClass()));
   3.119              sb.append("(");
   3.120 -            Class<?>[] params = parameterTypes; // avoid clone
   3.121 +            Class<?>[] params = getParameterTypes(); // avoid clone
   3.122              for (int j = 0; j < params.length; j++) {
   3.123                  sb.append(Field.getTypeName(params[j]));
   3.124                  if (j < (params.length - 1))
   3.125                      sb.append(",");
   3.126              }
   3.127              sb.append(")");
   3.128 +            /*
   3.129              Class<?>[] exceptions = exceptionTypes; // avoid clone
   3.130              if (exceptions.length > 0) {
   3.131                  sb.append(" throws ");
   3.132 @@ -309,6 +279,7 @@
   3.133                          sb.append(",");
   3.134                  }
   3.135              }
   3.136 +            */
   3.137              return sb.toString();
   3.138          } catch (Exception e) {
   3.139              return "<" + e + ">";
   3.140 @@ -452,9 +423,29 @@
   3.141          throws InstantiationException, IllegalAccessException,
   3.142                 IllegalArgumentException, InvocationTargetException
   3.143      {
   3.144 -        throw new SecurityException();
   3.145 +        Class[] types = getParameterTypes();
   3.146 +        if (types.length != initargs.length) {
   3.147 +            throw new IllegalArgumentException("Types len " + types.length + " args: " + initargs.length);
   3.148 +        } else {
   3.149 +            initargs = initargs.clone();
   3.150 +            for (int i = 0; i < types.length; i++) {
   3.151 +                Class c = types[i];
   3.152 +                if (c.isPrimitive() && initargs[i] != null) {
   3.153 +                    initargs[i] = Method.toPrimitive(initargs[i]);
   3.154 +                }
   3.155 +            }
   3.156 +        }
   3.157 +        return (T) newInstance0(this.getDeclaringClass(), "cons__" + sig, initargs);
   3.158      }
   3.159  
   3.160 +    @JavaScriptBody(args = { "self", "sig", "args" }, body =
   3.161 +          "\nvar c = self.cnstr;"
   3.162 +        + "\nvar inst = c();"
   3.163 +        + "\nc[sig].apply(inst, args);"
   3.164 +        + "\nreturn inst;"
   3.165 +    )
   3.166 +    private static native Object newInstance0(Class<?> self, String sig, Object[] args);
   3.167 +    
   3.168      /**
   3.169       * Returns {@code true} if this constructor was declared to take
   3.170       * a variable number of arguments; returns {@code false}
   3.171 @@ -481,22 +472,6 @@
   3.172          return Modifier.isSynthetic(getModifiers());
   3.173      }
   3.174  
   3.175 -    int getSlot() {
   3.176 -        return slot;
   3.177 -    }
   3.178 -
   3.179 -   String getSignature() {
   3.180 -            return signature;
   3.181 -   }
   3.182 -
   3.183 -    byte[] getRawAnnotations() {
   3.184 -        return annotations;
   3.185 -    }
   3.186 -
   3.187 -    byte[] getRawParameterAnnotations() {
   3.188 -        return parameterAnnotations;
   3.189 -    }
   3.190 -
   3.191      /**
   3.192       * @throws NullPointerException {@inheritDoc}
   3.193       * @since 1.5
   3.194 @@ -532,11 +507,11 @@
   3.195       * @since 1.5
   3.196       */
   3.197      public Annotation[][] getParameterAnnotations() {
   3.198 -        int numParameters = parameterTypes.length;
   3.199 -        if (parameterAnnotations == null)
   3.200 -            return new Annotation[numParameters][0];
   3.201 +//        int numParameters = parameterTypes.length;
   3.202 +//        if (parameterAnnotations == null)
   3.203 +//            return new Annotation[numParameters][0];
   3.204          
   3.205 -        return new Annotation[numParameters][0]; // XXX
   3.206 +        return new Annotation[0][0]; // XXX
   3.207  /*
   3.208          Annotation[][] result = AnnotationParser.parseParameterAnnotations(
   3.209              parameterAnnotations,
     4.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Sat Sep 28 02:45:17 2013 +0200
     4.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Sat Sep 28 12:03:59 2013 +0200
     4.3 @@ -113,7 +113,7 @@
     4.4      }
     4.5      
     4.6      @JavaScriptBody(args = "self", body = "return self.access;")
     4.7 -    private static native int getAccess(Object self);
     4.8 +    static native int getAccess(Object self);
     4.9      
    4.10      /**
    4.11       * Returns an array of {@code TypeVariable} objects that represent the
    4.12 @@ -183,6 +183,10 @@
    4.13       * represents
    4.14       */
    4.15      public Class<?>[] getParameterTypes() {
    4.16 +        return getParameterTypes(sig);
    4.17 +    }
    4.18 +    
    4.19 +    static Class<?>[] getParameterTypes(String sig) {
    4.20          Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1];
    4.21          Enumeration<Class> en = MethodImpl.signatureParser(sig);
    4.22          en.nextElement(); // return type
    4.23 @@ -583,7 +587,7 @@
    4.24      private static native Integer fromRaw(Class<?> cls, String m, Object o);
    4.25  
    4.26      @JavaScriptBody(args = { "o" }, body = "return o.valueOf();")
    4.27 -    private static native Object toPrimitive(Object o);
    4.28 +    static native Object toPrimitive(Object o);
    4.29      
    4.30      /**
    4.31       * Returns {@code true} if this method is a bridge
    4.32 @@ -692,6 +696,11 @@
    4.33              protected Method create(Class<?> declaringClass, String name, Object data, String sig) {
    4.34                  return new Method(declaringClass, name, data, sig);
    4.35              }
    4.36 +
    4.37 +            @Override
    4.38 +            protected Constructor create(Class<?> declaringClass, Object data, String sig) {
    4.39 +                return new Constructor(declaringClass, data, sig);
    4.40 +            }
    4.41          };
    4.42      }
    4.43  }
     5.1 --- a/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Sat Sep 28 02:45:17 2013 +0200
     5.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Sat Sep 28 12:03:59 2013 +0200
     5.3 @@ -18,6 +18,7 @@
     5.4  package org.apidesign.bck2brwsr.emul.reflect;
     5.5  
     5.6  import java.lang.reflect.Array;
     5.7 +import java.lang.reflect.Constructor;
     5.8  import java.lang.reflect.Method;
     5.9  import java.util.Enumeration;
    5.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    5.11 @@ -37,15 +38,17 @@
    5.12      }
    5.13  
    5.14      protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
    5.15 +    protected abstract Constructor create(Class<?> declaringClass, Object data, String sig);
    5.16      
    5.17      
    5.18      //
    5.19      // bck2brwsr implementation
    5.20      //
    5.21  
    5.22 -    @JavaScriptBody(args = {"clazz", "prefix"},
    5.23 +    @JavaScriptBody(args = {"clazz", "prefix", "cnstr"},
    5.24          body = ""
    5.25 -        + "var c = clazz.cnstr.prototype;"
    5.26 +        + "var c = clazz.cnstr;\n"
    5.27 +        + "if (!cnstr) c = c.prototype;"
    5.28          + "var arr = new Array();\n"
    5.29          + "for (m in c) {\n"
    5.30          + "  if (m.indexOf(prefix) === 0) {\n"
    5.31 @@ -57,11 +60,55 @@
    5.32          + "}\n"
    5.33          + "return arr;")
    5.34      private static native Object[] findMethodData(
    5.35 -        Class<?> clazz, String prefix);
    5.36 +        Class<?> clazz, String prefix, boolean cnstr);
    5.37  
    5.38 +    public static Constructor findConstructor(
    5.39 +        Class<?> clazz, Class<?>... parameterTypes) {
    5.40 +        Object[] data = findMethodData(clazz, "cons__", true);
    5.41 +        BIG: for (int i = 0; i < data.length; i += 3) {
    5.42 +            String sig = ((String) data[i]).substring(6);
    5.43 +            Class<?> cls = (Class<?>) data[i + 2];
    5.44 +            Constructor tmp = INSTANCE.create(cls, data[i + 1], sig);
    5.45 +            Class<?>[] tmpParms = tmp.getParameterTypes();
    5.46 +            if (parameterTypes.length != tmpParms.length) {
    5.47 +                continue;
    5.48 +            }
    5.49 +            for (int j = 0; j < tmpParms.length; j++) {
    5.50 +                if (!parameterTypes[j].equals(tmpParms[j])) {
    5.51 +                    continue BIG;
    5.52 +                }
    5.53 +            }
    5.54 +            return tmp;
    5.55 +        }
    5.56 +        return null;
    5.57 +    }
    5.58 +
    5.59 +    public static Constructor[] findConstructors(Class<?> clazz, int mask) {
    5.60 +        Object[] namesAndData = findMethodData(clazz, "", true);
    5.61 +        int cnt = 0;
    5.62 +        for (int i = 0; i < namesAndData.length; i += 3) {
    5.63 +            String sig = (String) namesAndData[i];
    5.64 +            Object data = namesAndData[i + 1];
    5.65 +            if (!sig.startsWith("cons__")) {
    5.66 +                continue;
    5.67 +            }
    5.68 +            sig = sig.substring(6);
    5.69 +            Class<?> cls = (Class<?>) namesAndData[i + 2];
    5.70 +            final Constructor m = INSTANCE.create(cls, data, sig);
    5.71 +            if ((m.getModifiers() & mask) == 0) {
    5.72 +                continue;
    5.73 +            }
    5.74 +            namesAndData[cnt++] = m;
    5.75 +        }
    5.76 +        Constructor[] arr = new Constructor[cnt];
    5.77 +        for (int i = 0; i < cnt; i++) {
    5.78 +            arr[i] = (Constructor) namesAndData[i];
    5.79 +        }
    5.80 +        return arr;
    5.81 +    }
    5.82      public static Method findMethod(
    5.83          Class<?> clazz, String name, Class<?>... parameterTypes) {
    5.84 -        Object[] data = findMethodData(clazz, name + "__");
    5.85 +        Object[] data = findMethodData(clazz, name + "__", false);
    5.86          BIG: for (int i = 0; i < data.length; i += 3) {
    5.87              String sig = ((String) data[i]).substring(name.length() + 2);
    5.88              Class<?> cls = (Class<?>) data[i + 2];
    5.89 @@ -81,7 +128,7 @@
    5.90      }
    5.91  
    5.92      public static Method[] findMethods(Class<?> clazz, int mask) {
    5.93 -        Object[] namesAndData = findMethodData(clazz, "");
    5.94 +        Object[] namesAndData = findMethodData(clazz, "", false);
    5.95          int cnt = 0;
    5.96          for (int i = 0; i < namesAndData.length; i += 3) {
    5.97              String sig = (String) namesAndData[i];