Add javadocs

This commit is contained in:
Alexey Andreev 2015-09-27 18:12:52 +03:00
parent 83d39bf943
commit aa42070311
9 changed files with 230 additions and 17 deletions

View File

@ -23,10 +23,102 @@ import java.lang.annotation.Target;
/** /**
* <p>Indicates that method is to have native JavaScript implementation. * <p>Indicates that method is to have native JavaScript implementation.
* Method only can take and return primitive values and {@link JSObject}s. * Method only can take and return primitive values and {@link JSObject}s.
* JSBody script can't call Java methods, but you can pass callbacks wrapped into {@link JSFunctor}.
* Note that unless method is static, it must belong to class that implements {@link JSObject}. * Note that unless method is static, it must belong to class that implements {@link JSObject}.
* If applied to non-native method, original Java body will be overwritten by JavaScript.</p> * If applied to non-native method, original Java body will be overwritten by JavaScript.</p>
* *
* <p>Example:</p>
*
* <pre>
* {@literal @}JSBody(params = { "message" }, script = "window.alert(message);")
* public static native void alert(String message);
* </pre>
*
* <p>The motivation for <code>params</code> field is the following: Java can avoid inclusion of parameter names
* into bytecode (for example, you can compile with no debug information). In order the JSO implementation
* with no access to original source code could work properly, JSO forces developer to specify parameter
* names explicitly.</p>
*
*
* <h2>Type conversion</h2>
*
* <p>A method marked with JSBody annotation is restricted to take parameters of allowed types.
* A type is allowed if it is either:</p>
*
* <ul>
* <li>a primitive Java type, i.e. <code>boolean</code>, <code>byte</code>, <code>short</code>, <code>char</code>,
* <code>int</code>, <code>long</code>, <code>float</code> or <code>double</code>;</li>
* <li>is <code>java.lang.String</code> class;</li>
* <li>an overlay type, see {@link JSObject};</li>
* <li>an array of allowed type.</li>
* </ul>
*
* <p>Java primitives are converted to corresponding JavaScript primitives, except for <code>char</code>,
* which does not have corresponding JavaScript representation. JSO implementation converts Java chars to JavaScript
* numbers, and expects a JavaScript number when converting to a Java character.</p>
*
* <p>Java arrays are converted to JavaScript arrays and vice versa. Arrays are passed by copy.</p>
*
* <p><code>java.lang.String</code> objects are converted to JavaScript string.</p>
*
* <p>Overlay types are passed as is.</p>
*
*
* <h2>Passing functions</h2>
*
* <p>Sometimes JavaScript functions expect you to pass a function as a parameter value. JSO allows you to
* pass special form of overlay objects as functions. These overlay objects must be interfaces with exactly one
* parameter and marked with {@link JSFunctor} annotation. Example:</p>
*
* <pre>
* {@literal @}JSFunctor
* interface TimerHandler extends JSObject {
* void onTimer();
* }
*
* {@literal @}JSBody(params = { "handler", "delay" }, script = "return window.setTimeout(handler, delay);")
* public static native int setTimeout(TimerHandler handler, int delay);
* </pre>
*
*
* <h2>Calling Java methods from JSBody</h2>
*
* <p>You can call Java methods from JSBody script. You should use the following notation:
*
* <pre>javaMethods.get('<i>method reference</i>').invoke([instance, ] param1 [, param2 ...]);</pre>
*
* <p>The method reference has the following format:</p>
*
* <pre>
* (<i>PackageName</i> <b>.</b>)* <i>ClassName</i> <b>.</b> <i>MethodName</i> <i>MethodDescriptor</i>
* </pre>
*
* <p>where</p>
*
* <pre>
* <i>PackageName</i> = <i>Identifier</i>
* <i>ClassName</i> = <i>Identifier</i>
* <i>MethodName</i> = <i>Identifier</i>
* <i>MethodDescriptor</i> = <b>(</b> <i>TypeDescriptor</i> <b>)</b> <b>V</b>)
* | <b>(</b> <i>TypeDescriptor</i> <b>)</b> <i>TypeDescriptor</i>
* <i>TypeDescriptor</i> = <b>Z</b> | <b>B</b> | <b>C</b> | <b>S</b> | <b>I</b> | <b>J</b> | <b>F</b> | <b>D</b>
* | <b>L</b> <i>QualifiedClassName</i> <b>;</b> | <b>[</b> <i>TypeDescriptor</i>.
* </pre>
*
* <p>that is similar to <a href="https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
* descriptors</a> augmented with class and method names.</p>
*
* <p>For example,</p>
*
* <pre>
* {@literal @}JSBody(params = { "message" }, script = "javaMethods.get('org.teavm.jso.browser.Window"
* + ".alert(Ljava/lang/String;)V').invoke(message);")
* public static native void alertCaller(String message);
* </pre>
*
* <p>Note that <code>get</code> method must take string constant. Dynamic resolution of Java methods may
* not work on some platforms.</p>
*
* @see JSObject
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ -38,7 +130,7 @@ public @interface JSBody {
String[] params(); String[] params();
/** /**
* <p>JavaScript implementation.</p> * <p>JavaScript code.</p>
*/ */
String script(); String script();
} }

