mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds initial source code of plugin to support html4j
This commit is contained in:
parent
cc3a89ebf7
commit
afc85c9780
9
pom.xml
9
pom.xml
|
@ -34,4 +34,13 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>enable-html4j-support</id>
|
||||
<modules>
|
||||
<module>teavm-html4j</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
5
teavm-html4j/.gitignore
vendored
Normal file
5
teavm-html4j/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/target
|
||||
/.settings
|
||||
/.classpath
|
||||
/.factorypath
|
||||
/.project
|
101
teavm-html4j/pom.xml
Normal file
101
teavm-html4j/pom.xml
Normal file
|
@ -0,0 +1,101 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>teavm-html4j</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-core</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-classlib</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.netbeans.html</groupId>
|
||||
<artifactId>net.java.html.boot</artifactId>
|
||||
<version>0.8-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-maven-plugin</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-javascript-tests</id>
|
||||
<goals>
|
||||
<goal>build-junit</goal>
|
||||
</goals>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<minifying>false</minifying>
|
||||
<numThreads>1</numThreads>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-maven-plugin</artifactId>
|
||||
<versionRange>[0.0.1-SNAPSHOT,)</versionRange>
|
||||
<goals>
|
||||
<goal>build-junit</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore></ignore>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.JavascriptBuilderHost;
|
||||
import org.teavm.javascript.JavascriptBuilderPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class HTML4JPlugin implements JavascriptBuilderPlugin {
|
||||
@Override
|
||||
public void install(JavascriptBuilderHost host) {
|
||||
host.add(new JavaScriptBodyDependency());
|
||||
host.add(new JavaScriptBodyTransformer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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 net.java.html.js.JavaScriptBody;
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class JavaScriptBodyDependency implements DependencyListener {
|
||||
private DependencyNode allClassesNode;
|
||||
|
||||
@Override
|
||||
public void started(DependencyChecker dependencyChecker) {
|
||||
allClassesNode = dependencyChecker.createNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
||||
allClassesNode.propagate(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodReference methodRef) {
|
||||
ClassHolder cls = dependencyChecker.getClassSource().get(methodRef.getClassName());
|
||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
||||
AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName());
|
||||
if (annot != null) {
|
||||
AnnotationValue javacall = annot.getValue("javacall");
|
||||
MethodGraph graph = dependencyChecker.attachMethodGraph(methodRef);
|
||||
if (graph.getResult() != null) {
|
||||
allClassesNode.connect(graph.getResult());
|
||||
}
|
||||
if (javacall != null && javacall.getBoolean()) {
|
||||
String body = annot.getValue("body").getString();
|
||||
new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldReference field) {
|
||||
}
|
||||
|
||||
private static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) {
|
||||
while (clsName != null) {
|
||||
ClassReader cls = classSource.get(clsName);
|
||||
for (MethodReader method : cls.getMethods()) {
|
||||
if (method.getName().equals(desc.getName()) && sameParams(method.getDescriptor(), desc)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
clsName = cls.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static boolean sameParams(MethodDescriptor a, MethodDescriptor b) {
|
||||
if (a.parameterCount() != b.parameterCount()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.parameterCount(); ++i) {
|
||||
if (!a.parameterType(i).equals(b.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private class GeneratorJsCallback extends JsCallback {
|
||||
private ClassReaderSource classSource;
|
||||
private DependencyChecker dependencyChecker;
|
||||
public GeneratorJsCallback(ClassReaderSource classSource, DependencyChecker dependencyChecker) {
|
||||
this.classSource = classSource;
|
||||
this.dependencyChecker = dependencyChecker;
|
||||
}
|
||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||
MethodDescriptor desc = MethodDescriptor.parse(method + "V");
|
||||
MethodReader reader = findMethod(classSource, fqn, desc);
|
||||
if (reader != null) {
|
||||
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
||||
MethodGraph graph = dependencyChecker.attachMethodGraph(reader.getReference());
|
||||
for (int i = 0; i <= graph.getParameterCount(); ++i) {
|
||||
allClassesNode.connect(graph.getVariable(i));
|
||||
}
|
||||
} else {
|
||||
allClassesNode.addConsumer(new VirtualCallbackConsumer(classSource, dependencyChecker, desc));
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private class VirtualCallbackConsumer implements DependencyConsumer {
|
||||
private ClassReaderSource classSource;
|
||||
private DependencyChecker dependencyChecker;
|
||||
private MethodDescriptor desc;
|
||||
public VirtualCallbackConsumer(ClassReaderSource classSource, DependencyChecker dependencyChecker,
|
||||
MethodDescriptor desc) {
|
||||
this.classSource = classSource;
|
||||
this.dependencyChecker = dependencyChecker;
|
||||
this.desc = desc;
|
||||
}
|
||||
@Override public void consume(String type) {
|
||||
MethodReader reader = findMethod(classSource, type, desc);
|
||||
if (reader != null) {
|
||||
MethodGraph graph = dependencyChecker.attachMethodGraph(reader.getReference());
|
||||
for (int i = 0; i <= graph.getParameterCount(); ++i) {
|
||||
allClassesNode.connect(graph.getVariable(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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 java.util.List;
|
||||
import net.java.html.js.JavaScriptBody;
|
||||
import org.teavm.codegen.NamingStrategy;
|
||||
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 JavaScriptBodyGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
MethodReader method = context.getClassSource().get(methodRef.getClassName())
|
||||
.getMethod(methodRef.getDescriptor());
|
||||
AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName());
|
||||
String body = annot.getValue("body").getString();
|
||||
List<AnnotationValue> args = annot.getValue("args").getList();
|
||||
AnnotationValue javacall = annot.getValue("javacall");
|
||||
if (javacall != null && javacall.getBoolean()) {
|
||||
GeneratorJsCallback callbackGen = new GeneratorJsCallback(context.getClassSource(), writer.getNaming());
|
||||
body = callbackGen.parse(body);
|
||||
}
|
||||
writer.append("return (function(");
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
writer.append(args.get(i).getString());
|
||||
}
|
||||
writer.append(")").ws().append("{").indent().softNewLine();
|
||||
writer.append(body).softNewLine();
|
||||
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));
|
||||
}
|
||||
writer.append(");");
|
||||
}
|
||||
|
||||
private static class GeneratorJsCallback extends JsCallback {
|
||||
private ClassReaderSource classSource;
|
||||
private NamingStrategy naming;
|
||||
public GeneratorJsCallback(ClassReaderSource classSource, NamingStrategy naming) {
|
||||
this.classSource = classSource;
|
||||
this.naming = naming;
|
||||
}
|
||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||
MethodDescriptor desc = MethodDescriptor.parse(method + "V");
|
||||
MethodReader reader = findMethod(fqn, desc);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String name = naming.getNameFor(naming.getNameFor(reader.getReference()));
|
||||
if (ident != null) {
|
||||
if (reader.hasModifier(ElementModifier.FINAL)) {
|
||||
sb.append(name).append("(").append(ident).append(",").append(params.substring(1));
|
||||
} else {
|
||||
sb.append(ident).append('.').append(name).append(params);
|
||||
}
|
||||
} else {
|
||||
sb.append("(").append(ident).append(",").append(params.substring(1));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
private MethodReader findMethod(String clsName, MethodDescriptor desc) {
|
||||
while (clsName != null) {
|
||||
ClassReader cls = classSource.get(clsName);
|
||||
for (MethodReader method : cls.getMethods()) {
|
||||
if (method.getName().equals(desc.getName()) && sameParams(method.getDescriptor(), desc)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
clsName = cls.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private boolean sameParams(MethodDescriptor a, MethodDescriptor b) {
|
||||
if (a.parameterCount() != b.parameterCount()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.parameterCount(); ++i) {
|
||||
if (!a.parameterType(i).equals(b.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 net.java.html.js.JavaScriptBody;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class JavaScriptBodyTransformer implements ClassHolderTransformer {
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
if (method.getAnnotations().get(JavaScriptBody.class.getName()) != null) {
|
||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||
JavaScriptBodyGenerator.class.getName())));
|
||||
method.getAnnotations().add(genAnnot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
teavm-html4j/src/main/java/org/teavm/html4j/JsCallback.java
Normal file
174
teavm-html4j/src/main/java/org/teavm/html4j/JsCallback.java
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
||||
*
|
||||
* Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
||||
* Other names may be trademarks of their respective owners.
|
||||
*
|
||||
* The contents of this file are subject to the terms of either the GNU
|
||||
* General Public License Version 2 only ("GPL") or the Common
|
||||
* Development and Distribution License("CDDL") (collectively, the
|
||||
* "License"). You may not use this file except in compliance with the
|
||||
* License. You can obtain a copy of the License at
|
||||
* http://www.netbeans.org/cddl-gplv2.html
|
||||
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
||||
* specific language governing permissions and limitations under the
|
||||
* License. When distributing the software, include this License Header
|
||||
* Notice in each file and include the License file at
|
||||
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the GPL Version 2 section of the License file that
|
||||
* accompanied this code. If applicable, add the following below the
|
||||
* License Header, with the fields enclosed by brackets [] replaced by
|
||||
* your own identifying information:
|
||||
* "Portions Copyrighted [year] [name of copyright owner]"
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* The Original Software is NetBeans. The Initial Developer of the Original
|
||||
* Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
|
||||
*
|
||||
* If you wish your version of this file to be governed by only the CDDL
|
||||
* or only the GPL Version 2, indicate your decision by adding
|
||||
* "[Contributor] elects to include this software in this distribution
|
||||
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
||||
* single choice of license, a recipient has the option to distribute
|
||||
* your version of this file under either the CDDL, the GPL Version 2 or
|
||||
* to extend the choice of license to its licensees as provided above.
|
||||
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
||||
* Version 2 license, then the option applies only if the new code is
|
||||
* made subject to such option by the copyright holder.
|
||||
*/
|
||||
package org.teavm.html4j;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jaroslav Tulach <jtulach@netbeans.org>
|
||||
*/
|
||||
abstract class JsCallback {
|
||||
final String parse(String body) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int pos = 0;
|
||||
for (;;) {
|
||||
int next = body.indexOf(".@", pos);
|
||||
if (next == -1) {
|
||||
sb.append(body.substring(pos));
|
||||
body = sb.toString();
|
||||
break;
|
||||
}
|
||||
int ident = next;
|
||||
while (ident > 0) {
|
||||
if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
|
||||
ident++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String refId = body.substring(ident, next);
|
||||
|
||||
sb.append(body.substring(pos, ident));
|
||||
|
||||
int sigBeg = body.indexOf('(', next);
|
||||
int sigEnd = body.indexOf(')', sigBeg);
|
||||
int colon4 = body.indexOf("::", next);
|
||||
if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
|
||||
throw new IllegalStateException(
|
||||
"Wrong format of instance callback. "
|
||||
+ "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
|
||||
+ body
|
||||
);
|
||||
}
|
||||
String fqn = body.substring(next + 2, colon4);
|
||||
String method = body.substring(colon4 + 2, sigBeg);
|
||||
String params = body.substring(sigBeg, sigEnd + 1);
|
||||
|
||||
int paramBeg = body.indexOf('(', sigEnd + 1);
|
||||
if (paramBeg == -1) {
|
||||
throw new IllegalStateException(
|
||||
"Wrong format of instance callback. "
|
||||
+ "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n"
|
||||
+ body
|
||||
);
|
||||
}
|
||||
|
||||
sb.append(callMethod(refId, fqn, method, params));
|
||||
if (body.charAt(paramBeg + 1) != (')')) {
|
||||
sb.append(",");
|
||||
}
|
||||
pos = paramBeg + 1;
|
||||
}
|
||||
pos = 0;
|
||||
sb = null;
|
||||
for (;;) {
|
||||
int next = body.indexOf("@", pos);
|
||||
if (next == -1) {
|
||||
if (sb == null) {
|
||||
return body;
|
||||
}
|
||||
sb.append(body.substring(pos));
|
||||
return sb.toString();
|
||||
}
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
|
||||
sb.append(body.substring(pos, next));
|
||||
|
||||
int sigBeg = body.indexOf('(', next);
|
||||
int sigEnd = body.indexOf(')', sigBeg);
|
||||
int colon4 = body.indexOf("::", next);
|
||||
if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
|
||||
throw new IllegalStateException(
|
||||
"Wrong format of static callback. "
|
||||
+ "Should be: '@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n"
|
||||
+ body
|
||||
);
|
||||
}
|
||||
String fqn = body.substring(next + 1, colon4);
|
||||
String method = body.substring(colon4 + 2, sigBeg);
|
||||
String params = body.substring(sigBeg, sigEnd + 1);
|
||||
|
||||
int paramBeg = body.indexOf('(', sigEnd + 1);
|
||||
|
||||
sb.append(callMethod(null, fqn, method, params));
|
||||
pos = paramBeg + 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract CharSequence callMethod(
|
||||
String ident, String fqn, String method, String params
|
||||
);
|
||||
|
||||
static String mangle(String fqn, String method, String params) {
|
||||
if (params.startsWith("(")) {
|
||||
params = params.substring(1);
|
||||
}
|
||||
if (params.endsWith(")")) {
|
||||
params = params.substring(0, params.length() - 1);
|
||||
}
|
||||
return
|
||||
replace(fqn) + "$" + replace(method) + "$" + replace(params);
|
||||
}
|
||||
|
||||
private static String replace(String orig) {
|
||||
return orig.replace("_", "_1").
|
||||
replace(";", "_2").
|
||||
replace("[", "_3").
|
||||
replace('.', '_').replace('/', '_');
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.teavm.html4j.HTML4JPlugin
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 JavaScriptBodyTests {
|
||||
@Test
|
||||
public void javaScriptBodyHandled() {
|
||||
assertEquals(23, simpleNativeMethod());
|
||||
}
|
||||
|
||||
@JavaScriptBody(args = {}, body = "return 23;")
|
||||
private native int simpleNativeMethod();
|
||||
|
||||
@Test
|
||||
public void dependencyPropagated() {
|
||||
A a = (A)returnValuePassed(new AImpl());
|
||||
assertEquals(23, a.foo());
|
||||
}
|
||||
|
||||
private static interface A {
|
||||
public int foo();
|
||||
}
|
||||
private static class AImpl implements A {
|
||||
@Override public int foo() {
|
||||
return 23;
|
||||
}
|
||||
}
|
||||
@JavaScriptBody(args = { "value" }, body = "return value;")
|
||||
private native Object returnValuePassed(Object value);
|
||||
}
|
|
@ -23,7 +23,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
|||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>teavm-jso</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
|
|
Loading…
Reference in New Issue
Block a user