mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>enable-html4j-support</id>
|
||||||
|
<modules>
|
||||||
|
<module>teavm-html4j</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
</project>
|
</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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user