diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JS.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JS.java index bb3244524..ea8c3afdf 100644 --- a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JS.java +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JS.java @@ -390,48 +390,6 @@ final class JS { JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, 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) @JSBody(params = { "instance", "index" }, script = "return instance[index];") public static native JSObject get(JSObject instance, JSObject index); diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java index a4a758aa5..f2e062eb4 100644 --- a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java @@ -27,7 +27,6 @@ import org.teavm.diagnostics.Diagnostics; import org.teavm.javascript.spi.GeneratedBy; import org.teavm.javascript.spi.Sync; import org.teavm.jso.JSBody; -import org.teavm.jso.JSConstructor; import org.teavm.jso.JSFunctor; import org.teavm.jso.JSIndexer; import org.teavm.jso.JSMethod; @@ -371,40 +370,20 @@ class JavascriptNativeProcessor { } } else { String name = method.getName(); - AnnotationReader constructorAnnot = method.getAnnotations().get(JSConstructor.class.getName()); - boolean isConstructor = false; - if (constructorAnnot != null) { - if (!isSupportedType(method.getResultType())) { - diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript " - + "constructor declaration", invoke.getMethod()); - 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; + + 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; + } + for (ValueType arg : method.getParameterTypes()) { if (!isSupportedType(arg)) { diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " @@ -416,8 +395,7 @@ class JavascriptNativeProcessor { InvokeInstruction newInvoke = new InvokeInstruction(); ValueType[] signature = new ValueType[method.parameterCount() + 3]; Arrays.fill(signature, ValueType.object(JSObject.class.getName())); - newInvoke.setMethod(new MethodReference(JS.class.getName(), - isConstructor ? "instantiate" : "invoke", signature)); + newInvoke.setMethod(new MethodReference(JS.class.getName(), "invoke", signature)); newInvoke.setType(InvocationType.SPECIAL); newInvoke.setReceiver(result); newInvoke.getArguments().add(invoke.getInstance()); @@ -793,7 +771,7 @@ class JavascriptNativeProcessor { } else if (itemType.isObject(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) { diff --git a/teavm-jso/src/main/java/org/teavm/jso/JSConstructor.java b/teavm-jso/src/main/java/org/teavm/jso/JSConstructor.java deleted file mode 100644 index 76b25140c..000000000 --- a/teavm-jso/src/main/java/org/teavm/jso/JSConstructor.java +++ /dev/null @@ -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; - -/** - *

Marks abstract member method as a JavaScript constructor. This is equivalent to the following:

- * - *
{@code
- * @JSBody(params = ..., script = "return new this.constructorName(...);")
- * }
- * - *

where constructorName is method's name by default or a name, directly specified by - * this annotation.

- * - * @author Alexey Andreev - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface JSConstructor { - String value() default ""; -} diff --git a/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributes.java b/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributes.java index 8ed6cac0f..f64748a7f 100644 --- a/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributes.java +++ b/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributes.java @@ -15,6 +15,7 @@ */ package org.teavm.jso.webgl; +import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; @@ -22,40 +23,43 @@ import org.teavm.jso.JSProperty; * * @author Alexey Andreev */ -public interface WebGLContextAttributes extends JSObject { +public abstract class WebGLContextAttributes implements JSObject { @JSProperty - boolean isAlpha(); + public abstract boolean isAlpha(); @JSProperty - void setAlpha(boolean alpha); + public abstract void setAlpha(boolean alpha); @JSProperty - boolean isDepth(); + public abstract boolean isDepth(); @JSProperty - void setDepth(boolean depth); + public abstract void setDepth(boolean depth); @JSProperty - boolean isScencil(); + public abstract boolean isScencil(); @JSProperty - void setStencil(boolean stencil); + public abstract void setStencil(boolean stencil); @JSProperty - boolean isAntialias(); + public abstract boolean isAntialias(); @JSProperty - void setAntialias(boolean antialias); + public abstract void setAntialias(boolean antialias); @JSProperty - boolean isPremultipliedAlpha(); + public abstract boolean isPremultipliedAlpha(); @JSProperty - void setPremultipliedAlpha(boolean premultipliedAlpha); + public abstract void setPremultipliedAlpha(boolean premultipliedAlpha); @JSProperty - boolean isPreserveDrawingBuffer(); + public abstract boolean isPreserveDrawingBuffer(); @JSProperty - void setPreserveDrawingBuffer(boolean preserveDrawingBuffer); + public abstract void setPreserveDrawingBuffer(boolean preserveDrawingBuffer); + + @JSBody(params = {}, script = "return {};") + public static native WebGLContextAttributes create(); } diff --git a/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributesFactory.java b/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributesFactory.java deleted file mode 100644 index 6ab7ba60c..000000000 --- a/teavm-jso/src/main/java/org/teavm/jso/webgl/WebGLContextAttributesFactory.java +++ /dev/null @@ -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(); -} diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/AnnotationsTest.java b/teavm-jso/src/test/java/org/teavm/jso/test/AnnotationsTest.java new file mode 100644 index 000000000..b8b435e9d --- /dev/null +++ b/teavm-jso/src/test/java/org/teavm/jso/test/AnnotationsTest.java @@ -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); +} diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java b/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java index afa36d3e2..1e67e2cae 100644 --- a/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java +++ b/teavm-jso/src/test/java/org/teavm/jso/test/ConversionTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; 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]); } + @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 = "" + "return '' + a + ':' + b + ':' + c + ':' + d + ':' + e + ':' + f.toFixed(1) + ':'" + "+ g.toFixed(1) + ':' + h;") @@ -263,4 +284,19 @@ public class ConversionTest { @JSProperty 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); } diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/JSBodyTest.java b/teavm-jso/src/test/java/org/teavm/jso/test/JSBodyTest.java deleted file mode 100644 index 34d7f393f..000000000 --- a/teavm-jso/src/test/java/org/teavm/jso/test/JSBodyTest.java +++ /dev/null @@ -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); - } -} diff --git a/teavm-platform/src/main/java/org/teavm/platform/Platform.java b/teavm-platform/src/main/java/org/teavm/platform/Platform.java index 9f68a024e..abf5483b6 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/Platform.java +++ b/teavm-platform/src/main/java/org/teavm/platform/Platform.java @@ -134,9 +134,8 @@ public final class Platform { ((PlatformHelper) Window.current()).killSchedule(id); } - public static PlatformQueue createQueue() { - return ((PlatformHelper) Window.current()).newQueue(); - } + @JSBody(params = {}, script = "return [];") + public static native PlatformQueue createQueue(); public static PlatformString stringFromCharCode(int charCode) { return ((PlatformHelper) Window.current()).getStringClass().fromCharCode(charCode); diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java index 817cc08e3..dfe2b4c9c 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java @@ -15,7 +15,6 @@ */ package org.teavm.platform; -import org.teavm.jso.JSConstructor; import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; @@ -31,9 +30,6 @@ interface PlatformHelper extends JSObject { @JSProperty("String") PlatformStringClass getStringClass(); - @JSConstructor("Array") - PlatformQueue newQueue(); - @JSMethod("clearTimeout") void killSchedule(int scheduleId); }