mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
New JSBody generator allowing to get smaller JavaScript code
This commit is contained in:
parent
792294296d
commit
d4309bb564
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.jso.plugin;
|
package org.teavm.jso.plugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -479,8 +480,11 @@ public class AstWriter {
|
||||||
|
|
||||||
private void print(PropertyGet node) throws IOException {
|
private void print(PropertyGet node) throws IOException {
|
||||||
print(node.getLeft(), PRECEDENCE_MEMBER);
|
print(node.getLeft(), PRECEDENCE_MEMBER);
|
||||||
writer.ws().append('.').ws();
|
writer.append('.');
|
||||||
|
Map<String, String> oldNameMap = nameMap;
|
||||||
|
nameMap = Collections.emptyMap();
|
||||||
print(node.getRight());
|
print(node.getRight());
|
||||||
|
nameMap = oldNameMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(FunctionCall node, int precedence) throws IOException {
|
private void print(FunctionCall node, int precedence) throws IOException {
|
||||||
|
@ -597,7 +601,7 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(ObjectLiteral node) throws IOException {
|
private void print(ObjectLiteral node) throws IOException {
|
||||||
writer.append('{');
|
writer.append('{').ws();
|
||||||
if (node.getElements() != null && !node.getElements().isEmpty()) {
|
if (node.getElements() != null && !node.getElements().isEmpty()) {
|
||||||
print(node.getElements().get(0));
|
print(node.getElements().get(0));
|
||||||
for (int i = 1; i < node.getElements().size(); ++i) {
|
for (int i = 1; i < node.getElements().size(); ++i) {
|
||||||
|
@ -605,7 +609,7 @@ public class AstWriter {
|
||||||
print(node.getElements().get(i));
|
print(node.getElements().get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.append('}');
|
writer.ws().append('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(ObjectProperty node) throws IOException {
|
private void print(ObjectProperty node) throws IOException {
|
||||||
|
@ -614,7 +618,10 @@ public class AstWriter {
|
||||||
} else if (node.isSetterMethod()) {
|
} else if (node.isSetterMethod()) {
|
||||||
writer.append("set ");
|
writer.append("set ");
|
||||||
}
|
}
|
||||||
|
Map<String, String> oldNameMap = nameMap;
|
||||||
|
nameMap = Collections.emptyMap();
|
||||||
print(node.getLeft());
|
print(node.getLeft());
|
||||||
|
nameMap = oldNameMap;
|
||||||
if (!node.isMethod()) {
|
if (!node.isMethod()) {
|
||||||
writer.ws().append(':').ws();
|
writer.ws().append(':').ws();
|
||||||
}
|
}
|
||||||
|
@ -631,7 +638,7 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
writer.append('(');
|
writer.append('(');
|
||||||
printList(node.getParams());
|
printList(node.getParams());
|
||||||
writer.append(')');
|
writer.append(')').ws();
|
||||||
|
|
||||||
if (node.isExpressionClosure()) {
|
if (node.isExpressionClosure()) {
|
||||||
if (node.getBody().getLastChild() instanceof ReturnStatement) {
|
if (node.getBody().getLastChild() instanceof ReturnStatement) {
|
||||||
|
@ -642,10 +649,6 @@ public class AstWriter {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print(node.getBody());
|
print(node.getBody());
|
||||||
writer.softNewLine();
|
|
||||||
}
|
|
||||||
if (node.getFunctionType() == FunctionNode.FUNCTION_STATEMENT || node.isMethod()) {
|
|
||||||
writer.softNewLine();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,8 @@ import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.mozilla.javascript.CompilerEnvirons;
|
import org.mozilla.javascript.CompilerEnvirons;
|
||||||
import org.mozilla.javascript.IRFactory;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.ast.AstNode;
|
|
||||||
import org.mozilla.javascript.ast.AstRoot;
|
import org.mozilla.javascript.ast.AstRoot;
|
||||||
import org.mozilla.javascript.ast.NodeVisitor;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.spi.Generator;
|
import org.teavm.javascript.spi.Generator;
|
||||||
import org.teavm.javascript.spi.GeneratorContext;
|
import org.teavm.javascript.spi.GeneratorContext;
|
||||||
|
@ -45,29 +43,86 @@ public class JSBodyGenerator implements Generator {
|
||||||
AnnotationReader annot = method.getAnnotations().get(JSBodyImpl.class.getName());
|
AnnotationReader annot = method.getAnnotations().get(JSBodyImpl.class.getName());
|
||||||
boolean isStatic = annot.getValue("isStatic").getBoolean();
|
boolean isStatic = annot.getValue("isStatic").getBoolean();
|
||||||
List<AnnotationValue> paramNames = annot.getValue("params").getList();
|
List<AnnotationValue> paramNames = annot.getValue("params").getList();
|
||||||
|
String script = annot.getValue("script").getString();
|
||||||
|
|
||||||
int bodyParamCount = isStatic ? method.parameterCount() : method.parameterCount() - 1;
|
TeaVMErrorReporter errorReporter = new TeaVMErrorReporter(context.getDiagnostics(),
|
||||||
|
new CallLocation(methodRef));
|
||||||
CompilerEnvirons env = new CompilerEnvirons();
|
CompilerEnvirons env = new CompilerEnvirons();
|
||||||
env.setRecoverFromErrors(true);
|
env.setRecoverFromErrors(true);
|
||||||
IRFactory factory = new IRFactory(env, new TeaVMErrorReporter(context.getDiagnostics(),
|
env.setLanguageVersion(Context.VERSION_1_8);
|
||||||
new CallLocation(methodRef)));
|
env.setIdeMode(true);
|
||||||
String script = annot.getValue("script").getString();
|
JSParser parser = new JSParser(env, errorReporter);
|
||||||
AstRoot rootNode;
|
parser.enterFunction();
|
||||||
try {
|
AstRoot rootNode = parser.parse(new StringReader(script), null, 0);
|
||||||
rootNode = factory.parse(new StringReader(script), null, 0);
|
parser.exitFunction();
|
||||||
} catch (IOException e) {
|
if (errorReporter.hasErrors()) {
|
||||||
context.getDiagnostics().error(new CallLocation(methodRef), "IO error parsing JSBody script");
|
generateBloated(context, writer, methodRef, method, isStatic, paramNames, script);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rootNode.visit(new NodeVisitor() {
|
AstWriter astWriter = new AstWriter(writer);
|
||||||
@Override
|
int paramIndex = 1;
|
||||||
public boolean visit(AstNode node) {
|
if (!isStatic) {
|
||||||
return false;
|
astWriter.declareAlias("this", context.getParameterName(paramIndex++));
|
||||||
}
|
}
|
||||||
});
|
for (int i = 0; i < paramNames.size(); ++i) {
|
||||||
|
astWriter.declareAlias(paramNames.get(i).getString(), context.getParameterName(paramIndex++));
|
||||||
|
}
|
||||||
|
astWriter.hoist(rootNode);
|
||||||
|
astWriter.print(rootNode);
|
||||||
|
writer.softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateBloated(GeneratorContext context, SourceWriter writer, MethodReference methodRef,
|
||||||
|
MethodReader method, boolean isStatic, List<AnnotationValue> paramNames, String script)
|
||||||
|
throws IOException {
|
||||||
|
int bodyParamCount = isStatic ? method.parameterCount() : method.parameterCount() - 1;
|
||||||
|
|
||||||
|
writer.append("if (!").appendMethodBody(methodRef).append(".$native)").ws().append('{').indent().newLine();
|
||||||
|
writer.appendMethodBody(methodRef).append(".$native").ws().append('=').ws().append("function(");
|
||||||
|
int count = method.parameterCount();
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
writer.append('_').append(context.getParameterName(i + 1));
|
||||||
|
}
|
||||||
|
writer.append(')').ws().append('{').softNewLine().indent();
|
||||||
|
|
||||||
|
writer.append("return (function(");
|
||||||
|
for (int i = 0; i < bodyParamCount; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
String name = paramNames.get(i).getString();
|
||||||
|
writer.append(name);
|
||||||
|
}
|
||||||
|
writer.append(')').ws().append('{').softNewLine().indent();
|
||||||
|
writer.append(script).softNewLine();
|
||||||
|
writer.outdent().append("})");
|
||||||
|
if (!isStatic) {
|
||||||
|
writer.append(".call");
|
||||||
|
}
|
||||||
|
writer.append('(');
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
writer.append('_').append(context.getParameterName(i + 1));
|
||||||
|
}
|
||||||
|
writer.append(");").softNewLine();
|
||||||
|
writer.outdent().append("};").softNewLine();
|
||||||
|
writer.appendMethodBody(methodRef).ws().append('=').ws().appendMethodBody(methodRef).append(".$native;")
|
||||||
|
.softNewLine();
|
||||||
|
writer.outdent().append("}").softNewLine();
|
||||||
|
|
||||||
|
writer.append("return ").appendMethodBody(methodRef).append('(');
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
writer.append(context.getParameterName(i + 1));
|
||||||
|
}
|
||||||
|
writer.append(");").softNewLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,22 +27,28 @@ import org.teavm.model.CallLocation;
|
||||||
public class TeaVMErrorReporter implements ErrorReporter {
|
public class TeaVMErrorReporter implements ErrorReporter {
|
||||||
private Diagnostics diagnostics;
|
private Diagnostics diagnostics;
|
||||||
private CallLocation location;
|
private CallLocation location;
|
||||||
|
private boolean hasErrors;
|
||||||
|
|
||||||
public TeaVMErrorReporter(Diagnostics diagnostics, CallLocation location) {
|
public TeaVMErrorReporter(Diagnostics diagnostics, CallLocation location) {
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasErrors() {
|
||||||
|
return hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
||||||
diagnostics.warning(location, "Error in @JSBody script line " + line + ", char " + lineOffset
|
diagnostics.warning(location, "Warning in @JSBody script line " + line + ", char " + lineOffset
|
||||||
+ ": " + message);
|
+ ": " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
|
||||||
diagnostics.error(location, "Error in @JSBody script line " + line + ", char " + lineOffset
|
diagnostics.warning(location, "Error in @JSBody script line " + line + ", char " + lineOffset
|
||||||
+ ": " + message);
|
+ ": " + message);
|
||||||
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -45,9 +45,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
||||||
<goals>
|
<goals>
|
||||||
<goal>test-jar</goal>
|
<goal>test-jar</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
|
||||||
<classifier>tck</classifier>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
@ -67,6 +64,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -22,9 +22,9 @@ public final class Performance implements JSObject {
|
||||||
private Performance() {
|
private Performance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSBody(params = {}, script = "return Performance.now();")
|
@JSBody(params = {}, script = "return window.performance.now();")
|
||||||
public static native double now();
|
public static native double now();
|
||||||
|
|
||||||
@JSBody(params = {}, script = "return typeof(Performance) !== 'undefined';")
|
@JSBody(params = {}, script = "return typeof(window.performance) !== 'undefined';")
|
||||||
public static native boolean isSupported();
|
public static native boolean isSupported();
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class AnnotationsTest {
|
||||||
|
|
||||||
@JSBody(params = "value", script = ""
|
@JSBody(params = "value", script = ""
|
||||||
+ "return {"
|
+ "return {"
|
||||||
+ "value : value, "
|
+ "'value' : value, "
|
||||||
+ "testMethod : function(num) { return this.value + num + 1; }, "
|
+ "testMethod : function(num) { return this.value + num + 1; }, "
|
||||||
+ "renamedJSMethod : function(num) { return this.value + num + 2; }"
|
+ "renamedJSMethod : function(num) { return this.value + num + 2; }"
|
||||||
+ "};")
|
+ "};")
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
package org.teavm.samples.kotlin
|
package org.teavm.samples.kotlin
|
||||||
|
|
||||||
import org.teavm.jso.*
|
import org.teavm.jso.*
|
||||||
import org.teavm.dom.browser.*
|
import org.teavm.jso.browser.*
|
||||||
import org.teavm.dom.html.*
|
import org.teavm.jso.dom.html.*
|
||||||
import org.teavm.dom.events.*
|
import org.teavm.jso.dom.events.*
|
||||||
|
|
||||||
fun main(args : Array<String>) {
|
fun main(args : Array<String>) {
|
||||||
var window = JS.getGlobal() as Window;
|
var document = Window.current().getDocument();
|
||||||
var document = window.getDocument();
|
|
||||||
|
|
||||||
document.getElementById("hello-kotlin").addEventListener("click", EventListener<MouseEvent>() {
|
document.getElementById("hello-kotlin").addEventListener("click", EventListener<MouseEvent>() {
|
||||||
window.alert("Hello, developer!");
|
Window.alert("Hello, developer!");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
<groupId>org.teavm</groupId>
|
<groupId>org.teavm</groupId>
|
||||||
<artifactId>teavm-jso</artifactId>
|
<artifactId>teavm-jso</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<classifier>tck</classifier>
|
<classifier>tests</classifier>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
@ -83,6 +84,12 @@
|
||||||
<phase>process-test-classes</phase>
|
<phase>process-test-classes</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minifying>false</minifying>
|
<minifying>false</minifying>
|
||||||
|
<scanDependencies>true</scanDependencies>
|
||||||
|
<wildcards>
|
||||||
|
<wildcard>org.teavm.classlib.**.*Test</wildcard>
|
||||||
|
<wildcard>org.teavm.jso.**.*Test</wildcard>
|
||||||
|
<wildcard>org.teavm.platform.metadata.*Test</wildcard>
|
||||||
|
</wildcards>
|
||||||
<properties>
|
<properties>
|
||||||
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
|
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user