Ability to control prototypes. Making sure any JavaScript Object is instance of Java object
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 02 Dec 2012 21:00:12 +0100
changeset 2398ceee38f5840
parent 232 36f16c49bdef
child 240 4e88a33d7972
Ability to control prototypes. Making sure any JavaScript Object is instance of Java object
core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java
emul/src/main/java/java/lang/Object.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/test/java/org/apidesign/vm4brwsr/Instance.java
vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java	Sun Dec 02 21:00:12 2012 +0100
     1.3 @@ -0,0 +1,41 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.bck2brwsr.core;
    1.22 +
    1.23 +import java.lang.annotation.ElementType;
    1.24 +import java.lang.annotation.Retention;
    1.25 +import java.lang.annotation.RetentionPolicy;
    1.26 +import java.lang.annotation.Target;
    1.27 +
    1.28 +/** Controls how JavaScript inheritance should be handled.
    1.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.30 + */
    1.31 +@Retention(RetentionPolicy.CLASS)
    1.32 +@Target({ ElementType.TYPE })
    1.33 +public @interface JavaScriptPrototype {
    1.34 +    /** Expression that identifies the function where all methods
    1.35 +     * should be added into.
    1.36 +     * @return name of function to contain methods found in given class
    1.37 +     */
    1.38 +    String container();
    1.39 +    /** Expression that defines the way to construct prototype for this
    1.40 +     * class.
    1.41 +     * @return expression to construct prototype
    1.42 +     */
    1.43 +    String prototype();
    1.44 +}
     2.1 --- a/emul/src/main/java/java/lang/Object.java	Sun Dec 02 06:25:28 2012 +0100
     2.2 +++ b/emul/src/main/java/java/lang/Object.java	Sun Dec 02 21:00:12 2012 +0100
     2.3 @@ -26,6 +26,7 @@
     2.4  package java.lang;
     2.5  
     2.6  import org.apidesign.bck2brwsr.core.JavaScriptBody;
     2.7 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
     2.8  
     2.9  /**
    2.10   * Class {@code Object} is the root of the class hierarchy.
    2.11 @@ -36,6 +37,7 @@
    2.12   * @see     java.lang.Class
    2.13   * @since   JDK1.0
    2.14   */
    2.15 +@JavaScriptPrototype(container = "Object.prototype", prototype = "new Object")
    2.16  public class Object {
    2.17  
    2.18      @JavaScriptBody(args = {}, body = "")
     3.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sun Dec 02 06:25:28 2012 +0100
     3.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sun Dec 02 21:00:12 2012 +0100
     3.3 @@ -82,6 +82,10 @@
     3.4                  return null;
     3.5              }
     3.6          }
     3.7 +        String[] proto = findAnnotation(arrData, jc, 
     3.8 +            "org.apidesign.bck2brwsr.core.JavaScriptPrototype", 
     3.9 +            "container", "prototype"
    3.10 +        );
    3.11          StringArray toInitilize = new StringArray();
    3.12          final String className = className(jc);
    3.13          out.append("\n\n").append(assignClass(className));
    3.14 @@ -92,25 +96,26 @@
    3.15                  out.append("\n  CLS.").append(v.getName()).append(initField(v));
    3.16              }
    3.17          }
    3.18 -        // ClassName sc = jc.getSuperClass();
    3.19 -        String sc = jc.getSuperClassName(); // with _
    3.20 -        if (sc != null) {
    3.21 +        if (proto == null) {
    3.22 +            String sc = jc.getSuperClassName(); // with _
    3.23              out.append("\n    var p = CLS.prototype = ").
    3.24                  append(sc.replace('/', '_')).append("(true);");
    3.25 +            out.append("\n    var c = p;");
    3.26          } else {
    3.27 -            out.append("\n    var p = CLS.prototype;");
    3.28 +            out.append("\n    var p = ").append(proto[1]).append(";");
    3.29 +            out.append("\n    var c = ").append(proto[0]).append(";");
    3.30          }
    3.31          for (MethodData m : jc.getMethods()) {
    3.32              if (m.isStatic()) {
    3.33 -                generateStaticMethod("\n    p.", m, toInitilize);
    3.34 +                generateStaticMethod("\n    c.", m, toInitilize);
    3.35              } else {
    3.36 -                generateInstanceMethod("\n    p.", m);
    3.37 +                generateInstanceMethod("\n    c.", m);
    3.38              }
    3.39          }
    3.40 -        out.append("\n    p.constructor = CLS;");
    3.41 -        out.append("\n    p.$instOf_").append(className).append(" = true;");
    3.42 +        out.append("\n    c.constructor = CLS;");
    3.43 +        out.append("\n    c.$instOf_").append(className).append(" = true;");
    3.44          for (String superInterface : jc.getSuperInterfaces()) {
    3.45 -            out.append("\n    p.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
    3.46 +            out.append("\n    c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
    3.47          }
    3.48          out.append("\n  }");
    3.49          out.append("\n  if (arguments.length === 0) {");
     4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Sun Dec 02 06:25:28 2012 +0100
     4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Sun Dec 02 21:00:12 2012 +0100
     4.3 @@ -117,4 +117,12 @@
     4.4          
     4.5          return constructor(x) == constructor(y);
     4.6      }
     4.7 +    @JavaScriptBody(args = {}, body = "return {};")
     4.8 +    private static Object jsObj() {
     4.9 +        return null;
    4.10 +    }
    4.11 +    
    4.12 +    public static boolean iofObject() {
    4.13 +        return jsObj() instanceof Object;
    4.14 +    }
    4.15  }
     5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Sun Dec 02 06:25:28 2012 +0100
     5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Sun Dec 02 21:00:12 2012 +0100
     5.3 @@ -123,6 +123,14 @@
     5.4              Double.valueOf(0)
     5.5          );
     5.6      }
     5.7 +
     5.8 +    @Test public void jsObjectIsLikeJavaObject() throws Exception {
     5.9 +        assertExec(
    5.10 +            "JavaScript object is instance of Java Object",
    5.11 +            Instance.class, "iofObjectZ",
    5.12 +            Double.valueOf(1)
    5.13 +        );
    5.14 +    }
    5.15      
    5.16      protected String startCompilationWith() {
    5.17          return "org/apidesign/vm4brwsr/Instance";