Remove JSConstructor. Further development of JSO TCK

This commit is contained in:
Alexey Andreev 2015-09-12 13:47:58 +03:00
parent 0b66d4c799
commit 5fca860b70
10 changed files with 182 additions and 216 deletions

View File

@ -390,48 +390,6 @@ final class JS {
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k,
JSObject l, JSObject m); JSObject l, JSObject m);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f, JSObject g);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
@InjectedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
@JSBody(params = { "instance", "index" }, script = "return instance[index];") @JSBody(params = { "instance", "index" }, script = "return instance[index];")
public static native JSObject get(JSObject instance, JSObject index); public static native JSObject get(JSObject instance, JSObject index);

View File

@ -27,7 +27,6 @@ import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.spi.GeneratedBy; import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.javascript.spi.Sync; import org.teavm.javascript.spi.Sync;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSConstructor;
import org.teavm.jso.JSFunctor; import org.teavm.jso.JSFunctor;
import org.teavm.jso.JSIndexer; import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSMethod; import org.teavm.jso.JSMethod;
@ -371,40 +370,20 @@ class JavascriptNativeProcessor {
} }
} else { } else {
String name = method.getName(); String name = method.getName();
AnnotationReader constructorAnnot = method.getAnnotations().get(JSConstructor.class.getName());
boolean isConstructor = false; AnnotationReader methodAnnot = method.getAnnotations().get(JSMethod.class.getName());
if (constructorAnnot != null) { if (methodAnnot != null) {
if (!isSupportedType(method.getResultType())) { AnnotationValue redefinedMethodName = methodAnnot.getValue("value");
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript " if (redefinedMethodName != null) {
+ "constructor declaration", invoke.getMethod()); name = redefinedMethodName.getString();
continue;
}
AnnotationValue nameVal = constructorAnnot.getValue("value");
name = nameVal != null ? constructorAnnot.getValue("value").getString() : "";
if (name.isEmpty()) {
if (!method.getName().startsWith("new") || method.getName().length() == 3) {
diagnostics.error(callLocation, "Method {{m0}} is not declared as a native "
+ "JavaScript constructor, but its name does not satisfy conventions",
invoke.getMethod());
continue;
}
name = method.getName().substring(3);
}
isConstructor = true;
} else {
AnnotationReader methodAnnot = method.getAnnotations().get(JSMethod.class.getName());
if (methodAnnot != null) {
AnnotationValue redefinedMethodName = methodAnnot.getValue("value");
if (redefinedMethodName != null) {
name = redefinedMethodName.getString();
}
}
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "declaration", invoke.getMethod());
continue;
} }
} }
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "declaration", invoke.getMethod());
continue;
}
for (ValueType arg : method.getParameterTypes()) { for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) { if (!isSupportedType(arg)) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
@ -416,8 +395,7 @@ class JavascriptNativeProcessor {
InvokeInstruction newInvoke = new InvokeInstruction(); InvokeInstruction newInvoke = new InvokeInstruction();
ValueType[] signature = new ValueType[method.parameterCount() + 3]; ValueType[] signature = new ValueType[method.parameterCount() + 3];
Arrays.fill(signature, ValueType.object(JSObject.class.getName())); Arrays.fill(signature, ValueType.object(JSObject.class.getName()));
newInvoke.setMethod(new MethodReference(JS.class.getName(), newInvoke.setMethod(new MethodReference(JS.class.getName(), "invoke", signature));
isConstructor ? "instantiate" : "invoke", signature));
newInvoke.setType(InvocationType.SPECIAL); newInvoke.setType(InvocationType.SPECIAL);
newInvoke.setReceiver(result); newInvoke.setReceiver(result);
newInvoke.getArguments().add(invoke.getInstance()); newInvoke.getArguments().add(invoke.getInstance());
@ -793,7 +771,7 @@ class JavascriptNativeProcessor {
} else if (itemType.isObject(String.class)) { } else if (itemType.isObject(String.class)) {
return new MethodReference(JS.class, "unwrapStringArray", JSArrayReader.class, String[].class); return new MethodReference(JS.class, "unwrapStringArray", JSArrayReader.class, String[].class);
} }
return new MethodReference(JS.class, "unwrapArray", Class.class, JSArrayReader.class, byte[].class); return new MethodReference(JS.class, "unwrapArray", Class.class, JSArrayReader.class, JSObject[].class);
} }
private MethodReference multipleDimensionArrayUnwrapper(ValueType itemType) { private MethodReference multipleDimensionArrayUnwrapper(ValueType itemType) {

View File

@ -1,39 +0,0 @@
/*
* Copyright 2014 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.
*/
package org.teavm.jso;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>Marks abstract member method as a JavaScript constructor. This is equivalent to the following:</p>
*
* <pre>{@code
* @JSBody(params = ..., script = "return new this.constructorName(...);")
* }</pre>
*
* <p>where <code>constructorName</code> is method's name by default or a name, directly specified by
* this annotation.</p>
*
* @author Alexey Andreev
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JSConstructor {
String value() default "";
}

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.jso.webgl; package org.teavm.jso.webgl;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
@ -22,40 +23,43 @@ import org.teavm.jso.JSProperty;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public interface WebGLContextAttributes extends JSObject { public abstract class WebGLContextAttributes implements JSObject {
@JSProperty @JSProperty
boolean isAlpha(); public abstract boolean isAlpha();
@JSProperty @JSProperty
void setAlpha(boolean alpha); public abstract void setAlpha(boolean alpha);
@JSProperty @JSProperty
boolean isDepth(); public abstract boolean isDepth();
@JSProperty @JSProperty
void setDepth(boolean depth); public abstract void setDepth(boolean depth);
@JSProperty @JSProperty
boolean isScencil(); public abstract boolean isScencil();
@JSProperty @JSProperty
void setStencil(boolean stencil); public abstract void setStencil(boolean stencil);
@JSProperty @JSProperty
boolean isAntialias(); public abstract boolean isAntialias();
@JSProperty @JSProperty
void setAntialias(boolean antialias); public abstract void setAntialias(boolean antialias);
@JSProperty @JSProperty
boolean isPremultipliedAlpha(); public abstract boolean isPremultipliedAlpha();
@JSProperty @JSProperty
void setPremultipliedAlpha(boolean premultipliedAlpha); public abstract void setPremultipliedAlpha(boolean premultipliedAlpha);
@JSProperty @JSProperty
boolean isPreserveDrawingBuffer(); public abstract boolean isPreserveDrawingBuffer();
@JSProperty @JSProperty
void setPreserveDrawingBuffer(boolean preserveDrawingBuffer); public abstract void setPreserveDrawingBuffer(boolean preserveDrawingBuffer);
@JSBody(params = {}, script = "return {};")
public static native WebGLContextAttributes create();
} }

View File

@ -1,28 +0,0 @@
/*
* 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.
*/
package org.teavm.jso.webgl;
import org.teavm.jso.JSConstructor;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
*/
public interface WebGLContextAttributesFactory extends JSObject {
@JSConstructor("Object")
WebGLContextAttributes createWebGLContextAttributes();
}

View File

@ -0,0 +1,113 @@
/*
* 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.
*/
package org.teavm.jso.test;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSMethod;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev
*/
public class AnnotationsTest {
@Test
public void staticBodyWorks() {
assertEquals(12, add(5, 7));
}
@Test
public void memberBodyWorks() {
assertEquals(12, convert(convert(5).add(convert(7))));
}
@Test
public void abstractWrapperWorks() {
AbstractWrapper obj = AbstractWrapper.create(5);
assertEquals(5, obj.getValue());
assertEquals(12, obj.testMethod(6));
assertEquals(13, obj.renamedMethod(6));
assertEquals(25, obj.javaMethod(6));
}
@Test
public void interfaceWrapperWorks() {
InterfaceWrapper obj = createWrapper(5);
assertEquals(5, obj.getValue());
assertEquals(12, obj.testMethod(6));
assertEquals(13, obj.renamedMethod(6));
}
@JSBody(params = { "a", "b" }, script = "return a + b;")
private static native int add(int a, int b);
@JSBody(params = "n", script = "return n;")
private static native Num convert(int n);
@JSBody(params = "n", script = "return n;")
private static native int convert(Num n);
static abstract class Num implements JSObject {
@JSBody(params = "other", script = "return this + other;")
public final native Num add(Num other);
}
static abstract class AbstractWrapper implements JSObject {
private AbstractWrapper() {
}
@JSProperty
public abstract int getValue();
public abstract int testMethod(int num);
@JSMethod("renamedJSMethod")
public abstract int renamedMethod(int num);
public final int javaMethod(int num) {
return testMethod(num) + renamedMethod(num);
}
@JSBody(params = "value", script = ""
+ "return {"
+ "value : value, "
+ "testMethod : function(num) { return this.value + num + 1; }, "
+ "renamedJSMethod : function(num) { return this.value + num + 2; }"
+ "};")
public static native AbstractWrapper create(int value);
}
interface InterfaceWrapper extends JSObject {
@JSProperty
int getValue();
int testMethod(int num);
@JSMethod("renamedJSMethod")
int renamedMethod(int num);
}
@JSBody(params = "value", script = ""
+ "return {"
+ "value : value, "
+ "testMethod : function(num) { return this.value + num + 1; }, "
+ "renamedJSMethod : function(num) { return this.value + num + 2; }"
+ "};")
public static native InterfaceWrapper createWrapper(int value);
}

View File

@ -20,6 +20,7 @@ import org.junit.Test;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
import org.teavm.jso.core.JSString;
/** /**
* *
@ -120,6 +121,26 @@ public class ConversionTest {
assertArrayEquals(new String[] { "foo" }, arrays.getH()[0][0][0]); assertArrayEquals(new String[] { "foo" }, arrays.getH()[0][0][0]);
} }
@Test
public void passesJSObject() {
assertEquals("(foo)", surround(JSString.valueOf("foo")).stringValue());
}
@Test
public void convertsArrayOfJSObject() {
assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue());
assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());
assertEquals("(foo)", surround(new JSString[][][][] {{{{ JSString.valueOf("foo") }}}})[0][0][0][0]
.stringValue());
}
@Test
public void copiesArray() {
int[] array = { 23 };
assertEquals(24, mutate(array));
assertEquals(23, array[0]);
}
@JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = "" @JSBody(params = { "a", "b", "c", "d", "e", "f", "g", "h" }, script = ""
+ "return '' + a + ':' + b + ':' + c + ':' + d + ':' + e + ':' + f.toFixed(1) + ':'" + "return '' + a + ':' + b + ':' + c + ':' + d + ':' + e + ':' + f.toFixed(1) + ':'"
+ "+ g.toFixed(1) + ':' + h;") + "+ g.toFixed(1) + ':' + h;")
@ -263,4 +284,19 @@ public class ConversionTest {
@JSProperty @JSProperty
String[][][][] getH(); String[][][][] getH();
} }
@JSBody(params = "str", script = "return '(' + str + ')';")
private static native JSString surround(JSString str);
@JSBody(params = "str", script = "return ['(' + str[0] + ')'];")
private static native JSString[] surround(JSString[] str);
@JSBody(params = "str", script = "return [['(' + str[0][0] + ')']];")
private static native JSString[][] surround(JSString[][] str);
@JSBody(params = "str", script = "return [[[['(' + str[0][0][0][0] + ')']]]];")
private static native JSString[][][][] surround(JSString[][][][] str);
@JSBody(params = "array", script = "array[0]++; return array[0];")
private static native int mutate(int[] array);
} }

View File

@ -1,51 +0,0 @@
/*
* 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.
*/
package org.teavm.jso.test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
*/
public class JSBodyTest {
@Test
public void staticWorks() {
assertEquals(12, add(5, 7));
}
@Test
public void memberWorks() {
assertEquals(12, convert(convert(5).add(convert(7))));
}
@JSBody(params = { "a", "b" }, script = "return a + b;")
private static native int add(int a, int b);
@JSBody(params = "n", script = "return n;")
private static native Num convert(int n);
@JSBody(params = "n", script = "return n;")
private static native int convert(Num n);
static abstract class Num implements JSObject {
@JSBody(params = "other", script = "return this + other;")
public final native Num add(Num other);
}
}

View File

@ -134,9 +134,8 @@ public final class Platform {
((PlatformHelper) Window.current()).killSchedule(id); ((PlatformHelper) Window.current()).killSchedule(id);
} }
public static <T> PlatformQueue<T> createQueue() { @JSBody(params = {}, script = "return [];")
return ((PlatformHelper) Window.current()).newQueue(); public static native <T> PlatformQueue<T> createQueue();
}
public static PlatformString stringFromCharCode(int charCode) { public static PlatformString stringFromCharCode(int charCode) {
return ((PlatformHelper) Window.current()).getStringClass().fromCharCode(charCode); return ((PlatformHelper) Window.current()).getStringClass().fromCharCode(charCode);

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform; package org.teavm.platform;
import org.teavm.jso.JSConstructor;
import org.teavm.jso.JSMethod; import org.teavm.jso.JSMethod;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
@ -31,9 +30,6 @@ interface PlatformHelper extends JSObject {
@JSProperty("String") @JSProperty("String")
PlatformStringClass getStringClass(); PlatformStringClass getStringClass();
@JSConstructor("Array")
<T> PlatformQueue<T> newQueue();
@JSMethod("clearTimeout") @JSMethod("clearTimeout")
void killSchedule(int scheduleId); void killSchedule(int scheduleId);
} }