mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -479,8 +480,11 @@ public class AstWriter {
|
|||
|
||||
private void print(PropertyGet node) throws IOException {
|
||||
print(node.getLeft(), PRECEDENCE_MEMBER);
|
||||
writer.ws().append('.').ws();
|
||||
writer.append('.');
|
||||
Map<String, String> oldNameMap = nameMap;
|
||||
nameMap = Collections.emptyMap();
|
||||
print(node.getRight());
|
||||
nameMap = oldNameMap;
|
||||
}
|
||||
|
||||
private void print(FunctionCall node, int precedence) throws IOException {
|
||||
|
@ -597,7 +601,7 @@ public class AstWriter {
|
|||
}
|
||||
|
||||
private void print(ObjectLiteral node) throws IOException {
|
||||
writer.append('{');
|
||||
writer.append('{').ws();
|
||||
if (node.getElements() != null && !node.getElements().isEmpty()) {
|
||||
print(node.getElements().get(0));
|
||||
for (int i = 1; i < node.getElements().size(); ++i) {
|
||||
|
@ -605,7 +609,7 @@ public class AstWriter {
|
|||
print(node.getElements().get(i));
|
||||
}
|
||||
}
|
||||
writer.append('}');
|
||||
writer.ws().append('}');
|
||||
}
|
||||
|
||||
private void print(ObjectProperty node) throws IOException {
|
||||
|
@ -614,7 +618,10 @@ public class AstWriter {
|
|||
} else if (node.isSetterMethod()) {
|
||||
writer.append("set ");
|
||||
}
|
||||
Map<String, String> oldNameMap = nameMap;
|
||||
nameMap = Collections.emptyMap();
|
||||
print(node.getLeft());
|
||||
nameMap = oldNameMap;
|
||||
if (!node.isMethod()) {
|
||||
writer.ws().append(':').ws();
|
||||
}
|
||||
|
@ -631,7 +638,7 @@ public class AstWriter {
|
|||
}
|
||||
writer.append('(');
|
||||
printList(node.getParams());
|
||||
writer.append(')');
|
||||
writer.append(')').ws();
|
||||
|
||||
if (node.isExpressionClosure()) {
|
||||
if (node.getBody().getLastChild() instanceof ReturnStatement) {
|
||||
|
@ -642,10 +649,6 @@ public class AstWriter {
|
|||
}
|
||||
} else {
|
||||
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.util.List;
|
||||
import org.mozilla.javascript.CompilerEnvirons;
|
||||
import org.mozilla.javascript.IRFactory;
|
||||
import org.mozilla.javascript.ast.AstNode;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ast.AstRoot;
|
||||
import org.mozilla.javascript.ast.NodeVisitor;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.spi.Generator;
|
||||
import org.teavm.javascript.spi.GeneratorContext;
|
||||
|
@ -45,29 +43,86 @@ public class JSBodyGenerator implements Generator {
|
|||
AnnotationReader annot = method.getAnnotations().get(JSBodyImpl.class.getName());
|
||||
boolean isStatic = annot.getValue("isStatic").getBoolean();
|
||||
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();
|
||||
env.setRecoverFromErrors(true);
|
||||
IRFactory factory = new IRFactory(env, new TeaVMErrorReporter(context.getDiagnostics(),
|
||||
new CallLocation(methodRef)));
|
||||
String script = annot.getValue("script").getString();
|
||||
AstRoot rootNode;
|
||||
try {
|
||||
rootNode = factory.parse(new StringReader(script), null, 0);
|
||||
} catch (IOException e) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "IO error parsing JSBody script");
|
||||
env.setLanguageVersion(Context.VERSION_1_8);
|
||||
env.setIdeMode(true);
|
||||
JSParser parser = new JSParser(env, errorReporter);
|
||||
parser.enterFunction();
|
||||
AstRoot rootNode = parser.parse(new StringReader(script), null, 0);
|
||||
parser.exitFunction();
|
||||
if (errorReporter.hasErrors()) {
|
||||
generateBloated(context, writer, methodRef, method, isStatic, paramNames, script);
|
||||
return;
|
||||
}
|
||||
|
||||
rootNode.visit(new NodeVisitor() {
|
||||
@Override
|
||||
public boolean visit(AstNode node) {
|
||||
return false;
|
||||
AstWriter astWriter = new AstWriter(writer);
|
||||
int paramIndex = 1;
|
||||
if (!isStatic) {
|
||||
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 {
|
||||
private Diagnostics diagnostics;
|
||||
private CallLocation location;
|
||||
private boolean hasErrors;
|
||||
|
||||
public TeaVMErrorReporter(Diagnostics diagnostics, CallLocation location) {
|
||||
this.diagnostics = diagnostics;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,9 +45,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
|||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>tck</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</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>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -22,9 +22,9 @@ public final class Performance implements JSObject {
|
|||
private Performance() {
|
||||
}
|
||||
|
||||
@JSBody(params = {}, script = "return Performance.now();")
|
||||
@JSBody(params = {}, script = "return window.performance.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();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class AnnotationsTest {
|
|||
|
||||
@JSBody(params = "value", script = ""
|
||||
+ "return {"
|
||||
+ "value : value, "
|
||||
+ "'value' : value, "
|
||||
+ "testMethod : function(num) { return this.value + num + 1; }, "
|
||||
+ "renamedJSMethod : function(num) { return this.value + num + 2; }"
|
||||
+ "};")
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
package org.teavm.samples.kotlin
|
||||
|
||||
import org.teavm.jso.*
|
||||
import org.teavm.dom.browser.*
|
||||
import org.teavm.dom.html.*
|
||||
import org.teavm.dom.events.*
|
||||
import org.teavm.jso.browser.*
|
||||
import org.teavm.jso.dom.html.*
|
||||
import org.teavm.jso.dom.events.*
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
var window = JS.getGlobal() as Window;
|
||||
var document = window.getDocument();
|
||||
var document = Window.current().getDocument();
|
||||
|
||||
document.getElementById("hello-kotlin").addEventListener("click", EventListener<MouseEvent>() {
|
||||
window.alert("Hello, developer!");
|
||||
Window.alert("Hello, developer!");
|
||||
})
|
||||
}
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-jso</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tck</classifier>
|
||||
<classifier>tests</classifier>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
@ -83,6 +84,12 @@
|
|||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<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>
|
||||
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
|
||||
</properties>
|
||||
|
|
Loading…
Reference in New Issue
Block a user