mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds type conversion from Java array and integer to JS array and number
This commit is contained in:
parent
f8ea743c26
commit
ae2ca37ee0
|
@ -25,7 +25,6 @@ import org.teavm.model.MethodReference;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class StringNativeGenerator implements Injector {
|
||||
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
|
|
|
@ -123,7 +123,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
|||
if (integerCache == null) {
|
||||
integerCache = new TInteger[256];
|
||||
for (int j = 0; j < integerCache.length; ++j) {
|
||||
integerCache[j - 128] = new TInteger(j);
|
||||
integerCache[j] = new TInteger(j - 128);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,9 +57,10 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
|
||||
@Override
|
||||
public String getNameFor(MethodReference method) {
|
||||
MethodReference origMethod = method;
|
||||
method = getRealMethod(method);
|
||||
if (method == null) {
|
||||
throw new NamingException("Can't provide name for method as it was not found: " + method);
|
||||
throw new NamingException("Can't provide name for method as it was not found: " + origMethod);
|
||||
}
|
||||
ClassHolder clsHolder = classSource.get(method.getClassName());
|
||||
MethodHolder methodHolder = clsHolder.getMethod(method.getDescriptor());
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.html4j;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public final class JavaScriptBodyConverter {
|
||||
private JavaScriptBodyConverter() {
|
||||
}
|
||||
|
||||
@GeneratedBy(JavaScriptBodyConverterGenerator.class)
|
||||
@PluggableDependency(JavaScriptBodyConverterGenerator.class)
|
||||
public static native Object toJavaScript(Object obj);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.html4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyConsumer;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodGraph;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class JavaScriptBodyConverterGenerator implements Generator, DependencyPlugin {
|
||||
private static final MethodReference intValueMethod = new MethodReference("java.lang.Integer",
|
||||
new MethodDescriptor("intValue", ValueType.INTEGER));
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker checker, MethodReference method) {
|
||||
switch (method.getName()) {
|
||||
case "toJavaScript":
|
||||
achieveToJavaScript(checker, method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void achieveToJavaScript(final DependencyChecker checker, MethodReference method) {
|
||||
MethodGraph graph = checker.attachMethodGraph(method);
|
||||
graph.getVariable(1).addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(String type) {
|
||||
if (type.equals("java.lang.Integer")) {
|
||||
checker.attachMethodGraph(intValueMethod);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "toJavaScript":
|
||||
generateToJavaScript(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateToJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
ClassReaderSource classSource = context.getClassSource();
|
||||
String obj = context.getParameterName(1);
|
||||
writer.append("if").ws().append("(").append(obj).ws().append("===").ws().append("null)").ws().append("{")
|
||||
.softNewLine().indent();
|
||||
writer.append("return null;").softNewLine();
|
||||
writer.outdent().append("}").ws().append("else if").ws().append('(').append(obj)
|
||||
.append(".constructor.$meta.item)").ws().append("{").indent().softNewLine();
|
||||
writer.append("return ").append(obj).append(".data;").softNewLine();
|
||||
writer.outdent().append("}");
|
||||
if (classSource.get("java.lang.String") != null) {
|
||||
writer.ws().append("else if").ws().append("(").append(obj).append(".constructor").ws().append("===").ws()
|
||||
.appendClass("java.lang.String").append(")").ws().append("{").indent().softNewLine();
|
||||
generateStringToJavaScript(context, writer);
|
||||
writer.outdent().append("}");
|
||||
}
|
||||
if (classSource.get("java.lang.Integer") != null) {
|
||||
writer.ws().append("else if").ws().append("(").append(obj).append(".constructor").ws().append("===").ws()
|
||||
.appendClass("java.lang.Integer").append(")").ws().append("{").indent().softNewLine();
|
||||
writer.append("return ").appendMethodBody(intValueMethod).append("(").append(obj)
|
||||
.append(");").softNewLine();
|
||||
writer.outdent().append("}");
|
||||
}
|
||||
writer.ws().append("else").ws().append("{").indent().softNewLine();
|
||||
writer.append("return ").append(obj).append(";").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
private void generateStringToJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
FieldReference charsField = new FieldReference("java.lang.String", "characters");
|
||||
writer.append("var result = \"\";").softNewLine();
|
||||
writer.append("var data = ").append(context.getParameterName(1)).append('.')
|
||||
.appendField(charsField).append(".data;").softNewLine();
|
||||
writer.append("for (var i = 0; i < data.length; i = (i + 1) | 0) {").indent().softNewLine();
|
||||
writer.append("result += String.fromCharCode(data[i]);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return result;").softNewLine();
|
||||
}
|
||||
}
|
|
@ -73,6 +73,16 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
String body = annot.getValue("body").getString();
|
||||
new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body);
|
||||
}
|
||||
for (int i = 0; i < methodRef.parameterCount(); ++i) {
|
||||
ValueType type = methodRef.getDescriptor().parameterType(i);
|
||||
if (type.isObject("java.lang.Object")) {
|
||||
MethodGraph convGraph = dependencyChecker.attachMethodGraph(new MethodReference(
|
||||
JavaScriptBodyConverter.class.getName(),
|
||||
new MethodDescriptor("toJavaScript", ValueType.object("java.lang.Object"),
|
||||
ValueType.object("java.lang.Object"))));
|
||||
graph.getVariable(i + 1).connect(convGraph.getVariable(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,22 @@ public class JavaScriptBodyGenerator implements Generator {
|
|||
writer.outdent().append("}).call(").append(context.getParameterName(0));
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
writer.append(",").ws();
|
||||
writer.append(context.getParameterName(i + 1));
|
||||
wrapParameter(writer, methodRef.getDescriptor().parameterType(i), context.getParameterName(i + 1));
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
}
|
||||
|
||||
private void wrapParameter(SourceWriter writer, ValueType type, String param) throws IOException {
|
||||
if (type.isObject("java.lang.Object")) {
|
||||
writer.appendMethodBody(new MethodReference(JavaScriptBodyConverter.class.getName(),
|
||||
new MethodDescriptor("toJavaScript", ValueType.object("java.lang.Object"),
|
||||
ValueType.object("java.lang.Object"))));
|
||||
writer.append("(").append(param).append(")");
|
||||
} else {
|
||||
writer.append(param);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GeneratorJsCallback extends JsCallback {
|
||||
private ClassReaderSource classSource;
|
||||
private NamingStrategy naming;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.html4j.test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import net.java.html.js.JavaScriptBody;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class JavaScriptBodyConversionTests {
|
||||
@Test
|
||||
public void convertsInteger() {
|
||||
assertEquals(23, returnAsInt(23));
|
||||
}
|
||||
|
||||
@JavaScriptBody(args = { "value" }, body = "return value;")
|
||||
private native int returnAsInt(Object value);
|
||||
}
|
|
@ -64,6 +64,11 @@ public class JavaScriptBodyTests {
|
|||
assertEquals(23, invokeCallback(a));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void staticCallbackInvoked() {
|
||||
assertEquals(23, invokeStaticCallback(new AImpl()));
|
||||
}
|
||||
|
||||
private static class AImpl implements A {
|
||||
@Override public int foo() {
|
||||
return 23;
|
||||
|
@ -90,4 +95,13 @@ public class JavaScriptBodyTests {
|
|||
"@org.teavm.html4j.test.B::bar(" +
|
||||
"Lorg/teavm/html4j/test/A;)(_global_)", javacall = true)
|
||||
private native int invokeCallback(B callback);
|
||||
|
||||
public static int staticCallback(A a) {
|
||||
return a.foo();
|
||||
}
|
||||
|
||||
@JavaScriptBody(args = { "a" }, body = "return " +
|
||||
"@org.teavm.html4j.test.JavaScriptBodyTests::staticCallback(" +
|
||||
"Lorg/teavm/html4j/test/A;)(a)", javacall = true)
|
||||
private native int invokeStaticCallback(A a);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user