Constructors are not assigned to prototype, as they are not inherited. newInstance checks for access rights.
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 29 Dec 2012 19:46:09 +0100
changeset 3972adac52f955e
parent 396 4c7619614872
child 398 945c799a6812
Constructors are not assigned to prototype, as they are not inherited. newInstance checks for access rights.
emul/src/main/java/java/lang/Class.java
javap/src/main/java/org/apidesign/javap/MethodData.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java
vm/src/test/java/org/apidesign/vm4brwsr/Classes.java
     1.1 --- a/emul/src/main/java/java/lang/Class.java	Sat Dec 29 19:44:58 2012 +0100
     1.2 +++ b/emul/src/main/java/java/lang/Class.java	Sat Dec 29 19:46:09 2012 +0100
     1.3 @@ -210,15 +210,32 @@
     1.4       *             </ul>
     1.5       *
     1.6       */
     1.7 -    @JavaScriptBody(args = "self", body =
     1.8 -          "var inst = self.cnstr();"
     1.9 -        + "inst.cons__V(inst);"
    1.10 -        + "return inst;"
    1.11 +    @JavaScriptBody(args = { "self", "illegal" }, body =
    1.12 +          "\nvar c = self.cnstr;"
    1.13 +        + "\nif (c['cons__V']) {"
    1.14 +        + "\n  if ((c.cons__V.access & 0x1) != 0) {"
    1.15 +        + "\n    var inst = c();"
    1.16 +        + "\n    c.cons__V(inst);"
    1.17 +        + "\n    return inst;"
    1.18 +        + "\n  }"
    1.19 +        + "\n  return illegal;"
    1.20 +        + "\n}"
    1.21 +        + "\nreturn null;"
    1.22      )
    1.23 +    private static native Object newInstance0(Class<?> self, Object illegal);
    1.24 +    
    1.25      public T newInstance()
    1.26          throws InstantiationException, IllegalAccessException
    1.27      {
    1.28 -        throw new UnsupportedOperationException();
    1.29 +        Object illegal = new Object();
    1.30 +        Object inst = newInstance0(this, illegal);
    1.31 +        if (inst == null) {
    1.32 +            throw new InstantiationException(getName());
    1.33 +        }
    1.34 +        if (inst == illegal) {
    1.35 +            throw new IllegalAccessException();
    1.36 +        }
    1.37 +        return (T)inst;
    1.38      }
    1.39  
    1.40      /**
     2.1 --- a/javap/src/main/java/org/apidesign/javap/MethodData.java	Sat Dec 29 19:44:58 2012 +0100
     2.2 +++ b/javap/src/main/java/org/apidesign/javap/MethodData.java	Sat Dec 29 19:46:09 2012 +0100
     2.3 @@ -25,9 +25,9 @@
     2.4  
     2.5  package org.apidesign.javap;
     2.6  
     2.7 -import java.io.*;
     2.8 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
     2.9  
    2.10 +import java.io.DataInputStream;
    2.11 +import java.io.IOException;
    2.12  import static org.apidesign.javap.RuntimeConstants.*;
    2.13  
    2.14  /**
    2.15 @@ -387,4 +387,8 @@
    2.16          attrs.copyInto(arr);
    2.17          return ClassData.findAttr(n, arr);
    2.18      }
    2.19 +
    2.20 +    public boolean isConstructor() {
    2.21 +        return "<init>".equals(getName());
    2.22 +    }
    2.23  }
     3.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sat Dec 29 19:44:58 2012 +0100
     3.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sat Dec 29 19:46:09 2012 +0100
     3.3 @@ -135,19 +135,27 @@
     3.4                  }
     3.5                  continue;
     3.6              }
     3.7 +            String prefix;
     3.8              String mn;
     3.9              if (m.isStatic()) {
    3.10 -                mn = generateStaticMethod("\n    c.", m, toInitilize);
    3.11 +                prefix = "\n    c.";
    3.12 +                mn = generateStaticMethod(prefix, m, toInitilize);
    3.13              } else {
    3.14 -                mn = generateInstanceMethod("\n    c.", m);
    3.15 +                if (m.isConstructor()) {
    3.16 +                    prefix = "\n    CLS.";
    3.17 +                    mn = generateInstanceMethod(prefix, m);
    3.18 +                } else {
    3.19 +                    prefix = "\n    c.";
    3.20 +                    mn = generateInstanceMethod(prefix, m);
    3.21 +                }
    3.22              }
    3.23              byte[] runAnno = m.findAnnotationData(false);
    3.24              if (runAnno != null) {
    3.25 -                out.append("\n    c.").append(mn).append(".anno = {");
    3.26 +                out.append(prefix).append(mn).append(".anno = {");
    3.27                  generateAnno(jc, out, runAnno);
    3.28                  out.append("\n    };");
    3.29              }
    3.30 -            out.append("\n    c.").append(mn).append(".access = " + m.getAccess()).append(";");
    3.31 +            out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
    3.32          }
    3.33          out.append("\n    c.constructor = CLS;");
    3.34          out.append("\n    c.$instOf_").append(className).append(" = true;");
    3.35 @@ -1122,7 +1130,7 @@
    3.36                          final String classInternalName = jc.getClassName(e.catch_cpx);
    3.37                          addReference(classInternalName);
    3.38                          out.append("if (e.$instOf_"+classInternalName.replace('/', '_')+") {");
    3.39 -                        out.append("gt="+e.handler_pc+"; continue;");
    3.40 +                        out.append("gt="+e.handler_pc+"; stA0 = e; continue;");
    3.41                          out.append("} ");
    3.42                      } else {
    3.43                          //finally - todo
    3.44 @@ -1311,6 +1319,9 @@
    3.45          final String in = mi[0];
    3.46          out.append(accessClass(in.replace('/', '_')));
    3.47          out.append("(false).");
    3.48 +        if (mn.startsWith("cons_")) {
    3.49 +            out.append("constructor.");
    3.50 +        }
    3.51          out.append(mn);
    3.52          out.append('(');
    3.53          if (numArguments > 0) {
     4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Sat Dec 29 19:44:58 2012 +0100
     4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Sat Dec 29 19:46:09 2012 +0100
     4.3 @@ -74,6 +74,16 @@
     4.4      @Test public void jsNewInstance() throws Exception {
     4.5          assertExec("Check new instance", Classes.class, "newInstance__Z", Double.valueOf(1));
     4.6      }
     4.7 +    @Test public void javaNoNewInstance() throws Exception {
     4.8 +        assertEquals("java.lang.InstantiationException:java.lang.Float", 
     4.9 +            Classes.newInstanceNoPubConstructor()
    4.10 +        );
    4.11 +    }
    4.12 +    @Test public void jsNoNewInstance() throws Exception {
    4.13 +        assertExec("Check problems with new instance", Classes.class, "newInstanceNoPubConstructor__Ljava_lang_String_2", 
    4.14 +            "java.lang.InstantiationException:java.lang.Float"
    4.15 +        );
    4.16 +    }
    4.17      @Test public void jsAnnotation() throws Exception {
    4.18          assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
    4.19      }
     5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Sat Dec 29 19:44:58 2012 +0100
     5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Sat Dec 29 19:46:09 2012 +0100
     5.3 @@ -72,6 +72,14 @@
     5.4          }
     5.5          throw new IllegalStateException("Not a subtype: " + ioe);
     5.6      }
     5.7 +    public static String newInstanceNoPubConstructor() throws Exception {
     5.8 +        try {
     5.9 +            Float f = Float.class.newInstance();
    5.10 +            return "wrong, can't instantiate: " + f;
    5.11 +        } catch (Exception ex) {
    5.12 +            return (ex.getClass().getName() + ":" + ex.getMessage()).toString().toString();
    5.13 +        }
    5.14 +    }
    5.15      public static int getMarker() {
    5.16          if (!Classes.class.isAnnotationPresent(ClassesMarker.class)) {
    5.17              return -2;