mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Merge branch 'html4j-convert'
This commit is contained in:
commit
fa1f8f1c6e
|
@ -25,7 +25,6 @@ import org.teavm.model.MethodReference;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class StringNativeGenerator implements Injector {
|
public class StringNativeGenerator implements Injector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
||||||
if (integerCache == null) {
|
if (integerCache == null) {
|
||||||
integerCache = new TInteger[256];
|
integerCache = new TInteger[256];
|
||||||
for (int j = 0; j < integerCache.length; ++j) {
|
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
|
@Override
|
||||||
public String getNameFor(MethodReference method) {
|
public String getNameFor(MethodReference method) {
|
||||||
|
MethodReference origMethod = method;
|
||||||
method = getRealMethod(method);
|
method = getRealMethod(method);
|
||||||
if (method == null) {
|
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());
|
ClassHolder clsHolder = classSource.get(method.getClassName());
|
||||||
MethodHolder methodHolder = clsHolder.getMethod(method.getDescriptor());
|
MethodHolder methodHolder = clsHolder.getMethod(method.getDescriptor());
|
||||||
|
|
|
@ -43,6 +43,10 @@ $rt_createArray = function(cls, sz) {
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
$rt_wrapArray = function(cls, data) {
|
||||||
|
var arr = new ($rt_arraycls(cls))(data);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
$rt_createUnfilledArray = function(cls, sz) {
|
$rt_createUnfilledArray = function(cls, sz) {
|
||||||
return new ($rt_arraycls(cls))(new Array(sz));
|
return new ($rt_arraycls(cls))(new Array(sz));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.javascript.ni.GeneratedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public final class JavaScriptBodyConverter {
|
||||||
|
private JavaScriptBodyConverter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@GeneratedBy(JavaScriptBodyConverterGenerator.class)
|
||||||
|
public static native Object toJavaScript(Object obj);
|
||||||
|
|
||||||
|
@GeneratedBy(JavaScriptBodyConverterGenerator.class)
|
||||||
|
public static native Object fromJavaScript(Object obj);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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.javascript.ni.Generator;
|
||||||
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class JavaScriptBodyConverterGenerator implements Generator {
|
||||||
|
private static final String convCls = JavaScriptBodyConverter.class.getName();
|
||||||
|
static final MethodReference intValueMethod = new MethodReference("java.lang.Integer",
|
||||||
|
new MethodDescriptor("intValue", ValueType.INTEGER));
|
||||||
|
private static final ValueType objType = ValueType.object("java.lang.Object");
|
||||||
|
static final MethodReference toJsMethod = new MethodReference(convCls, new MethodDescriptor(
|
||||||
|
"toJavaScript", objType, objType));
|
||||||
|
static final MethodReference fromJsMethod = new MethodReference(convCls, new MethodDescriptor(
|
||||||
|
"fromJavaScript", objType, objType));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
|
switch (methodRef.getName()) {
|
||||||
|
case "toJavaScript":
|
||||||
|
generateToJavaScript(context, writer);
|
||||||
|
break;
|
||||||
|
case "fromJavaScript":
|
||||||
|
generateFromJavaScript(context, writer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateToJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
|
String obj = context.getParameterName(1);
|
||||||
|
writer.append("if (" + obj + " === null) {").softNewLine().indent();
|
||||||
|
writer.append("return null;").softNewLine();
|
||||||
|
writer.outdent().append("} else if (" + obj + ".constructor.$meta.item) {").indent().softNewLine();
|
||||||
|
writer.append("var arr = new Array(" + obj + ".data.length);").softNewLine();
|
||||||
|
writer.append("for (var i = 0; i < arr.length; ++i) {").indent().softNewLine();
|
||||||
|
writer.append("arr[i] = ").appendMethodBody(toJsMethod).append("(" + obj + ".data[i]);").softNewLine();
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
writer.append("return arr;").softNewLine();
|
||||||
|
writer.outdent().append("}");
|
||||||
|
writer.append(" else if (" + obj + ".constructor === ").appendClass("java.lang.String")
|
||||||
|
.append(") {").indent().softNewLine();
|
||||||
|
generateStringToJavaScript(context, writer);
|
||||||
|
writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Integer")
|
||||||
|
.append(") {").indent().softNewLine();
|
||||||
|
writer.append("return ").appendMethodBody(intValueMethod).append("(" + obj + ");").softNewLine();
|
||||||
|
writer.outdent().append("}");
|
||||||
|
writer.append(" else {").indent().softNewLine();
|
||||||
|
writer.append("return " + obj + ";").softNewLine();
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateFromJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
|
String obj = context.getParameterName(1);
|
||||||
|
writer.append("if (" + obj +" === null || " + obj + " === undefined)").ws().append("{")
|
||||||
|
.softNewLine().indent();
|
||||||
|
writer.append("return null;").softNewLine();
|
||||||
|
writer.outdent().append("} else if (" + obj + " instanceof Array) {").indent().softNewLine();
|
||||||
|
writer.append("var arr = $rt_createArray($rt_objcls(), " + obj + ".length);").softNewLine();
|
||||||
|
writer.append("for (var i = 0; i < arr.data.length; ++i) {").indent().softNewLine();
|
||||||
|
writer.append("arr.data[i] = ").appendMethodBody(fromJsMethod).append("(" + obj + "[i]);")
|
||||||
|
.softNewLine();
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
writer.append("return arr;").softNewLine();
|
||||||
|
writer.outdent().append("}");
|
||||||
|
writer.append(" else if (" + obj + ".constructor === ").appendClass("java.lang.String")
|
||||||
|
.append(") {").indent().softNewLine();
|
||||||
|
writer.append("return $rt_str(" + obj + ");").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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,8 +30,6 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyChecker dependencyChecker) {
|
||||||
allClassesNode = dependencyChecker.createNode();
|
allClassesNode = dependencyChecker.createNode();
|
||||||
allClassesNode.setTag("JavaScriptBody:global");
|
allClassesNode.setTag("JavaScriptBody:global");
|
||||||
allClassesNode.getArrayItem().addConsumer(new OneDirectionalConnection(allClassesNode));
|
|
||||||
allClassesNode.getArrayItem().getArrayItem().addConsumer(new OneDirectionalConnection(allClassesNode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OneDirectionalConnection implements DependencyConsumer {
|
private static class OneDirectionalConnection implements DependencyConsumer {
|
||||||
|
@ -55,6 +53,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
||||||
AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName());
|
AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName());
|
||||||
if (annot != null) {
|
if (annot != null) {
|
||||||
|
includeDefaultDependencies(dependencyChecker);
|
||||||
AnnotationValue javacall = annot.getValue("javacall");
|
AnnotationValue javacall = annot.getValue("javacall");
|
||||||
MethodGraph graph = dependencyChecker.attachMethodGraph(methodRef);
|
MethodGraph graph = dependencyChecker.attachMethodGraph(methodRef);
|
||||||
if (graph.getResult() != null) {
|
if (graph.getResult() != null) {
|
||||||
|
@ -76,6 +75,12 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void includeDefaultDependencies(DependencyChecker dependencyChecker) {
|
||||||
|
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.fromJsMethod);
|
||||||
|
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.toJsMethod);
|
||||||
|
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.intValueMethod);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldReference field) {
|
public void fieldAchieved(DependencyChecker dependencyChecker, FieldReference field) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
GeneratorJsCallback callbackGen = new GeneratorJsCallback(context.getClassSource(), writer.getNaming());
|
GeneratorJsCallback callbackGen = new GeneratorJsCallback(context.getClassSource(), writer.getNaming());
|
||||||
body = callbackGen.parse(body);
|
body = callbackGen.parse(body);
|
||||||
}
|
}
|
||||||
writer.append("return (function(");
|
writer.append("var result = (function(");
|
||||||
for (int i = 0; i < args.size(); ++i) {
|
for (int i = 0; i < args.size(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
|
@ -53,9 +53,30 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
writer.outdent().append("}).call(").append(context.getParameterName(0));
|
writer.outdent().append("}).call(").append(context.getParameterName(0));
|
||||||
for (int i = 0; i < args.size(); ++i) {
|
for (int i = 0; i < args.size(); ++i) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
writer.append(context.getParameterName(i + 1));
|
wrapParameter(writer, methodRef.getDescriptor().parameterType(i), context.getParameterName(i + 1));
|
||||||
|
}
|
||||||
|
writer.append(")").softNewLine();
|
||||||
|
writer.append("return ");
|
||||||
|
unwrapValue(writer, method.getResultType(), "result");
|
||||||
|
writer.append(";").softNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void wrapParameter(SourceWriter writer, ValueType type, String param) throws IOException {
|
||||||
|
if (type.isObject("java.lang.Object")) {
|
||||||
|
writer.appendMethodBody(JavaScriptBodyConverterGenerator.toJsMethod);
|
||||||
|
writer.append("(").append(param).append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unwrapValue(SourceWriter writer, ValueType type, String param) throws IOException {
|
||||||
|
if (type.isObject("java.lang.Object")) {
|
||||||
|
writer.appendMethodBody(JavaScriptBodyConverterGenerator.fromJsMethod);
|
||||||
|
writer.append("(").append(param).append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(param);
|
||||||
}
|
}
|
||||||
writer.append(");").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class GeneratorJsCallback extends JsCallback {
|
private static class GeneratorJsCallback extends JsCallback {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -49,21 +49,17 @@ public class JavaScriptBodyTests {
|
||||||
assertEquals(23, array[0].foo());
|
assertEquals(23, array[0].foo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void dependencyPropagatedBackThroughArray() {
|
|
||||||
A[] first = new A[1];
|
|
||||||
storeObject(first);
|
|
||||||
Object[] second = (Object[])retrieveObject();
|
|
||||||
second[0] = new AImpl();
|
|
||||||
assertEquals(23, first[0].foo());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void valuePropagatedToCallback() {
|
public void valuePropagatedToCallback() {
|
||||||
A a = new AImpl();
|
A a = new AImpl();
|
||||||
assertEquals(23, invokeCallback(a));
|
assertEquals(23, invokeCallback(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void staticCallbackInvoked() {
|
||||||
|
assertEquals(23, invokeStaticCallback(new AImpl()));
|
||||||
|
}
|
||||||
|
|
||||||
private static class AImpl implements A {
|
private static class AImpl implements A {
|
||||||
@Override public int foo() {
|
@Override public int foo() {
|
||||||
return 23;
|
return 23;
|
||||||
|
@ -90,4 +86,13 @@ public class JavaScriptBodyTests {
|
||||||
"@org.teavm.html4j.test.B::bar(" +
|
"@org.teavm.html4j.test.B::bar(" +
|
||||||
"Lorg/teavm/html4j/test/A;)(_global_)", javacall = true)
|
"Lorg/teavm/html4j/test/A;)(_global_)", javacall = true)
|
||||||
private native int invokeCallback(B callback);
|
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