View File

@ -26,16 +26,16 @@ import java.lang.annotation.Target;
* <p>Getter indexer is a method that returns value and takes exactly one parameter. In * <p>Getter indexer is a method that returns value and takes exactly one parameter. In
* this case annotation is equivalent to this:</p> * this case annotation is equivalent to this:</p>
* *
* <pre>{@code * <pre>
* @JSBody(params = "index", script = "return this[index];") * {@literal @}JSBody(params = "index", script = "return this[index];")
* }</pre> * </pre>
* *
* <p>Setter indexer is a method that takes two parameter and does not return any value. * <p>Setter indexer is a method that takes two parameter and does not return any value.
* Ins this case annotation is equivalent to the following:</p> * Ins this case annotation is equivalent to the following:</p>
* *
* <pre>{@code * <pre>
* @JSBody(params = { "index", "value" }, script = "this[index] = value;") * {@literal @}JSBody(params = { "index", "value" }, script = "this[index] = value;")
* }</pre> * </pre>
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */

View File

@ -23,13 +23,16 @@ import java.lang.annotation.Target;
/** /**
* <p>Marks abstract member method as a JavaScript method. This is equivalent to the following:</p> * <p>Marks abstract member method as a JavaScript method. This is equivalent to the following:</p>
* *
* <pre>{@code * <pre>
* @JSBody(params = ..., script = "return new this.methodName(...);") * {@literal @}JSBody(params = ..., script = "return new this.methodName(...);")
* }</pre> * </pre>
* *
* <p>where <code>methodName</code> is method's name by default or a name, directly specified by * <p>where <code>methodName</code> is method's name by default or a name, directly specified by
* this annotation.</p> * this annotation.</p>
* *
* <p>JSMethod can be avoided. This means that if you define abstract method on overlay class or interface,
* and don't specify any annotations, this method is treated as marked by JSMethod.</p>
*
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -16,7 +16,46 @@
package org.teavm.jso; package org.teavm.jso;
/** /**
* <p>The base type for all overlay types. Overlay types are Java types that represent JavaScript object,
* and therefore can be passed to and from JavaScript code.</p>
* *
* <p>An overlay type is an abstract class or an interface that extends/implements JSObject. An overlay type
* has following restrictions:</p>
*
* <ul>
* <li>it must not contain any member fields, however static fields are allowed;</li>
* <li>its non-abstract methods must not override methods of a parent type.</li>
* </ul>
*
* <p>To simplify creation of overlay objects, you can use shortcut annotations instead of {@link JSBody}:
* {@link JSMethod}, {@link JSProperty} and {@link JSIndexer}.</p>
*
* <p>Example:</p>
*
* <pre>
* public abstract class Int32Array implements JSObject {
* {@literal @}JSBody(params = {}, script = "return this.length;")
* public native int getLength();
*
* {@literal @}JSIndexer
* public abstract int get(int index);
*
* {@literal @}JSIndexer
* public abstract void set(int index, int value);
*
* {@literal @}JSBody(params = "length", script = "return new Int32Array(length);")
* public static native ArrayBuffer create(int length);
*
* {@literal @}JSBody(params = "buffer", script = "return new Int32Array(buffer);")
* public static native ArrayBuffer create(ArrayBuffer buffer);
*
* {@literal @}JSBody(params = { "buffer", "offset", "length" },
* script = "return new Int32Array(buffer, offset, length);")
* public static native ArrayBuffer create(ArrayBuffer buffer, int offset, int length);
* }
* </pre>
*
* @see JSBody
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public interface JSObject { public interface JSObject {

View File

@ -27,17 +27,17 @@ import java.lang.annotation.Target;
* (or <code>is</code> in case of boolean getter). It must not take any parameters and must return a value. * (or <code>is</code> in case of boolean getter). It must not take any parameters and must return a value.
* For getter annotation is equivalent to the following:</p> * For getter annotation is equivalent to the following:</p>
* *
* <pre>{@code * <pre>
* @JSBody(params = {}, script = "return this.propertyName;") * {@literal @}JSBody(params = {}, script = "return this.propertyName;")
* }</pre> * </pre>
* *
* <p>Setter's name must conform the Java Beans specification, i.e. start with <code>set</code> prefix * <p>Setter's name must conform the Java Beans specification, i.e. start with <code>set</code> prefix
* It must take exactly one parameter and must not return a value. * It must take exactly one parameter and must not return a value.
* For setter annotation is equivalent to the following:</p> * For setter annotation is equivalent to the following:</p>
* *
* <pre>{@code * <pre>
* @JSBody(params = "value", script = "this.propertyName = value;") * {@literal @}JSBody(params = "value", script = "this.propertyName = value;")
* }</pre> * </pre>
* *
* <p>By default <code>propertyName</code> is calculated from method's name according to Java Beans specification, * <p>By default <code>propertyName</code> is calculated from method's name according to Java Beans specification,
* otherwise the name specified by annotation is taken.</p> * otherwise the name specified by annotation is taken.</p>

View File

@ -37,4 +37,8 @@ public interface Screen extends JSObject {
@JSProperty @JSProperty
int getColorDepth(); int getColorDepth();
static Screen current() {
return Window.current().getScreen();
}
} }

View File

@ -35,4 +35,12 @@ public abstract class Storage implements JSObject {
public abstract void removeItem(String key); public abstract void removeItem(String key);
public abstract void clear(); public abstract void clear();
public static Storage getSessionStorage() {
return Window.current().getSessionStorage();
}
public static Storage getLocalStorage() {
return Window.current().getLocalStorage();
}
} }

View File

@ -16,6 +16,7 @@
package org.teavm.jso.dom.html; package org.teavm.jso.dom.html;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
import org.teavm.jso.browser.Window;
import org.teavm.jso.dom.events.EventTarget; import org.teavm.jso.dom.events.EventTarget;
import org.teavm.jso.dom.xml.Document; import org.teavm.jso.dom.xml.Document;
@ -45,4 +46,8 @@ public interface HTMLDocument extends Document, EventTarget {
@JSProperty @JSProperty
int getScrollTop(); int getScrollTop();
static HTMLDocument current() {
return Window.current().getDocument();
}
} }

View File

@ -0,0 +1,62 @@
/*
* Copyright 2015 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* <p>JSO is a specification that describes how Java platform can interact with JavaScript code.
* There are two parts of this specification: JSO core, that defines mapping between Java and JavaScript
* objects and JSO APIs, that define Java wrappers around various JavaScript and HTML5 APIs.
* The latter part is simply application of the former one. JSO implementor must implement only the first part,
* and it may ignore the second part, since it should work properly this way. However, it may implement
* some of the APIs itself in some cases, for example to improve performance.</p>
*
* <p>The first part of JSO is directly in this package. All subpackages declare the second part of JSO.</p>
*
* <p>JSO does not do anything itself. It is only a set of interfaces that define interaction.
* To use JSO in your application, you should include one of its implementations, that may exist for
* different platforms, such as JVM, RoboVM, Android, TeaVM or bck2brwsr.</p>
*
*
* <h2>JSBody annotation</h2>
*
* <p>The easiest way to invoke JavaScript code from Java is to define native method marked with the
* {@link org.teavm.jso.JSBody} annotation that contains the JavaScript code.</p>
*
* <p>Example:</p>
*
* <pre>
* {@literal @}JSBody(params = { "message" }, script = "window.alert(message);")
* public static native void alert(String message);
* </pre>
*
*
* <h2>Overlay types</h2>
*
* <p>Often you need to pass complex values between Java and JavaScript. Primitives are usually insufficient for
* this purposed. JSO comes with concept of overlay types, that are usable from both Java and JavaScript.
* For detailed description, see {@link org.teavm.jso.JSObject} interface.</p>
*
* <p>When wrapping JavaScript APIs in Java classes, you usually write boilerplate {@link org.teavm.jso.JSBody} like
* this:</p>
*
* <pre>
* {@literal @}JSBody(params = "newChild", script = "return this.appendChild(newChild);")
* Node appendChild(Node newChild);
* </pre>
*
* <p>JSO offers shortcut annotations that help to avoid such boilerplate. They are: {@link org.teavm.jso.JSMethod},
* {@link org.teavm.jso.JSProperty}, {@link org.teavm.jso.JSIndexer}.
*
*/
package org.teavm.jso;