JS: get rid of IOException in SourceWriter and related classes

This commit is contained in:
Alexey Andreev 2023-10-31 20:09:55 +01:00
parent 32ee8943c1
commit 23ad999bbd
54 changed files with 1388 additions and 1605 deletions

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.impl; package org.teavm.classlib.impl;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -27,7 +26,7 @@ public class ServiceLoaderJSSupport implements Generator {
private static final MethodDescriptor INIT_METHOD = new MethodDescriptor("<init>", void.class); private static final MethodDescriptor INIT_METHOD = new MethodDescriptor("<init>", void.class);
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource()); var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource());
var template = templateFactory.createFromResource("org/teavm/classlib/java/util/ServiceLoader.js"); var template = templateFactory.createFromResource("org/teavm/classlib/java/util/ServiceLoader.js");
var information = context.getService(ServiceLoaderInformation.class); var information = context.getService(ServiceLoaderInformation.class);

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.classlib.impl.reflection; package org.teavm.classlib.impl.reflection;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public class ConverterInjector implements Injector { public class ConverterInjector implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "toJava": case "toJava":
case "fromJava": case "fromJava":

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.impl.string; package org.teavm.classlib.impl.string;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -23,7 +22,7 @@ import org.teavm.model.MethodReference;
public class JSStringConstructorGenerator implements Generator { public class JSStringConstructorGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
writer.append(context.getParameterName(0)); writer.append(context.getParameterName(0));
writer.append(".").appendField(JSStringInjector.NATIVE_FIELD).ws().append("=").ws(); writer.append(".").appendField(JSStringInjector.NATIVE_FIELD).ws().append("=").ws();
writer.append(context.getParameterName(1)).append(";").softNewLine(); writer.append(context.getParameterName(1)).append(";").softNewLine();

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.impl.string; package org.teavm.classlib.impl.string;
import java.io.IOException;
import java.util.function.Function; import java.util.function.Function;
import org.teavm.backend.javascript.ProviderContext; import org.teavm.backend.javascript.ProviderContext;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
@ -51,7 +50,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
} }
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "initWithEmptyChars": case "initWithEmptyChars":
initWithEmptyChars(context); initWithEmptyChars(context);
@ -104,13 +103,13 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
} }
} }
private void initWithEmptyChars(InjectorContext context) throws IOException { private void initWithEmptyChars(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws().append("\"\""); writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws().append("\"\"");
} }
private void borrowChars(InjectorContext context) throws IOException { private void borrowChars(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws(); writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws();
@ -118,7 +117,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(".").appendField(NATIVE_FIELD); writer.append(".").appendField(NATIVE_FIELD);
} }
private void initWithCharArray(InjectorContext context) throws IOException { private void initWithCharArray(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws(); writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws();
@ -131,7 +130,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(")"); writer.append(")");
} }
private void takeCharArray(InjectorContext context) throws IOException { private void takeCharArray(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws(); writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws();
@ -140,13 +139,13 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(".data)"); writer.append(".data)");
} }
private void charactersLength(InjectorContext context) throws IOException { private void charactersLength(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).append(".length"); writer.append(".").appendField(NATIVE_FIELD).append(".length");
} }
private void charactersGet(InjectorContext context) throws IOException { private void charactersGet(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD).append(".charCodeAt("); writer.append(".").appendField(NATIVE_FIELD).append(".charCodeAt(");
@ -154,7 +153,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(")"); writer.append(")");
} }
private void copyCharsToArray(InjectorContext context) throws IOException { private void copyCharsToArray(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
writer.appendFunction("$rt_stringToCharArray").append("("); writer.appendFunction("$rt_stringToCharArray").append("(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
@ -171,7 +170,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(")"); writer.append(")");
} }
private void substringJS(InjectorContext context) throws IOException { private void substringJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".substring("); writer.append(".substring(");
@ -181,7 +180,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(")"); writer.append(")");
} }
private void fastCharArray(InjectorContext context) throws IOException { private void fastCharArray(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
writer.appendFunction("$rt_fastStringToCharArray").append("("); writer.appendFunction("$rt_fastStringToCharArray").append("(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
@ -189,44 +188,44 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
writer.append(")"); writer.append(")");
} }
private void nativeString(InjectorContext context) throws IOException { private void nativeString(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".").appendField(NATIVE_FIELD); writer.append(".").appendField(NATIVE_FIELD);
} }
private void toLowerCaseJS(InjectorContext context) throws IOException { private void toLowerCaseJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".toLowerCase()"); writer.append(".toLowerCase()");
} }
private void toUpperCaseJS(InjectorContext context) throws IOException { private void toUpperCaseJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".toUpperCase()"); writer.append(".toUpperCase()");
} }
private void intern(InjectorContext context) throws IOException { private void intern(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
writer.appendFunction("$rt_intern").append("("); writer.appendFunction("$rt_intern").append("(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(")"); writer.append(")");
} }
private void stripJS(InjectorContext context) throws IOException { private void stripJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".trim()"); writer.append(".trim()");
} }
private void stripLeadingJS(InjectorContext context) throws IOException { private void stripLeadingJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".trimStart()"); writer.append(".trimStart()");
} }
private void stripTrailingJS(InjectorContext context) throws IOException { private void stripTrailingJS(InjectorContext context) {
var writer = context.getWriter(); var writer = context.getWriter();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(".trimEnd()"); writer.append(".trimEnd()");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import java.util.Set; import java.util.Set;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.rendering.Precedence; import org.teavm.backend.javascript.rendering.Precedence;
@ -43,7 +42,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
new FieldReference(Class.class.getName(), "platformClass"); new FieldReference(Class.class.getName(), "platformClass");
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "createMetadata": case "createMetadata":
generateCreateMetadata(context, writer); generateCreateMetadata(context, writer);
@ -52,7 +51,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "newEmptyInstance": case "newEmptyInstance":
context.getWriter().append("new").ws().append("("); context.getWriter().append("new").ws().append("(");
@ -133,7 +132,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
}); });
} }
private void generateCreateMetadata(GeneratorContext context, SourceWriter writer) throws IOException { private void generateCreateMetadata(GeneratorContext context, SourceWriter writer) {
ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class); ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class);
for (String className : reflection.getClassesWithReflectableFields()) { for (String className : reflection.getClassesWithReflectableFields()) {
generateCreateFieldsForClass(context, writer, className); generateCreateFieldsForClass(context, writer, className);
@ -143,8 +142,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
} }
private void generateCreateFieldsForClass(GeneratorContext context, SourceWriter writer, String className) private void generateCreateFieldsForClass(GeneratorContext context, SourceWriter writer, String className) {
throws IOException {
ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class); ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class);
Set<String> accessibleFields = reflection.getAccessibleFields(className); Set<String> accessibleFields = reflection.getAccessibleFields(className);
@ -178,8 +176,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
writer.outdent().append("];").softNewLine(); writer.outdent().append("];").softNewLine();
} }
private void generateCreateMethodsForClass(GeneratorContext context, SourceWriter writer, String className) private void generateCreateMethodsForClass(GeneratorContext context, SourceWriter writer, String className) {
throws IOException {
ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class); ReflectionDependencyListener reflection = context.getService(ReflectionDependencyListener.class);
Set<MethodDescriptor> accessibleMethods = reflection.getAccessibleMethods(className); Set<MethodDescriptor> accessibleMethods = reflection.getAccessibleMethods(className);
@ -219,7 +216,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
private <T extends MemberReader> void generateCreateMembers(SourceWriter writer, Iterable<T> members, private <T extends MemberReader> void generateCreateMembers(SourceWriter writer, Iterable<T> members,
MemberRenderer<T> renderer) throws IOException { MemberRenderer<T> renderer) {
boolean first = true; boolean first = true;
for (T member : members) { for (T member : members) {
if (!first) { if (!first) {
@ -240,7 +237,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
} }
private void appendProperty(SourceWriter writer, String name, boolean first, Fragment value) throws IOException { private void appendProperty(SourceWriter writer, String name, boolean first, Fragment value) {
if (!first) { if (!first) {
writer.append(",").softNewLine(); writer.append(",").softNewLine();
} }
@ -248,7 +245,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
value.render(); value.render();
} }
private void renderGetter(GeneratorContext context, SourceWriter writer, FieldReader field) throws IOException { private void renderGetter(GeneratorContext context, SourceWriter writer, FieldReader field) {
writer.append("function(obj)").ws().append("{").indent().softNewLine(); writer.append("function(obj)").ws().append("{").indent().softNewLine();
initClass(context, writer, field); initClass(context, writer, field);
writer.append("return "); writer.append("return ");
@ -257,7 +254,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
writer.outdent().append("}"); writer.outdent().append("}");
} }
private void renderSetter(GeneratorContext context, SourceWriter writer, FieldReader field) throws IOException { private void renderSetter(GeneratorContext context, SourceWriter writer, FieldReader field) {
writer.append("function(obj,").ws().append("val)").ws().append("{").indent().softNewLine(); writer.append("function(obj,").ws().append("val)").ws().append("{").indent().softNewLine();
initClass(context, writer, field); initClass(context, writer, field);
fieldAccess(writer, field); fieldAccess(writer, field);
@ -267,7 +264,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
writer.outdent().append("}"); writer.outdent().append("}");
} }
private void renderCallable(GeneratorContext context, SourceWriter writer, MethodReader method) throws IOException { private void renderCallable(GeneratorContext context, SourceWriter writer, MethodReader method) {
writer.append("function(obj,").ws().append("args)").ws().append("{").indent().softNewLine(); writer.append("function(obj,").ws().append("args)").ws().append("{").indent().softNewLine();
initClass(context, writer, method); initClass(context, writer, method);
@ -299,13 +296,13 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
writer.outdent().append("}"); writer.outdent().append("}");
} }
private void initClass(GeneratorContext context, SourceWriter writer, MemberReader member) throws IOException { private void initClass(GeneratorContext context, SourceWriter writer, MemberReader member) {
if (member.hasModifier(ElementModifier.STATIC) && context.isDynamicInitializer(member.getOwnerName())) { if (member.hasModifier(ElementModifier.STATIC) && context.isDynamicInitializer(member.getOwnerName())) {
writer.appendClassInit(member.getOwnerName()).append("();").softNewLine(); writer.appendClassInit(member.getOwnerName()).append("();").softNewLine();
} }
} }
private void fieldAccess(SourceWriter writer, FieldReader field) throws IOException { private void fieldAccess(SourceWriter writer, FieldReader field) {
if (field.hasModifier(ElementModifier.STATIC)) { if (field.hasModifier(ElementModifier.STATIC)) {
writer.appendStaticField(field.getReference()); writer.appendStaticField(field.getReference());
} else { } else {
@ -313,7 +310,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
} }
private void boxIfNecessary(SourceWriter writer, ValueType type, Fragment fragment) throws IOException { private void boxIfNecessary(SourceWriter writer, ValueType type, Fragment fragment) {
boolean boxed = false; boolean boxed = false;
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) { switch (((ValueType.Primitive) type).getKind()) {
@ -353,7 +350,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
} }
private void unboxIfNecessary(SourceWriter writer, ValueType type, Fragment fragment) throws IOException { private void unboxIfNecessary(SourceWriter writer, ValueType type, Fragment fragment) {
boolean boxed = false; boolean boxed = false;
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) { switch (((ValueType.Primitive) type).getKind()) {
@ -392,10 +389,10 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
} }
private interface Fragment { private interface Fragment {
void render() throws IOException; void render();
} }
private interface MemberRenderer<T extends MemberReader> { private interface MemberRenderer<T extends MemberReader> {
void render(T member) throws IOException; void render(T member);
} }
} }

View File

@ -23,7 +23,6 @@ import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.rendering.RenderingUtil; import org.teavm.backend.javascript.rendering.RenderingUtil;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
@ -36,7 +35,7 @@ import org.teavm.model.MethodReference;
public class ClassLoaderNativeGenerator implements Injector { public class ClassLoaderNativeGenerator implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "supplyResources": case "supplyResources":
generateSupplyResources(context); generateSupplyResources(context);
@ -44,7 +43,7 @@ public class ClassLoaderNativeGenerator implements Injector {
} }
} }
private void generateSupplyResources(InjectorContext context) throws IOException { private void generateSupplyResources(InjectorContext context) {
SourceWriter writer = context.getWriter(); SourceWriter writer = context.getWriter();
writer.append("{").indent(); writer.append("{").indent();
@ -69,7 +68,7 @@ public class ClassLoaderNativeGenerator implements Injector {
} }
first = false; first = false;
writer.newLine(); writer.newLine();
byte[] dataBytes = Base64Impl.encode(IOUtils.toByteArray(new BufferedInputStream(input)), true); byte[] dataBytes = Base64Impl.encode(new BufferedInputStream(input).readAllBytes(), true);
char[] dataChars = new char[dataBytes.length]; char[] dataChars = new char[dataBytes.length];
for (int i = 0; i < dataBytes.length; ++i) { for (int i = 0; i < dataBytes.length; ++i) {
dataChars[i] = (char) dataBytes[i]; dataChars[i] = (char) dataBytes[i];
@ -77,6 +76,8 @@ public class ClassLoaderNativeGenerator implements Injector {
RenderingUtil.writeString(writer, resource); RenderingUtil.writeString(writer, resource);
writer.append(':').ws(); writer.append(':').ws();
RenderingUtil.writeString(writer, new String(dataChars)); RenderingUtil.writeString(writer, new String(dataChars));
} catch (IOException e) {
throw new RuntimeException(e);
} }
} }

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public class DoubleGenerator implements Injector { public class DoubleGenerator implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
if (methodRef.getName().equals("doubleEqualsJs")) { if (methodRef.getName().equals("doubleEqualsJs")) {
context.getWriter().appendFunction("$rt_equalDoubles").append("("); context.getWriter().appendFunction("$rt_equalDoubles").append("(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public class IntegerNativeGenerator implements Injector { public class IntegerNativeGenerator implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "divideUnsigned": case "divideUnsigned":
generateRuntimeCall(context, "$rt_udiv"); generateRuntimeCall(context, "$rt_udiv");
@ -37,7 +36,7 @@ public class IntegerNativeGenerator implements Injector {
} }
private void generateRuntimeCall(InjectorContext context, String name) throws IOException { private void generateRuntimeCall(InjectorContext context, String name) {
context.getWriter().appendFunction(name).append("("); context.getWriter().appendFunction(name).append("(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
context.getWriter().append(",").ws(); context.getWriter().append(",").ws();

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -23,7 +22,7 @@ import org.teavm.model.MethodReference;
public class LongNativeGenerator implements Generator { public class LongNativeGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "compare": case "compare":
generateRuntimeCall(context, writer, "Long_compare"); generateRuntimeCall(context, writer, "Long_compare");
@ -40,7 +39,7 @@ public class LongNativeGenerator implements Generator {
} }
} }
private void generateRuntimeCall(GeneratorContext context, SourceWriter writer, String name) throws IOException { private void generateRuntimeCall(GeneratorContext context, SourceWriter writer, String name) {
writer.append("return ").appendFunction(name).append("(").append(context.getParameterName(1)) writer.append("return ").appendFunction(name).append("(").append(context.getParameterName(1))
.append(",").ws() .append(",").ws()
.append(context.getParameterName(2)).append(");").softNewLine(); .append(context.getParameterName(2)).append(");").softNewLine();

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -23,7 +22,7 @@ import org.teavm.model.MethodReference;
public class MathNativeGenerator implements Generator { public class MathNativeGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
String name = methodRef.getName(); String name = methodRef.getName();
if (name.endsWith("Impl")) { if (name.endsWith("Impl")) {
name = name.substring(0, name.length() - 4); name = name.substring(0, name.length() - 4);
@ -34,8 +33,7 @@ public class MathNativeGenerator implements Generator {
function(context, writer, name, methodRef.parameterCount()); function(context, writer, name, methodRef.parameterCount());
} }
private void function(GeneratorContext context, SourceWriter writer, String name, int paramCount) private void function(GeneratorContext context, SourceWriter writer, String name, int paramCount) {
throws IOException {
writer.append("return ").append("$rt_globals.Math").append(".").append(name).append("("); writer.append("return ").append("$rt_globals.Math").append(".").append(name).append("(");
for (int i = 0; i < paramCount; ++i) { for (int i = 0; i < paramCount; ++i) {
if (i > 0) { if (i > 0) {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -26,12 +25,12 @@ import org.teavm.model.MethodReference;
public class SystemNativeGenerator implements Generator { public class SystemNativeGenerator implements Generator {
private JavaScriptTemplate template; private JavaScriptTemplate template;
public SystemNativeGenerator(JavaScriptTemplateFactory templateFactory) throws IOException { public SystemNativeGenerator(JavaScriptTemplateFactory templateFactory) {
template = templateFactory.createFromResource("org/teavm/classlib/java/lang/System.js"); template = templateFactory.createFromResource("org/teavm/classlib/java/lang/System.js");
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
var fragment = template.builder(methodRef.getName()).withContext(context).build(); var fragment = template.builder(methodRef.getName()).withContext(context).build();
fragment.write(writer, 0); fragment.write(writer, 0);
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.classlib.java.lang.reflect; package org.teavm.classlib.java.lang.reflect;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -26,12 +25,12 @@ import org.teavm.model.MethodReference;
public class ArrayNativeGenerator implements Generator { public class ArrayNativeGenerator implements Generator {
private JavaScriptTemplate template; private JavaScriptTemplate template;
public ArrayNativeGenerator(JavaScriptTemplateFactory templateFactory) throws IOException { public ArrayNativeGenerator(JavaScriptTemplateFactory templateFactory) {
template = templateFactory.createFromResource("org/teavm/classlib/java/lang/reflect/Array.js"); template = templateFactory.createFromResource("org/teavm/classlib/java/lang/reflect/Array.js");
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0); template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
} }
} }

View File

@ -458,58 +458,55 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
for (var entry : methodInjectors.entrySet()) { for (var entry : methodInjectors.entrySet()) {
renderingContext.addInjector(entry.getKey(), entry.getValue()); renderingContext.addInjector(entry.getKey(), entry.getValue());
} }
try {
printWrapperStart(sourceWriter);
for (RendererListener listener : rendererListeners) { printWrapperStart(sourceWriter);
listener.begin(renderer, target);
}
int start = sourceWriter.getOffset();
renderer.prepare(clsNodes); for (RendererListener listener : rendererListeners) {
runtimeRenderer.renderRuntime(); listener.begin(renderer, target);
sourceWriter.append("var ").append(renderer.getNaming().getScopeName()).ws().append("=").ws()
.append("Object.create(null);").newLine();
if (!renderer.render(clsNodes)) {
return;
}
runtimeRenderer.renderHandWrittenRuntime("array.js");
renderer.renderStringPool();
renderer.renderStringConstants();
renderer.renderCompatibilityStubs();
if (renderer.isLongLibraryUsed()) {
runtimeRenderer.renderHandWrittenRuntime("long.js");
}
if (renderer.isThreadLibraryUsed()) {
runtimeRenderer.renderHandWrittenRuntime("thread.js");
} else {
runtimeRenderer.renderHandWrittenRuntime("simpleThread.js");
}
for (var entry : controller.getEntryPoints().entrySet()) {
sourceWriter.append("$rt_exports.").append(entry.getKey()).ws().append("=").ws();
var ref = entry.getValue().getMethod();
sourceWriter.appendFunction("$rt_mainStarter").append("(").appendMethodBody(ref);
sourceWriter.append(");").newLine();
sourceWriter.append("$rt_exports.").append(entry.getKey()).append(".").append("javaException")
.ws().append("=").ws().appendFunction("$rt_javaException").append(";").newLine();
}
for (var listener : rendererListeners) {
listener.complete();
}
printWrapperEnd(sourceWriter);
int totalSize = sourceWriter.getOffset() - start;
printStats(renderer, totalSize);
} catch (IOException e) {
throw new RenderingException("IO Error occurred", e);
} }
int start = sourceWriter.getOffset();
renderer.prepare(clsNodes);
runtimeRenderer.renderRuntime();
sourceWriter.append("var ").append(renderer.getNaming().getScopeName()).ws().append("=").ws()
.append("Object.create(null);").newLine();
if (!renderer.render(clsNodes)) {
return;
}
runtimeRenderer.renderHandWrittenRuntime("array.js");
renderer.renderStringPool();
renderer.renderStringConstants();
renderer.renderCompatibilityStubs();
if (renderer.isLongLibraryUsed()) {
runtimeRenderer.renderHandWrittenRuntime("long.js");
}
if (renderer.isThreadLibraryUsed()) {
runtimeRenderer.renderHandWrittenRuntime("thread.js");
} else {
runtimeRenderer.renderHandWrittenRuntime("simpleThread.js");
}
for (var entry : controller.getEntryPoints().entrySet()) {
sourceWriter.append("$rt_exports.").append(entry.getKey()).ws().append("=").ws();
var ref = entry.getValue().getMethod();
sourceWriter.appendFunction("$rt_mainStarter").append("(").appendMethodBody(ref);
sourceWriter.append(");").newLine();
sourceWriter.append("$rt_exports.").append(entry.getKey()).append(".").append("javaException")
.ws().append("=").ws().appendFunction("$rt_javaException").append(";").newLine();
}
for (var listener : rendererListeners) {
listener.complete();
}
printWrapperEnd(sourceWriter);
int totalSize = sourceWriter.getOffset() - start;
printStats(renderer, totalSize);
} }
private void printWrapperStart(SourceWriter writer) throws IOException { private void printWrapperStart(SourceWriter writer) {
writer.append("\"use strict\";").newLine(); writer.append("\"use strict\";").newLine();
printUmdStart(writer); printUmdStart(writer);
writer.append("function($rt_globals,").ws().append("$rt_exports"); writer.append("function($rt_globals,").ws().append("$rt_exports");
@ -523,7 +520,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
return importedModules.get(name); return importedModules.get(name);
} }
private void printUmdStart(SourceWriter writer) throws IOException { private void printUmdStart(SourceWriter writer) {
writer.append("(function(root,").ws().append("module)").appendBlockStart(); writer.append("(function(root,").ws().append("module)").appendBlockStart();
writer.appendIf().append("typeof define").ws().append("===").ws().append("'function'") writer.appendIf().append("typeof define").ws().append("===").ws().append("'function'")
.ws().append("&&").ws().append("define.amd)").appendBlockStart(); .ws().append("&&").ws().append("define.amd)").appendBlockStart();
@ -562,7 +559,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
.ws(); .ws();
} }
private void printWrapperEnd(SourceWriter writer) throws IOException { private void printWrapperEnd(SourceWriter writer) {
writer.outdent().append("}));").newLine(); writer.outdent().append("}));").newLine();
} }

View File

@ -36,9 +36,11 @@ public final class AstUtil {
return factory.parse(string, null, 0); return factory.parse(string, null, 0);
} }
public static AstNode parseFromResources(ClassLoader classLoader, String path) throws IOException { public static AstNode parseFromResources(ClassLoader classLoader, String path) {
try (var input = classLoader.getResourceAsStream(path)) { try (var input = classLoader.getResourceAsStream(path)) {
return parse(new String(input.readAllBytes(), StandardCharsets.UTF_8)); return parse(new String(input.readAllBytes(), StandardCharsets.UTF_8));
} catch (IOException e) {
throw new RuntimeException(e);
} }
} }
} }

View File

@ -42,39 +42,43 @@ public class SourceWriter implements Appendable, LocationProvider {
this.minified = minified; this.minified = minified;
} }
public SourceWriter append(String value) throws IOException { public SourceWriter append(String value) {
append((CharSequence) value); append((CharSequence) value);
return this; return this;
} }
public SourceWriter appendBlockStart() throws IOException { public SourceWriter appendBlockStart() {
return ws().append("{").indent().softNewLine(); return ws().append("{").indent().softNewLine();
} }
public SourceWriter appendBlockEnd() throws IOException { public SourceWriter appendBlockEnd() {
return outdent().append("}").softNewLine(); return outdent().append("}").softNewLine();
} }
public SourceWriter appendIf() throws IOException { public SourceWriter appendIf() {
return append("if").ws().append("("); return append("if").ws().append("(");
} }
public SourceWriter appendElseIf() throws IOException { public SourceWriter appendElseIf() {
return outdent().append("}").ws().append("else ").appendIf(); return outdent().append("}").ws().append("else ").appendIf();
} }
public SourceWriter appendElse() throws IOException { public SourceWriter appendElse() {
return outdent().append("}").ws().append("else").appendBlockStart(); return outdent().append("}").ws().append("else").appendBlockStart();
} }
public SourceWriter append(int value) throws IOException { public SourceWriter append(int value) {
return append(String.valueOf(value)); return append(String.valueOf(value));
} }
@Override @Override
public SourceWriter append(char value) throws IOException { public SourceWriter append(char value) {
appendIndent(); appendIndent();
innerWriter.append(value); try {
innerWriter.append(value);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (value == '\n') { if (value == '\n') {
newLine(); newLine();
} else { } else {
@ -85,13 +89,13 @@ public class SourceWriter implements Appendable, LocationProvider {
} }
@Override @Override
public SourceWriter append(CharSequence csq) throws IOException { public SourceWriter append(CharSequence csq) {
append(csq, 0, csq.length()); append(csq, 0, csq.length());
return this; return this;
} }
@Override @Override
public SourceWriter append(CharSequence csq, int start, int end) throws IOException { public SourceWriter append(CharSequence csq, int start, int end) {
int last = start; int last = start;
for (int i = start; i < end; ++i) { for (int i = start; i < end; ++i) {
if (csq.charAt(i) == '\n') { if (csq.charAt(i) == '\n') {
@ -104,65 +108,69 @@ public class SourceWriter implements Appendable, LocationProvider {
return this; return this;
} }
private void appendSingleLine(CharSequence csq, int start, int end) throws IOException { private void appendSingleLine(CharSequence csq, int start, int end) {
if (start == end) { if (start == end) {
return; return;
} }
appendIndent(); appendIndent();
column += end - start; column += end - start;
offset += end - start; offset += end - start;
innerWriter.append(csq, start, end); try {
innerWriter.append(csq, start, end);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
public SourceWriter appendClass(String cls) throws IOException { public SourceWriter appendClass(String cls) {
return appendName(naming.getNameFor(cls)); return appendName(naming.getNameFor(cls));
} }
public SourceWriter appendClass(Class<?> cls) throws IOException { public SourceWriter appendClass(Class<?> cls) {
return appendClass(cls.getName()); return appendClass(cls.getName());
} }
public SourceWriter appendField(FieldReference field) throws IOException { public SourceWriter appendField(FieldReference field) {
return append(naming.getNameFor(field)); return append(naming.getNameFor(field));
} }
public SourceWriter appendStaticField(FieldReference field) throws IOException { public SourceWriter appendStaticField(FieldReference field) {
return appendName(naming.getFullNameFor(field)); return appendName(naming.getFullNameFor(field));
} }
public SourceWriter appendMethod(MethodDescriptor method) throws IOException { public SourceWriter appendMethod(MethodDescriptor method) {
return append(naming.getNameFor(method)); return append(naming.getNameFor(method));
} }
public SourceWriter appendMethod(String name, Class<?>... params) throws IOException { public SourceWriter appendMethod(String name, Class<?>... params) {
return append(naming.getNameFor(new MethodDescriptor(name, params))); return append(naming.getNameFor(new MethodDescriptor(name, params)));
} }
public SourceWriter appendMethodBody(MethodReference method) throws IOException { public SourceWriter appendMethodBody(MethodReference method) {
return appendName(naming.getFullNameFor(method)); return appendName(naming.getFullNameFor(method));
} }
public SourceWriter appendMethodBody(String className, String name, ValueType... params) throws IOException { public SourceWriter appendMethodBody(String className, String name, ValueType... params) {
return appendMethodBody(new MethodReference(className, new MethodDescriptor(name, params))); return appendMethodBody(new MethodReference(className, new MethodDescriptor(name, params)));
} }
public SourceWriter appendMethodBody(Class<?> cls, String name, Class<?>... params) throws IOException { public SourceWriter appendMethodBody(Class<?> cls, String name, Class<?>... params) {
return appendMethodBody(new MethodReference(cls, name, params)); return appendMethodBody(new MethodReference(cls, name, params));
} }
public SourceWriter appendFunction(String name) throws IOException { public SourceWriter appendFunction(String name) {
return append(naming.getNameForFunction(name)); return append(naming.getNameForFunction(name));
} }
public SourceWriter appendInit(MethodReference method) throws IOException { public SourceWriter appendInit(MethodReference method) {
return appendName(naming.getNameForInit(method)); return appendName(naming.getNameForInit(method));
} }
public SourceWriter appendClassInit(String className) throws IOException { public SourceWriter appendClassInit(String className) {
return appendName(naming.getNameForClassInit(className)); return appendName(naming.getNameForClassInit(className));
} }
private SourceWriter appendName(ScopedName name) throws IOException { private SourceWriter appendName(ScopedName name) {
if (name.scoped) { if (name.scoped) {
append(naming.getScopeName()).append("."); append(naming.getScopeName()).append(".");
} }
@ -170,22 +178,30 @@ public class SourceWriter implements Appendable, LocationProvider {
return this; return this;
} }
private void appendIndent() throws IOException { private void appendIndent() {
if (minified) { if (minified) {
return; return;
} }
if (lineStart) { if (lineStart) {
for (int i = 0; i < indentSize; ++i) { try {
innerWriter.append(" "); for (int i = 0; i < indentSize; ++i) {
column += 4; innerWriter.append(" ");
offset += 4; column += 4;
offset += 4;
}
lineStart = false;
} catch (IOException e) {
throw new RuntimeException(e);
} }
lineStart = false;
} }
} }
public SourceWriter newLine() throws IOException { public SourceWriter newLine() {
innerWriter.append('\n'); try {
innerWriter.append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
column = 0; column = 0;
++line; ++line;
++offset; ++offset;
@ -193,12 +209,16 @@ public class SourceWriter implements Appendable, LocationProvider {
return this; return this;
} }
public SourceWriter ws() throws IOException { public SourceWriter ws() {
if (column >= lineWidth) { if (column >= lineWidth) {
newLine(); newLine();
} else { } else {
if (!minified) { if (!minified) {
innerWriter.append(' '); try {
innerWriter.append(' ');
} catch (IOException e) {
throw new RuntimeException(e);
}
column++; column++;
offset++; offset++;
} }
@ -206,16 +226,20 @@ public class SourceWriter implements Appendable, LocationProvider {
return this; return this;
} }
public SourceWriter tokenBoundary() throws IOException { public SourceWriter tokenBoundary() {
if (column >= lineWidth) { if (column >= lineWidth) {
newLine(); newLine();
} }
return this; return this;
} }
public SourceWriter softNewLine() throws IOException { public SourceWriter softNewLine() {
if (!minified) { if (!minified) {
innerWriter.append('\n'); try {
innerWriter.append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
column = 0; column = 0;
++offset; ++offset;
++line; ++line;

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.intrinsics.ref; package org.teavm.backend.javascript.intrinsics.ref;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -27,7 +26,7 @@ public class ReferenceQueueGenerator implements Generator {
private JavaScriptTemplate template; private JavaScriptTemplate template;
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
ensureTemplate(context); ensureTemplate(context);
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "<init>": case "<init>":
@ -39,7 +38,7 @@ public class ReferenceQueueGenerator implements Generator {
} }
} }
private void ensureTemplate(GeneratorContext context) throws IOException { private void ensureTemplate(GeneratorContext context) {
if (template == null) { if (template == null) {
template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource()) template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource())
.createFromResource("org/teavm/classlib/java/lang/ref/ReferenceQueue.js"); .createFromResource("org/teavm/classlib/java/lang/ref/ReferenceQueue.js");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.intrinsics.ref; package org.teavm.backend.javascript.intrinsics.ref;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -27,15 +26,11 @@ public class WeakReferenceGenerator implements Generator {
private JavaScriptTemplate template; private JavaScriptTemplate template;
public WeakReferenceGenerator(JavaScriptTemplateFactory templateFactory) { public WeakReferenceGenerator(JavaScriptTemplateFactory templateFactory) {
try { template = templateFactory.createFromResource("org/teavm/classlib/java/lang/ref/WeakReference.js");
template = templateFactory.createFromResource("org/teavm/classlib/java/lang/ref/WeakReference.js");
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "<init>": case "<init>":
template.builder("init").withContext(context).build().write(writer, 0); template.builder("init").withContext(context).build().write(writer, 0);

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.rendering; package org.teavm.backend.javascript.rendering;
import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -155,19 +154,19 @@ public class AstWriter {
}); });
} }
public void print(Object node) throws IOException { public void print(Object node) {
print((AstNode) node); print((AstNode) node);
} }
public void print(Object node, int precedence) throws IOException { public void print(Object node, int precedence) {
print((AstNode) node, precedence); print((AstNode) node, precedence);
} }
public void print(AstNode node) throws IOException { public void print(AstNode node) {
print(node, PRECEDENCE_COMMA); print(node, PRECEDENCE_COMMA);
} }
public void print(AstNode node, int precedence) throws IOException { public void print(AstNode node, int precedence) {
switch (node.getType()) { switch (node.getType()) {
case Token.SCRIPT: case Token.SCRIPT:
print((AstRoot) node); print((AstRoot) node);
@ -305,14 +304,14 @@ public class AstWriter {
} }
} }
private void print(AstRoot node) throws IOException { private void print(AstRoot node) {
for (Node child : node) { for (Node child : node) {
print((AstNode) child); print((AstNode) child);
writer.softNewLine(); writer.softNewLine();
} }
} }
private void print(Block node) throws IOException { private void print(Block node) {
writer.append('{').softNewLine().indent(); writer.append('{').softNewLine().indent();
for (Node child = node.getFirstChild(); child != null; child = child.getNext()) { for (Node child = node.getFirstChild(); child != null; child = child.getNext()) {
print((AstNode) child); print((AstNode) child);
@ -321,7 +320,7 @@ public class AstWriter {
writer.outdent().append('}'); writer.outdent().append('}');
} }
private void print(Scope node) throws IOException { private void print(Scope node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append('{').softNewLine().indent(); writer.append('{').softNewLine().indent();
for (Node child = node.getFirstChild(); child != null; child = child.getNext()) { for (Node child = node.getFirstChild(); child != null; child = child.getNext()) {
@ -332,14 +331,14 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(LabeledStatement node) throws IOException { private void print(LabeledStatement node) {
for (Label label : node.getLabels()) { for (Label label : node.getLabels()) {
writer.append(label.getName()).append(':').ws(); writer.append(label.getName()).append(':').ws();
} }
print(node.getStatement()); print(node.getStatement());
} }
private void print(BreakStatement node) throws IOException { private void print(BreakStatement node) {
writer.append("break"); writer.append("break");
if (node.getBreakLabel() != null) { if (node.getBreakLabel() != null) {
writer.append(' ').append(node.getBreakLabel().getString()); writer.append(' ').append(node.getBreakLabel().getString());
@ -347,7 +346,7 @@ public class AstWriter {
writer.append(';'); writer.append(';');
} }
private void print(ContinueStatement node) throws IOException { private void print(ContinueStatement node) {
writer.append("continue"); writer.append("continue");
if (node.getLabel() != null) { if (node.getLabel() != null) {
writer.append(' ').append(node.getLabel().getString()); writer.append(' ').append(node.getLabel().getString());
@ -355,7 +354,7 @@ public class AstWriter {
writer.append(';'); writer.append(';');
} }
private void print(ReturnStatement node) throws IOException { private void print(ReturnStatement node) {
writer.append("return"); writer.append("return");
if (node.getReturnValue() != null) { if (node.getReturnValue() != null) {
writer.append(' '); writer.append(' ');
@ -364,13 +363,13 @@ public class AstWriter {
writer.append(';'); writer.append(';');
} }
private void print(ThrowStatement node) throws IOException { private void print(ThrowStatement node) {
writer.append("throw "); writer.append("throw ");
print(node.getExpression()); print(node.getExpression());
writer.append(';'); writer.append(';');
} }
private void print(DoLoop node) throws IOException { private void print(DoLoop node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("do ").ws(); writer.append("do ").ws();
print(node.getBody()); print(node.getBody());
@ -380,7 +379,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(ForInLoop node) throws IOException { private void print(ForInLoop node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("for"); writer.append("for");
if (node.isForEach()) { if (node.isForEach()) {
@ -395,7 +394,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(ForLoop node) throws IOException { private void print(ForLoop node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("for").ws().append('('); writer.append("for").ws().append('(');
print(node.getInitializer()); print(node.getInitializer());
@ -408,7 +407,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(WhileLoop node) throws IOException { private void print(WhileLoop node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("while").ws().append('('); writer.append("while").ws().append('(');
print(node.getCondition()); print(node.getCondition());
@ -417,7 +416,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(IfStatement node) throws IOException { private void print(IfStatement node) {
writer.append("if").ws().append('('); writer.append("if").ws().append('(');
print(node.getCondition()); print(node.getCondition());
writer.append(')').ws(); writer.append(')').ws();
@ -428,7 +427,7 @@ public class AstWriter {
} }
} }
private void print(SwitchStatement node) throws IOException { private void print(SwitchStatement node) {
writer.append("switch").ws().append('('); writer.append("switch").ws().append('(');
print(node.getExpression()); print(node.getExpression());
writer.append(')').ws().append('{').indent().softNewLine(); writer.append(')').ws().append('{').indent().softNewLine();
@ -452,7 +451,7 @@ public class AstWriter {
writer.outdent().append('}'); writer.outdent().append('}');
} }
private void print(TryStatement node) throws IOException { private void print(TryStatement node) {
writer.append("try "); writer.append("try ");
print(node.getTryBlock()); print(node.getTryBlock());
for (CatchClause cc : node.getCatchClauses()) { for (CatchClause cc : node.getCatchClauses()) {
@ -471,7 +470,7 @@ public class AstWriter {
} }
} }
private void print(VariableDeclaration node) throws IOException { private void print(VariableDeclaration node) {
switch (node.getType()) { switch (node.getType()) {
case Token.VAR: case Token.VAR:
writer.append("var "); writer.append("var ");
@ -495,7 +494,7 @@ public class AstWriter {
} }
} }
private void print(VariableInitializer node) throws IOException { private void print(VariableInitializer node) {
print(node.getTarget()); print(node.getTarget());
if (node.getInitializer() != null) { if (node.getInitializer() != null) {
writer.ws().append('=').ws(); writer.ws().append('=').ws();
@ -503,19 +502,19 @@ public class AstWriter {
} }
} }
private void print(ExpressionStatement node) throws IOException { private void print(ExpressionStatement node) {
print(node.getExpression()); print(node.getExpression());
writer.append(';'); writer.append(';');
} }
protected void print(ElementGet node) throws IOException { protected void print(ElementGet node) {
print(node.getTarget(), PRECEDENCE_MEMBER); print(node.getTarget(), PRECEDENCE_MEMBER);
writer.append('['); writer.append('[');
print(node.getElement()); print(node.getElement());
writer.append(']'); writer.append(']');
} }
public void print(PropertyGet node) throws IOException { public void print(PropertyGet node) {
print(node.getLeft(), PRECEDENCE_MEMBER); print(node.getLeft(), PRECEDENCE_MEMBER);
writer.append('.'); writer.append('.');
var oldRootScope = rootScope; var oldRootScope = rootScope;
@ -524,7 +523,7 @@ public class AstWriter {
rootScope = oldRootScope; rootScope = oldRootScope;
} }
private void print(FunctionCall node, int precedence) throws IOException { private void print(FunctionCall node, int precedence) {
if (intrinsic(node, precedence)) { if (intrinsic(node, precedence)) {
return; return;
} }
@ -556,11 +555,11 @@ public class AstWriter {
} }
} }
protected boolean intrinsic(FunctionCall node, int precedence) throws IOException { protected boolean intrinsic(FunctionCall node, int precedence) {
return false; return false;
} }
private boolean tryJavaInvocation(FunctionCall node) throws IOException { private boolean tryJavaInvocation(FunctionCall node) {
if (!(node.getTarget() instanceof PropertyGet)) { if (!(node.getTarget() instanceof PropertyGet)) {
return false; return false;
} }
@ -593,7 +592,7 @@ public class AstWriter {
return str.substring("$$JSO$$_".length()); return str.substring("$$JSO$$_".length());
} }
private void print(ConditionalExpression node, int precedence) throws IOException { private void print(ConditionalExpression node, int precedence) {
if (precedence < PRECEDENCE_COND) { if (precedence < PRECEDENCE_COND) {
writer.append('('); writer.append('(');
} }
@ -607,7 +606,7 @@ public class AstWriter {
} }
} }
private void printList(List<? extends AstNode> nodes) throws IOException { private void printList(List<? extends AstNode> nodes) {
if (nodes == null || nodes.isEmpty()) { if (nodes == null || nodes.isEmpty()) {
return; return;
} }
@ -618,7 +617,7 @@ public class AstWriter {
} }
} }
private void print(ArrayComprehension node) throws IOException { private void print(ArrayComprehension node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("["); writer.append("[");
for (ArrayComprehensionLoop loop : node.getLoops()) { for (ArrayComprehensionLoop loop : node.getLoops()) {
@ -638,7 +637,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(GeneratorExpression node) throws IOException { private void print(GeneratorExpression node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("("); writer.append("(");
for (GeneratorExpressionLoop loop : node.getLoops()) { for (GeneratorExpressionLoop loop : node.getLoops()) {
@ -658,17 +657,17 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(NumberLiteral node) throws IOException { private void print(NumberLiteral node) {
writer.append(node.getValue()); writer.append(node.getValue());
} }
private void print(StringLiteral node) throws IOException { private void print(StringLiteral node) {
writer.append(node.getQuoteCharacter()); writer.append(node.getQuoteCharacter());
writer.append(ScriptRuntime.escapeString(node.getValue(), node.getQuoteCharacter())); writer.append(ScriptRuntime.escapeString(node.getValue(), node.getQuoteCharacter()));
writer.append(node.getQuoteCharacter()); writer.append(node.getQuoteCharacter());
} }
public void print(Name node, int precedence) throws IOException { public void print(Name node, int precedence) {
var definingScope = scopeOfId(node.getIdentifier()); var definingScope = scopeOfId(node.getIdentifier());
if (rootScope && definingScope == null) { if (rootScope && definingScope == null) {
var alias = nameMap.get(node.getIdentifier()); var alias = nameMap.get(node.getIdentifier());
@ -685,17 +684,17 @@ public class AstWriter {
} }
} }
private void print(RegExpLiteral node) throws IOException { private void print(RegExpLiteral node) {
writer.append('/').append(node.getValue()).append('/').append(node.getFlags()); writer.append('/').append(node.getValue()).append('/').append(node.getFlags());
} }
private void print(ArrayLiteral node) throws IOException { private void print(ArrayLiteral node) {
writer.append('['); writer.append('[');
printList(node.getElements()); printList(node.getElements());
writer.append(']'); writer.append(']');
} }
private void print(ObjectLiteral node) throws IOException { private void print(ObjectLiteral node) {
writer.append('{').ws(); 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));
@ -707,7 +706,7 @@ public class AstWriter {
writer.ws().append('}'); writer.ws().append('}');
} }
private void print(ObjectProperty node) throws IOException { private void print(ObjectProperty node) {
if (node.isGetterMethod()) { if (node.isGetterMethod()) {
writer.append("get "); writer.append("get ");
} else if (node.isSetterMethod()) { } else if (node.isSetterMethod()) {
@ -723,7 +722,7 @@ public class AstWriter {
print(node.getRight()); print(node.getRight());
} }
private void print(FunctionNode node) throws IOException { private void print(FunctionNode node) {
var scope = enterScope(node); var scope = enterScope(node);
var isArrow = node.getFunctionType() == FunctionNode.ARROW_FUNCTION; var isArrow = node.getFunctionType() == FunctionNode.ARROW_FUNCTION;
if (!isArrow) { if (!isArrow) {
@ -761,7 +760,7 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(LetNode node) throws IOException { private void print(LetNode node) {
var scope = enterScope(node); var scope = enterScope(node);
writer.append("let").ws().append('('); writer.append("let").ws().append('(');
printList(node.getVariables().getVariables()); printList(node.getVariables().getVariables());
@ -770,11 +769,11 @@ public class AstWriter {
leaveScope(scope); leaveScope(scope);
} }
private void print(ParenthesizedExpression node, int precedence) throws IOException { private void print(ParenthesizedExpression node, int precedence) {
print(node.getExpression(), precedence); print(node.getExpression(), precedence);
} }
private void printUnary(UnaryExpression node, int precedence) throws IOException { private void printUnary(UnaryExpression node, int precedence) {
int innerPrecedence = PRECEDENCE_PREFIX; int innerPrecedence = PRECEDENCE_PREFIX;
if (innerPrecedence > precedence) { if (innerPrecedence > precedence) {
@ -797,7 +796,7 @@ public class AstWriter {
} }
} }
private void printUnary(UpdateExpression node, int precedence) throws IOException { private void printUnary(UpdateExpression node, int precedence) {
int innerPrecedence = node.isPostfix() ? PRECEDENCE_POSTFIX : PRECEDENCE_PREFIX; int innerPrecedence = node.isPostfix() ? PRECEDENCE_POSTFIX : PRECEDENCE_PREFIX;
if (innerPrecedence > precedence) { if (innerPrecedence > precedence) {
@ -826,7 +825,7 @@ public class AstWriter {
} }
} }
private void printInfix(InfixExpression node, int precedence) throws IOException { private void printInfix(InfixExpression node, int precedence) {
int innerPrecedence = getPrecedence(node.getType()); int innerPrecedence = getPrecedence(node.getType());
if (innerPrecedence > precedence) { if (innerPrecedence > precedence) {

View File

@ -15,8 +15,6 @@
*/ */
package org.teavm.backend.javascript.rendering; package org.teavm.backend.javascript.rendering;
import java.io.IOException;
public interface NameEmitter { public interface NameEmitter {
void emit(int precedence) throws IOException; void emit(int precedence);
} }

View File

@ -17,7 +17,6 @@ package org.teavm.backend.javascript.rendering;
import com.carrotsearch.hppc.ObjectIntHashMap; import com.carrotsearch.hppc.ObjectIntHashMap;
import com.carrotsearch.hppc.ObjectIntMap; import com.carrotsearch.hppc.ObjectIntMap;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -181,48 +180,36 @@ public class Renderer implements RenderingManager {
if (context.getStringPool().isEmpty()) { if (context.getStringPool().isEmpty()) {
return; return;
} }
try { int start = writer.getOffset();
int start = writer.getOffset(); writer.appendFunction("$rt_stringPool").append("([");
writer.appendFunction("$rt_stringPool").append("(["); for (int i = 0; i < context.getStringPool().size(); ++i) {
for (int i = 0; i < context.getStringPool().size(); ++i) { if (i > 0) {
if (i > 0) { writer.append(',').ws();
writer.append(',').ws();
}
RenderingUtil.writeString(writer, context.getStringPool().get(i));
} }
writer.append("]);").newLine(); RenderingUtil.writeString(writer, context.getStringPool().get(i));
stringPoolSize = writer.getOffset() - start;
} catch (IOException e) {
throw new RenderingException("IO error", e);
} }
writer.append("]);").newLine();
stringPoolSize = writer.getOffset() - start;
} }
public void renderStringConstants() throws RenderingException { public void renderStringConstants() throws RenderingException {
try { for (PostponedFieldInitializer initializer : postponedFieldInitializers) {
for (PostponedFieldInitializer initializer : postponedFieldInitializers) { int start = writer.getOffset();
int start = writer.getOffset(); writer.appendStaticField(initializer.field).ws().append("=").ws();
writer.appendStaticField(initializer.field).ws().append("=").ws(); context.constantToString(writer, initializer.value);
context.constantToString(writer, initializer.value); writer.append(";").softNewLine();
writer.append(";").softNewLine(); int sz = writer.getOffset() - start;
int sz = writer.getOffset() - start; appendClassSize(initializer.field.getClassName(), sz);
appendClassSize(initializer.field.getClassName(), sz);
}
} catch (IOException e) {
throw new RenderingException("IO error", e);
} }
} }
public void renderCompatibilityStubs() throws RenderingException { public void renderCompatibilityStubs() throws RenderingException {
try { renderJavaStringToString();
renderJavaStringToString(); renderJavaObjectToString();
renderJavaObjectToString(); renderTeaVMClass();
renderTeaVMClass();
} catch (IOException e) {
throw new RenderingException("IO error", e);
}
} }
private void renderJavaStringToString() throws IOException { private void renderJavaStringToString() {
writer.appendClass("java.lang.String").append(".prototype.toString").ws().append("=").ws().append("()") writer.appendClass("java.lang.String").append(".prototype.toString").ws().append("=").ws().append("()")
.ws().append("=>").ws().append("{").indent().softNewLine(); .ws().append("=>").ws().append("{").indent().softNewLine();
writer.append("return ").appendFunction("$rt_ustr").append("(this);").softNewLine(); writer.append("return ").appendFunction("$rt_ustr").append("(this);").softNewLine();
@ -231,7 +218,7 @@ public class Renderer implements RenderingManager {
.appendClass("java.lang.String").append(".prototype.toString;").softNewLine(); .appendClass("java.lang.String").append(".prototype.toString;").softNewLine();
} }
private void renderJavaObjectToString() throws IOException { private void renderJavaObjectToString() {
writer.appendClass("java.lang.Object").append(".prototype.toString").ws().append("=").ws() writer.appendClass("java.lang.Object").append(".prototype.toString").ws().append("=").ws()
.append("()").ws().append("=>").ws().append("{").indent().softNewLine(); .append("()").ws().append("=>").ws().append("{").indent().softNewLine();
writer.append("return ").appendFunction("$rt_ustr").append("(") writer.append("return ").appendFunction("$rt_ustr").append("(")
@ -240,7 +227,7 @@ public class Renderer implements RenderingManager {
writer.outdent().append("};").newLine(); writer.outdent().append("};").newLine();
} }
private void renderTeaVMClass() throws IOException { private void renderTeaVMClass() {
writer.appendClass("java.lang.Object").append(".prototype.__teavm_class__").ws().append("=").ws() writer.appendClass("java.lang.Object").append(".prototype.__teavm_class__").ws().append("=").ws()
.append("function()").ws().append("{").indent().softNewLine(); .append("function()").ws().append("{").indent().softNewLine();
writer.append("return ").appendFunction("$dbg_class").append("(this);").softNewLine(); writer.append("return ").appendFunction("$dbg_class").append("(this);").softNewLine();
@ -282,52 +269,48 @@ public class Renderer implements RenderingManager {
private void renderDeclaration(PreparedClass cls) throws RenderingException { private void renderDeclaration(PreparedClass cls) throws RenderingException {
ScopedName jsName = naming.getNameFor(cls.getName()); ScopedName jsName = naming.getNameFor(cls.getName());
debugEmitter.addClass(jsName.value, cls.getName(), cls.getParentName()); debugEmitter.addClass(jsName.value, cls.getName(), cls.getParentName());
try { List<FieldHolder> nonStaticFields = new ArrayList<>();
List<FieldHolder> nonStaticFields = new ArrayList<>(); List<FieldHolder> staticFields = new ArrayList<>();
List<FieldHolder> staticFields = new ArrayList<>(); for (FieldHolder field : cls.getClassHolder().getFields()) {
for (FieldHolder field : cls.getClassHolder().getFields()) { if (field.getModifiers().contains(ElementModifier.STATIC)) {
if (field.getModifiers().contains(ElementModifier.STATIC)) { staticFields.add(field);
staticFields.add(field);
} else {
nonStaticFields.add(field);
}
}
if (nonStaticFields.isEmpty() && !cls.getClassHolder().getName().equals("java.lang.Object")) {
renderShortClassFunctionDeclaration(cls, jsName);
} else { } else {
renderFullClassFunctionDeclaration(cls, jsName, nonStaticFields); nonStaticFields.add(field);
}
}
if (nonStaticFields.isEmpty() && !cls.getClassHolder().getName().equals("java.lang.Object")) {
renderShortClassFunctionDeclaration(cls, jsName);
} else {
renderFullClassFunctionDeclaration(cls, jsName, nonStaticFields);
}
for (FieldHolder field : staticFields) {
Object value = field.getInitialValue();
if (value == null) {
value = getDefaultValue(field.getType());
}
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
if (value instanceof String) {
context.lookupString((String) value);
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
value = null;
} }
for (FieldHolder field : staticFields) { ScopedName fieldName = naming.getFullNameFor(fieldRef);
Object value = field.getInitialValue(); if (fieldName.scoped) {
if (value == null) { writer.append(naming.getScopeName()).append(".");
value = getDefaultValue(field.getType()); } else {
} writer.append("var ");
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
if (value instanceof String) {
context.lookupString((String) value);
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
value = null;
}
ScopedName fieldName = naming.getFullNameFor(fieldRef);
if (fieldName.scoped) {
writer.append(naming.getScopeName()).append(".");
} else {
writer.append("var ");
}
writer.append(fieldName.value).ws().append("=").ws();
context.constantToString(writer, value);
writer.append(";").softNewLine();
} }
} catch (IOException e) { writer.append(fieldName.value).ws().append("=").ws();
throw new RenderingException("IO error occurred", e); context.constantToString(writer, value);
writer.append(";").softNewLine();
} }
} }
private void renderFullClassFunctionDeclaration(PreparedClass cls, ScopedName jsName, private void renderFullClassFunctionDeclaration(PreparedClass cls, ScopedName jsName,
List<FieldHolder> nonStaticFields) throws IOException { List<FieldHolder> nonStaticFields) {
boolean thisAliased = false; boolean thisAliased = false;
renderFunctionDeclaration(jsName); renderFunctionDeclaration(jsName);
writer.append("()").ws().append("{").indent().softNewLine(); writer.append("()").ws().append("{").indent().softNewLine();
@ -364,7 +347,7 @@ public class Renderer implements RenderingManager {
writer.newLine(); writer.newLine();
} }
private void renderShortClassFunctionDeclaration(PreparedClass cls, ScopedName jsName) throws IOException { private void renderShortClassFunctionDeclaration(PreparedClass cls, ScopedName jsName) {
if (jsName.scoped) { if (jsName.scoped) {
writer.append(naming.getScopeName()).append("."); writer.append(naming.getScopeName()).append(".");
} else { } else {
@ -381,34 +364,31 @@ public class Renderer implements RenderingManager {
private void renderMethodBodies(PreparedClass cls) throws RenderingException { private void renderMethodBodies(PreparedClass cls) throws RenderingException {
debugEmitter.emitClass(cls.getName()); debugEmitter.emitClass(cls.getName());
try {
MethodReader clinit = classSource.get(cls.getName()).getMethod(CLINIT_METHOD);
if (clinit != null && context.isDynamicInitializer(cls.getName())) { MethodReader clinit = classSource.get(cls.getName()).getMethod(CLINIT_METHOD);
renderCallClinit(clinit, cls);
} if (clinit != null && context.isDynamicInitializer(cls.getName())) {
if (!cls.getClassHolder().hasModifier(ElementModifier.INTERFACE) renderCallClinit(clinit, cls);
&& !cls.getClassHolder().hasModifier(ElementModifier.ABSTRACT)) { }
for (PreparedMethod method : cls.getMethods()) { if (!cls.getClassHolder().hasModifier(ElementModifier.INTERFACE)
if (!method.methodHolder.getModifiers().contains(ElementModifier.STATIC)) { && !cls.getClassHolder().hasModifier(ElementModifier.ABSTRACT)) {
if (method.reference.getName().equals("<init>")) { for (PreparedMethod method : cls.getMethods()) {
renderInitializer(method); if (!method.methodHolder.getModifiers().contains(ElementModifier.STATIC)) {
} if (method.reference.getName().equals("<init>")) {
renderInitializer(method);
} }
} }
} }
for (PreparedMethod method : cls.getMethods()) {
renderBody(method);
}
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
} }
for (PreparedMethod method : cls.getMethods()) {
renderBody(method);
}
debugEmitter.emitClass(null); debugEmitter.emitClass(null);
} }
private void renderCallClinit(MethodReader clinit, PreparedClass cls) private void renderCallClinit(MethodReader clinit, PreparedClass cls) {
throws IOException {
boolean isAsync = asyncMethods.contains(clinit.getReference()); boolean isAsync = asyncMethods.contains(clinit.getReference());
ScopedName className = naming.getNameFor(cls.getName()); ScopedName className = naming.getNameFor(cls.getName());
@ -470,7 +450,7 @@ public class Renderer implements RenderingManager {
writer.newLine(); writer.newLine();
} }
private void renderEraseClinit(PreparedClass cls) throws IOException { private void renderEraseClinit(PreparedClass cls) {
writer.appendClassInit(cls.getName()).ws().append("=").ws() writer.appendClassInit(cls.getName()).ws().append("=").ws()
.appendFunction("$rt_eraseClinit").append("(") .appendFunction("$rt_eraseClinit").append("(")
.appendClass(cls.getName()).append(");").softNewLine(); .appendClass(cls.getName()).append(");").softNewLine();
@ -484,25 +464,21 @@ public class Renderer implements RenderingManager {
ClassMetadataRequirements metadataRequirements = new ClassMetadataRequirements(context.getDependencyInfo()); ClassMetadataRequirements metadataRequirements = new ClassMetadataRequirements(context.getDependencyInfo());
int start = writer.getOffset(); int start = writer.getOffset();
try {
writer.appendFunction("$rt_packages").append("([");
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, metadataRequirements);
writer.append("]);").newLine();
for (int i = 0; i < classes.size(); i += 50) { writer.appendFunction("$rt_packages").append("([");
int j = Math.min(i + 50, classes.size()); ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, metadataRequirements);
renderClassMetadataPortion(classes.subList(i, j), packageIndexes, metadataRequirements); writer.append("]);").newLine();
}
} catch (IOException e) { for (int i = 0; i < classes.size(); i += 50) {
throw new RenderingException("IO error occurred", e); int j = Math.min(i + 50, classes.size());
renderClassMetadataPortion(classes.subList(i, j), packageIndexes, metadataRequirements);
} }
metadataSize = writer.getOffset() - start; metadataSize = writer.getOffset() - start;
} }
private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes, private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes,
ClassMetadataRequirements metadataRequirements) throws IOException { ClassMetadataRequirements metadataRequirements) {
writer.appendFunction("$rt_metadata").append("(["); writer.appendFunction("$rt_metadata").append("([");
boolean first = true; boolean first = true;
for (PreparedClass cls : classes) { for (PreparedClass cls : classes) {
@ -597,7 +573,7 @@ public class Renderer implements RenderingManager {
} }
private ObjectIntMap<String> generatePackageMetadata(List<PreparedClass> classes, private ObjectIntMap<String> generatePackageMetadata(List<PreparedClass> classes,
ClassMetadataRequirements metadataRequirements) throws IOException { ClassMetadataRequirements metadataRequirements) {
PackageNode root = new PackageNode(null); PackageNode root = new PackageNode(null);
for (PreparedClass classNode : classes) { for (PreparedClass classNode : classes) {
@ -621,8 +597,7 @@ public class Renderer implements RenderingManager {
return indexes; return indexes;
} }
private int writePackageStructure(PackageNode node, int startIndex, String prefix, ObjectIntMap<String> indexes) private int writePackageStructure(PackageNode node, int startIndex, String prefix, ObjectIntMap<String> indexes) {
throws IOException {
int index = startIndex; int index = startIndex;
for (PackageNode child : node.children.values()) { for (PackageNode child : node.children.values()) {
if (index >= 0) { if (index >= 0) {
@ -738,7 +713,7 @@ public class Renderer implements RenderingManager {
return null; return null;
} }
private void renderInitializer(PreparedMethod method) throws IOException { private void renderInitializer(PreparedMethod method) {
MethodReference ref = method.reference; MethodReference ref = method.reference;
debugEmitter.emitMethod(ref.getDescriptor()); debugEmitter.emitMethod(ref.getDescriptor());
ScopedName name = naming.getNameForInit(ref); ScopedName name = naming.getNameForInit(ref);
@ -774,7 +749,7 @@ public class Renderer implements RenderingManager {
return minifying ? RenderingUtil.indexToId(index) : "var_" + index; return minifying ? RenderingUtil.indexToId(index) : "var_" + index;
} }
private void renderVirtualDeclarations(Collection<MethodReference> methods) throws IOException { private void renderVirtualDeclarations(Collection<MethodReference> methods) {
if (methods.stream().noneMatch(this::isVirtual)) { if (methods.stream().noneMatch(this::isVirtual)) {
writer.append('0'); writer.append('0');
return; return;
@ -797,14 +772,14 @@ public class Renderer implements RenderingManager {
writer.append("]"); writer.append("]");
} }
private void emitVirtualDeclaration(MethodReference ref) throws IOException { private void emitVirtualDeclaration(MethodReference ref) {
String methodName = naming.getNameFor(ref.getDescriptor()); String methodName = naming.getNameFor(ref.getDescriptor());
writer.append("\"").append(methodName).append("\""); writer.append("\"").append(methodName).append("\"");
writer.append(",").ws(); writer.append(",").ws();
emitVirtualFunctionWrapper(ref); emitVirtualFunctionWrapper(ref);
} }
private void emitVirtualFunctionWrapper(MethodReference method) throws IOException { private void emitVirtualFunctionWrapper(MethodReference method) {
if (method.parameterCount() <= 4) { if (method.parameterCount() <= 4) {
writer.appendFunction("$rt_wrapFunction" + method.parameterCount()); writer.appendFunction("$rt_wrapFunction" + method.parameterCount());
writer.append("(").appendMethodBody(method).append(")"); writer.append("(").appendMethodBody(method).append(")");
@ -834,7 +809,7 @@ public class Renderer implements RenderingManager {
writer.append(");").ws().append("}"); writer.append(");").ws().append("}");
} }
private void renderBody(PreparedMethod method) throws IOException { private void renderBody(PreparedMethod method) {
StatementRenderer statementRenderer = new StatementRenderer(context, writer); StatementRenderer statementRenderer = new StatementRenderer(context, writer);
statementRenderer.setCurrentMethod(method.node); statementRenderer.setCurrentMethod(method.node);
@ -886,7 +861,7 @@ public class Renderer implements RenderingManager {
return body instanceof ReturnStatement && ((ReturnStatement) body).getResult() == null; return body instanceof ReturnStatement && ((ReturnStatement) body).getResult() == null;
} }
private void renderFunctionDeclaration(ScopedName name) throws IOException { private void renderFunctionDeclaration(ScopedName name) {
if (name.scoped) { if (name.scoped) {
writer.append(naming.getScopeName()).append(".").append(name.value).ws().append("=").ws(); writer.append(naming.getScopeName()).append(".").append(name.value).ws().append("=").ws();
} }
@ -896,14 +871,14 @@ public class Renderer implements RenderingManager {
} }
} }
private void renderAsyncPrologue() throws IOException { private void renderAsyncPrologue() {
writer.append(context.mainLoopName()).append(":").ws().append("while").ws().append("(true)") writer.append(context.mainLoopName()).append(":").ws().append("while").ws().append("(true)")
.ws().append("{").ws(); .ws().append("{").ws();
writer.append("switch").ws().append("(").append(context.pointerName()).append(")").ws() writer.append("switch").ws().append("(").append(context.pointerName()).append(")").ws()
.append('{').softNewLine(); .append('{').softNewLine();
} }
private void renderAsyncEpilogue() throws IOException { private void renderAsyncEpilogue() {
writer.append("default:").ws().appendFunction("$rt_invalidPointer").append("();").softNewLine(); writer.append("default:").ws().appendFunction("$rt_invalidPointer").append("();").softNewLine();
writer.append("}}").softNewLine(); writer.append("}}").softNewLine();
} }
@ -922,112 +897,36 @@ public class Renderer implements RenderingManager {
} }
public void renderNative(PreparedMethod method) { public void renderNative(PreparedMethod method) {
try { this.async = method.async;
this.async = method.async; statementRenderer.setAsync(method.async);
statementRenderer.setAsync(method.async); method.generator.generate(this, writer, method.reference);
method.generator.generate(this, writer, method.reference);
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
}
} }
@Override @Override
public void visit(RegularMethodNode method) { public void visit(RegularMethodNode method) {
try { statementRenderer.setAsync(false);
statementRenderer.setAsync(false); this.async = false;
this.async = false; MethodReference ref = method.getReference();
MethodReference ref = method.getReference(); for (int i = 0; i < method.getVariables().size(); ++i) {
for (int i = 0; i < method.getVariables().size(); ++i) { debugEmitter.emitVariable(new String[] { method.getVariables().get(i).getName() },
debugEmitter.emitVariable(new String[] { method.getVariables().get(i).getName() }, statementRenderer.variableName(i));
statementRenderer.variableName(i));
}
int variableCount = 0;
for (VariableNode var : method.getVariables()) {
variableCount = Math.max(variableCount, var.getIndex() + 1);
}
TryCatchFinder tryCatchFinder = new TryCatchFinder();
method.getBody().acceptVisitor(tryCatchFinder);
boolean hasTryCatch = tryCatchFinder.tryCatchFound;
List<String> variableNames = new ArrayList<>();
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
variableNames.add(statementRenderer.variableName(i));
}
if (hasTryCatch) {
variableNames.add("$$je");
}
if (!variableNames.isEmpty()) {
writer.append("var ");
for (int i = 0; i < variableNames.size(); ++i) {
if (i > 0) {
writer.append(",").ws();
}
writer.append(variableNames.get(i));
}
writer.append(";").softNewLine();
}
statementRenderer.setEnd(true);
statementRenderer.setCurrentPart(0);
if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_ENTER_SYNC_METHOD);
writer.append("(");
appendMonitor(statementRenderer, method);
writer.append(");").softNewLine();
writer.append("try").ws().append("{").softNewLine().indent();
}
method.getBody().acceptVisitor(statementRenderer);
if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.outdent().append("}").ws().append("finally").ws().append("{").indent().softNewLine();
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_EXIT_SYNC_METHOD);
writer.append("(");
appendMonitor(statementRenderer, method);
writer.append(");").softNewLine();
writer.outdent().append("}").softNewLine();
}
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
} }
}
@Override int variableCount = 0;
public void visit(AsyncMethodNode methodNode) { for (VariableNode var : method.getVariables()) {
threadLibraryUsed = true; variableCount = Math.max(variableCount, var.getIndex() + 1);
try { }
statementRenderer.setAsync(true); TryCatchFinder tryCatchFinder = new TryCatchFinder();
this.async = true; method.getBody().acceptVisitor(tryCatchFinder);
MethodReference ref = methodNode.getReference(); boolean hasTryCatch = tryCatchFinder.tryCatchFound;
for (int i = 0; i < methodNode.getVariables().size(); ++i) { List<String> variableNames = new ArrayList<>();
debugEmitter.emitVariable(new String[] { methodNode.getVariables().get(i).getName() }, for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
statementRenderer.variableName(i)); variableNames.add(statementRenderer.variableName(i));
} }
int variableCount = 0; if (hasTryCatch) {
for (VariableNode var : methodNode.getVariables()) { variableNames.add("$$je");
variableCount = Math.max(variableCount, var.getIndex() + 1); }
} if (!variableNames.isEmpty()) {
List<String> variableNames = new ArrayList<>();
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
variableNames.add(statementRenderer.variableName(i));
}
TryCatchFinder tryCatchFinder = new TryCatchFinder();
for (AsyncMethodPart part : methodNode.getBody()) {
if (!tryCatchFinder.tryCatchFound) {
part.getStatement().acceptVisitor(tryCatchFinder);
}
}
boolean hasTryCatch = tryCatchFinder.tryCatchFound;
if (hasTryCatch) {
variableNames.add("$$je");
}
variableNames.add(context.pointerName());
variableNames.add(context.tempVarName());
writer.append("var "); writer.append("var ");
for (int i = 0; i < variableNames.size(); ++i) { for (int i = 0; i < variableNames.size(); ++i) {
if (i > 0) { if (i > 0) {
@ -1036,71 +935,134 @@ public class Renderer implements RenderingManager {
writer.append(variableNames.get(i)); writer.append(variableNames.get(i));
} }
writer.append(";").softNewLine(); writer.append(";").softNewLine();
}
int firstToSave = 0; statementRenderer.setEnd(true);
if (methodNode.getModifiers().contains(ElementModifier.STATIC)) { statementRenderer.setCurrentPart(0);
firstToSave = 1;
} if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_ENTER_SYNC_METHOD);
writer.append("(");
appendMonitor(statementRenderer, method);
writer.append(");").softNewLine();
writer.append("try").ws().append("{").softNewLine().indent();
}
method.getBody().acceptVisitor(statementRenderer);
if (method.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.outdent().append("}").ws().append("finally").ws().append("{").indent().softNewLine();
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_EXIT_SYNC_METHOD);
writer.append("(");
appendMonitor(statementRenderer, method);
writer.append(");").softNewLine();
String popName = minifying ? "l" : "pop";
String pushName = minifying ? "s" : "push";
writer.append(context.pointerName()).ws().append('=').ws().append("0;").softNewLine();
writer.append("if").ws().append("(").appendFunction("$rt_resuming").append("())").ws()
.append("{").indent().softNewLine();
writer.append("var ").append(context.threadName()).ws().append('=').ws()
.appendFunction("$rt_nativeThread").append("();").softNewLine();
writer.append(context.pointerName()).ws().append('=').ws().append(context.threadName()).append(".")
.append(popName).append("();");
for (int i = variableCount - 1; i >= firstToSave; --i) {
writer.append(statementRenderer.variableName(i)).ws().append('=').ws().append(context.threadName())
.append(".").append(popName).append("();");
}
writer.softNewLine();
writer.outdent().append("}").softNewLine(); writer.outdent().append("}").softNewLine();
}
}
if (methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) { @Override
writer.append("try").ws().append('{').indent().softNewLine(); public void visit(AsyncMethodNode methodNode) {
threadLibraryUsed = true;
statementRenderer.setAsync(true);
this.async = true;
MethodReference ref = methodNode.getReference();
for (int i = 0; i < methodNode.getVariables().size(); ++i) {
debugEmitter.emitVariable(new String[] { methodNode.getVariables().get(i).getName() },
statementRenderer.variableName(i));
}
int variableCount = 0;
for (VariableNode var : methodNode.getVariables()) {
variableCount = Math.max(variableCount, var.getIndex() + 1);
}
List<String> variableNames = new ArrayList<>();
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
variableNames.add(statementRenderer.variableName(i));
}
TryCatchFinder tryCatchFinder = new TryCatchFinder();
for (AsyncMethodPart part : methodNode.getBody()) {
if (!tryCatchFinder.tryCatchFound) {
part.getStatement().acceptVisitor(tryCatchFinder);
} }
}
renderAsyncPrologue(); boolean hasTryCatch = tryCatchFinder.tryCatchFound;
for (int i = 0; i < methodNode.getBody().size(); ++i) { if (hasTryCatch) {
writer.append("case ").append(i).append(":").indent().softNewLine(); variableNames.add("$$je");
if (i == 0 && methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) { }
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_ENTER_METHOD); variableNames.add(context.pointerName());
writer.append("("); variableNames.add(context.tempVarName());
appendMonitor(statementRenderer, methodNode); writer.append("var ");
writer.append(");").softNewLine(); for (int i = 0; i < variableNames.size(); ++i) {
statementRenderer.emitSuspendChecker(); if (i > 0) {
} writer.append(",").ws();
AsyncMethodPart part = methodNode.getBody().get(i);
statementRenderer.setEnd(true);
statementRenderer.setCurrentPart(i);
part.getStatement().acceptVisitor(statementRenderer);
writer.outdent();
} }
renderAsyncEpilogue(); writer.append(variableNames.get(i));
}
writer.append(";").softNewLine();
if (methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) { int firstToSave = 0;
writer.outdent().append("}").ws().append("finally").ws().append('{').indent().softNewLine(); if (methodNode.getModifiers().contains(ElementModifier.STATIC)) {
writer.append("if").ws().append("(!").appendFunction("$rt_suspending").append("())") firstToSave = 1;
.ws().append("{").indent().softNewLine(); }
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_EXIT_METHOD);
String popName = minifying ? "l" : "pop";
String pushName = minifying ? "s" : "push";
writer.append(context.pointerName()).ws().append('=').ws().append("0;").softNewLine();
writer.append("if").ws().append("(").appendFunction("$rt_resuming").append("())").ws()
.append("{").indent().softNewLine();
writer.append("var ").append(context.threadName()).ws().append('=').ws()
.appendFunction("$rt_nativeThread").append("();").softNewLine();
writer.append(context.pointerName()).ws().append('=').ws().append(context.threadName()).append(".")
.append(popName).append("();");
for (int i = variableCount - 1; i >= firstToSave; --i) {
writer.append(statementRenderer.variableName(i)).ws().append('=').ws().append(context.threadName())
.append(".").append(popName).append("();");
}
writer.softNewLine();
writer.outdent().append("}").softNewLine();
if (methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.append("try").ws().append('{').indent().softNewLine();
}
renderAsyncPrologue();
for (int i = 0; i < methodNode.getBody().size(); ++i) {
writer.append("case ").append(i).append(":").indent().softNewLine();
if (i == 0 && methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_ENTER_METHOD);
writer.append("("); writer.append("(");
appendMonitor(statementRenderer, methodNode); appendMonitor(statementRenderer, methodNode);
writer.append(");").softNewLine(); writer.append(");").softNewLine();
writer.outdent().append('}').softNewLine(); statementRenderer.emitSuspendChecker();
writer.outdent().append('}').softNewLine();
} }
AsyncMethodPart part = methodNode.getBody().get(i);
writer.appendFunction("$rt_nativeThread").append("().").append(pushName).append("("); statementRenderer.setEnd(true);
for (int i = firstToSave; i < variableCount; ++i) { statementRenderer.setCurrentPart(i);
writer.append(statementRenderer.variableName(i)).append(',').ws(); part.getStatement().acceptVisitor(statementRenderer);
} writer.outdent();
writer.append(context.pointerName()).append(");");
writer.softNewLine();
} catch (IOException e) {
throw new RenderingException("IO error occurred", e);
} }
renderAsyncEpilogue();
if (methodNode.getModifiers().contains(ElementModifier.SYNCHRONIZED)) {
writer.outdent().append("}").ws().append("finally").ws().append('{').indent().softNewLine();
writer.append("if").ws().append("(!").appendFunction("$rt_suspending").append("())")
.ws().append("{").indent().softNewLine();
writer.appendMethodBody(NameFrequencyEstimator.MONITOR_EXIT_METHOD);
writer.append("(");
appendMonitor(statementRenderer, methodNode);
writer.append(");").softNewLine();
writer.outdent().append('}').softNewLine();
writer.outdent().append('}').softNewLine();
}
writer.appendFunction("$rt_nativeThread").append("().").append(pushName).append("(");
for (int i = firstToSave; i < variableCount; ++i) {
writer.append(statementRenderer.variableName(i)).append(',').ws();
}
writer.append(context.pointerName()).append(");");
writer.softNewLine();
} }
@Override @Override
@ -1155,11 +1117,7 @@ public class Renderer implements RenderingManager {
@Override @Override
public void typeToClassString(SourceWriter writer, ValueType type) { public void typeToClassString(SourceWriter writer, ValueType type) {
try { context.typeToClsString(writer, type);
context.typeToClsString(writer, type);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
@Override @Override
@ -1178,7 +1136,7 @@ public class Renderer implements RenderingManager {
} }
} }
private void appendMonitor(StatementRenderer statementRenderer, MethodNode methodNode) throws IOException { private void appendMonitor(StatementRenderer statementRenderer, MethodNode methodNode) {
if (methodNode.getModifiers().contains(ElementModifier.STATIC)) { if (methodNode.getModifiers().contains(ElementModifier.STATIC)) {
writer.appendFunction("$rt_cls").append("(") writer.appendFunction("$rt_cls").append("(")
.appendClass(methodNode.getReference().getClassName()).append(")"); .appendClass(methodNode.getReference().getClassName()).append(")");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.rendering; package org.teavm.backend.javascript.rendering;
import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -222,7 +221,7 @@ public abstract class RenderingContext {
return readonlyStringPool; return readonlyStringPool;
} }
public void constantToString(SourceWriter writer, Object cst) throws IOException { public void constantToString(SourceWriter writer, Object cst) {
if (cst == null) { if (cst == null) {
writer.append("null"); writer.append("null");
} }
@ -297,7 +296,7 @@ public abstract class RenderingContext {
} }
} }
public void typeToClsString(SourceWriter writer, ValueType type) throws IOException { public void typeToClsString(SourceWriter writer, ValueType type) {
int arrayCount = 0; int arrayCount = 0;
while (type instanceof ValueType.Array) { while (type instanceof ValueType.Array) {
arrayCount++; arrayCount++;

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.rendering; package org.teavm.backend.javascript.rendering;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -45,7 +44,7 @@ public final class RenderingUtil {
return sb.toString(); return sb.toString();
} }
public static void writeString(SourceWriter writer, String s) throws IOException { public static void writeString(SourceWriter writer, String s) {
if (s.isEmpty()) { if (s.isEmpty()) {
writer.append("\"\""); writer.append("\"\"");
return; return;

View File

@ -39,15 +39,11 @@ public class RuntimeRenderer {
} }
public void renderRuntime() throws RenderingException { public void renderRuntime() throws RenderingException {
try { renderHandWrittenRuntime("runtime.js");
renderHandWrittenRuntime("runtime.js"); renderHandWrittenRuntime("intern.js");
renderHandWrittenRuntime("intern.js");
} catch (IOException e) {
throw new RenderingException("IO error", e);
}
} }
public void renderHandWrittenRuntime(String name) throws IOException { public void renderHandWrittenRuntime(String name) {
AstRoot ast = parseRuntime(name); AstRoot ast = parseRuntime(name);
ast.visit(new StringConstantElimination()); ast.visit(new StringConstantElimination());
new TemplatingAstTransformer(classSource).visit(ast); new TemplatingAstTransformer(classSource).visit(ast);
@ -56,7 +52,7 @@ public class RuntimeRenderer {
astWriter.print(ast); astWriter.print(ast);
} }
private AstRoot parseRuntime(String name) throws IOException { private AstRoot parseRuntime(String name) {
CompilerEnvirons env = new CompilerEnvirons(); CompilerEnvirons env = new CompilerEnvirons();
env.setRecoverFromErrors(true); env.setRecoverFromErrors(true);
env.setLanguageVersion(Context.VERSION_1_8); env.setLanguageVersion(Context.VERSION_1_8);
@ -66,6 +62,8 @@ public class RuntimeRenderer {
try (InputStream input = loader.getResourceAsStream("org/teavm/backend/javascript/" + name); try (InputStream input = loader.getResourceAsStream("org/teavm/backend/javascript/" + name);
Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) {
return factory.parse(reader, null, 0); return factory.parse(reader, null, 0);
} catch (IOException e) {
throw new RenderingException(e);
} }
} }
} }

View File

@ -15,10 +15,9 @@
*/ */
package org.teavm.backend.javascript.spi; package org.teavm.backend.javascript.spi;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public interface Generator { public interface Generator {
void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException; void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef);
} }

View File

@ -15,9 +15,8 @@
*/ */
package org.teavm.backend.javascript.spi; package org.teavm.backend.javascript.spi;
import java.io.IOException;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public interface Injector { public interface Injector {
void generate(InjectorContext context, MethodReference methodRef) throws IOException; void generate(InjectorContext context, MethodReference methodRef);
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.spi; package org.teavm.backend.javascript.spi;
import java.io.IOException;
import java.util.Properties; import java.util.Properties;
import org.teavm.ast.Expr; import org.teavm.ast.Expr;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
@ -37,9 +36,9 @@ public interface InjectorContext extends ServiceRepository {
Properties getProperties(); Properties getProperties();
void writeEscaped(String str) throws IOException; void writeEscaped(String str);
void writeType(ValueType type) throws IOException; void writeType(ValueType type);
void writeExpr(Expr expr); void writeExpr(Expr expr);

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.templating; package org.teavm.backend.javascript.templating;
import java.io.IOException;
import org.teavm.backend.javascript.ast.AstUtil; import org.teavm.backend.javascript.ast.AstUtil;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
@ -28,7 +27,7 @@ public class JavaScriptTemplateFactory {
this.classSource = classSource; this.classSource = classSource;
} }
public JavaScriptTemplate createFromResource(String path) throws IOException { public JavaScriptTemplate createFromResource(String path) {
return new JavaScriptTemplate(AstUtil.parseFromResources(classLoader, path), classSource); return new JavaScriptTemplate(AstUtil.parseFromResources(classLoader, path), classSource);
} }
} }

View File

@ -15,9 +15,8 @@
*/ */
package org.teavm.backend.javascript.templating; package org.teavm.backend.javascript.templating;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
public interface SourceFragment { public interface SourceFragment {
void write(SourceWriter writer, int precedence) throws IOException; void write(SourceWriter writer, int precedence);
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.backend.javascript.templating; package org.teavm.backend.javascript.templating;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.mozilla.javascript.ast.ElementGet; import org.mozilla.javascript.ast.ElementGet;
@ -56,7 +55,7 @@ public class TemplatingAstWriter extends AstWriter {
} }
@Override @Override
protected boolean intrinsic(FunctionCall node, int precedence) throws IOException { protected boolean intrinsic(FunctionCall node, int precedence) {
if (node.getTarget() instanceof Name) { if (node.getTarget() instanceof Name) {
var name = (Name) node.getTarget(); var name = (Name) node.getTarget();
if (scopeOfId(name.getIdentifier()) == null) { if (scopeOfId(name.getIdentifier()) == null) {
@ -66,7 +65,7 @@ public class TemplatingAstWriter extends AstWriter {
return super.intrinsic(node, precedence); return super.intrinsic(node, precedence);
} }
private boolean tryIntrinsicName(FunctionCall node, String name) throws IOException { private boolean tryIntrinsicName(FunctionCall node, String name) {
switch (name) { switch (name) {
case "teavm_javaClass": case "teavm_javaClass":
return writeJavaClass(node); return writeJavaClass(node);
@ -83,7 +82,7 @@ public class TemplatingAstWriter extends AstWriter {
} }
} }
private boolean writeJavaClass(FunctionCall node) throws IOException { private boolean writeJavaClass(FunctionCall node) {
if (node.getArguments().size() != 1) { if (node.getArguments().size() != 1) {
return false; return false;
} }
@ -95,7 +94,7 @@ public class TemplatingAstWriter extends AstWriter {
return true; return true;
} }
private boolean writeJavaMethod(FunctionCall node) throws IOException { private boolean writeJavaMethod(FunctionCall node) {
if (node.getArguments().size() != 2) { if (node.getArguments().size() != 2) {
return false; return false;
} }
@ -110,7 +109,7 @@ public class TemplatingAstWriter extends AstWriter {
return true; return true;
} }
private boolean writeJavaConstructor(FunctionCall node) throws IOException { private boolean writeJavaConstructor(FunctionCall node) {
if (node.getArguments().size() != 2) { if (node.getArguments().size() != 2) {
return false; return false;
} }
@ -125,7 +124,7 @@ public class TemplatingAstWriter extends AstWriter {
return true; return true;
} }
private boolean writeJavaClassInit(FunctionCall node) throws IOException { private boolean writeJavaClassInit(FunctionCall node) {
if (node.getArguments().size() != 1) { if (node.getArguments().size() != 1) {
return false; return false;
} }
@ -137,7 +136,7 @@ public class TemplatingAstWriter extends AstWriter {
return true; return true;
} }
private boolean writeFragment(FunctionCall node) throws IOException { private boolean writeFragment(FunctionCall node) {
if (node.getArguments().size() != 1) { if (node.getArguments().size() != 1) {
return false; return false;
} }
@ -151,7 +150,7 @@ public class TemplatingAstWriter extends AstWriter {
} }
@Override @Override
protected void print(ElementGet node) throws IOException { protected void print(ElementGet node) {
if (node.getElement() instanceof FunctionCall) { if (node.getElement() instanceof FunctionCall) {
var call = (FunctionCall) node.getElement(); var call = (FunctionCall) node.getElement();
if (call.getTarget() instanceof Name) { if (call.getTarget() instanceof Name) {
@ -176,7 +175,7 @@ public class TemplatingAstWriter extends AstWriter {
} }
@Override @Override
public void print(PropertyGet node) throws IOException { public void print(PropertyGet node) {
if (node.getTarget() instanceof Name) { if (node.getTarget() instanceof Name) {
var name = (Name) node.getTarget(); var name = (Name) node.getTarget();
var scope = scopeOfId(name.getIdentifier()); var scope = scopeOfId(name.getIdentifier());
@ -192,7 +191,7 @@ public class TemplatingAstWriter extends AstWriter {
super.print(node); super.print(node);
} }
private boolean writeJavaVirtualMethod(ElementGet get, FunctionCall call) throws IOException { private boolean writeJavaVirtualMethod(ElementGet get, FunctionCall call) {
var arg = call.getArguments().get(0); var arg = call.getArguments().get(0);
if (!(arg instanceof StringLiteral)) { if (!(arg instanceof StringLiteral)) {
return false; return false;
@ -203,7 +202,7 @@ public class TemplatingAstWriter extends AstWriter {
return true; return true;
} }
private boolean writeJavaField(ElementGet get, FunctionCall call) throws IOException { private boolean writeJavaField(ElementGet get, FunctionCall call) {
if (call.getArguments().size() != 2) { if (call.getArguments().size() != 2) {
return false; return false;
} }
@ -220,7 +219,7 @@ public class TemplatingAstWriter extends AstWriter {
} }
@Override @Override
public void print(Name node, int precedence) throws IOException { public void print(Name node, int precedence) {
var definingScope = scopeOfId(node.getIdentifier()); var definingScope = scopeOfId(node.getIdentifier());
if (rootScope) { if (rootScope) {
if (names != null && definingScope == scope) { if (names != null && definingScope == scope) {

View File

@ -15,16 +15,15 @@
*/ */
package org.teavm.vm.spi; package org.teavm.vm.spi;
import java.io.IOException;
import org.teavm.backend.javascript.rendering.RenderingManager; import org.teavm.backend.javascript.rendering.RenderingManager;
import org.teavm.vm.BuildTarget; import org.teavm.vm.BuildTarget;
public abstract class AbstractRendererListener implements RendererListener { public abstract class AbstractRendererListener implements RendererListener {
@Override @Override
public void begin(RenderingManager manager, BuildTarget buildTarget) throws IOException { public void begin(RenderingManager manager, BuildTarget buildTarget) {
} }
@Override @Override
public void complete() throws IOException { public void complete() {
} }
} }

View File

@ -15,12 +15,11 @@
*/ */
package org.teavm.vm.spi; package org.teavm.vm.spi;
import java.io.IOException;
import org.teavm.backend.javascript.rendering.RenderingManager; import org.teavm.backend.javascript.rendering.RenderingManager;
import org.teavm.vm.BuildTarget; import org.teavm.vm.BuildTarget;
public interface RendererListener { public interface RendererListener {
void begin(RenderingManager context, BuildTarget buildTarget) throws IOException; void begin(RenderingManager context, BuildTarget buildTarget);
void complete() throws IOException; void complete();
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.rendering.RenderingManager; import org.teavm.backend.javascript.rendering.RenderingManager;
@ -44,7 +43,7 @@ class JSAliasRenderer implements RendererListener, VirtualMethodContributor {
} }
@Override @Override
public void complete() throws IOException { public void complete() {
if (!hasClassesToExpose()) { if (!hasClassesToExpose()) {
return; return;
} }
@ -178,7 +177,7 @@ class JSAliasRenderer implements RendererListener, VirtualMethodContributor {
} }
} }
private void writeFunctor(ClassReader cls, FieldReference functorField) throws IOException { private void writeFunctor(ClassReader cls, FieldReference functorField) {
AnnotationReader implAnnot = cls.getAnnotations().get(FunctorImpl.class.getName()); AnnotationReader implAnnot = cls.getAnnotations().get(FunctorImpl.class.getName());
MethodDescriptor functorMethod = MethodDescriptor.parse(implAnnot.getValue("value").getString()); MethodDescriptor functorMethod = MethodDescriptor.parse(implAnnot.getValue("value").getString());
String alias = cls.getMethod(functorMethod).getAnnotations() String alias = cls.getMethod(functorMethod).getAnnotations()
@ -206,7 +205,7 @@ class JSAliasRenderer implements RendererListener, VirtualMethodContributor {
writer.outdent().append("};").softNewLine(); writer.outdent().append("};").softNewLine();
} }
private void appendArguments(int count) throws IOException { private void appendArguments(int count) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (i > 0) { if (i > 0) {
writer.append(',').ws(); writer.append(',').ws();

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.mozilla.javascript.Node; import org.mozilla.javascript.Node;
import org.mozilla.javascript.ast.AstNode; import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.Block; import org.mozilla.javascript.ast.Block;
@ -44,7 +43,7 @@ class JSBodyAstEmitter implements JSBodyEmitter {
} }
@Override @Override
public void emit(InjectorContext context) throws IOException { public void emit(InjectorContext context) {
var astWriter = new AstWriter(context.getWriter(), new DefaultGlobalNameWriter(context.getWriter())); var astWriter = new AstWriter(context.getWriter(), new DefaultGlobalNameWriter(context.getWriter()));
int paramIndex = 0; int paramIndex = 0;
if (!isStatic) { if (!isStatic) {
@ -148,7 +147,7 @@ class JSBodyAstEmitter implements JSBodyEmitter {
} }
@Override @Override
public void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
var astWriter = new AstWriter(writer, new DefaultGlobalNameWriter(writer)); var astWriter = new AstWriter(writer, new DefaultGlobalNameWriter(writer));
int paramIndex = 1; int paramIndex = 1;
if (!isStatic) { if (!isStatic) {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
@ -38,7 +37,7 @@ class JSBodyBloatedEmitter implements JSBodyEmitter {
} }
@Override @Override
public void emit(InjectorContext context) throws IOException { public void emit(InjectorContext context) {
emit(context.getWriter(), new EmissionStrategy() { emit(context.getWriter(), new EmissionStrategy() {
@Override @Override
public void emitArgument(int argument) { public void emitArgument(int argument) {
@ -46,28 +45,28 @@ class JSBodyBloatedEmitter implements JSBodyEmitter {
} }
@Override @Override
public void emitModule(String name) throws IOException { public void emitModule(String name) {
context.getWriter().append(context.importModule(name)); context.getWriter().append(context.importModule(name));
} }
}); });
} }
@Override @Override
public void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
emit(writer, new EmissionStrategy() { emit(writer, new EmissionStrategy() {
@Override @Override
public void emitArgument(int argument) throws IOException { public void emitArgument(int argument) {
writer.append(context.getParameterName(argument + 1)); writer.append(context.getParameterName(argument + 1));
} }
@Override @Override
public void emitModule(String name) throws IOException { public void emitModule(String name) {
writer.append(context.importModule(name)); writer.append(context.importModule(name));
} }
}); });
} }
private void emit(SourceWriter writer, EmissionStrategy strategy) throws IOException { private void emit(SourceWriter writer, EmissionStrategy strategy) {
int bodyParamCount = isStatic ? method.parameterCount() : method.parameterCount() - 1; int bodyParamCount = isStatic ? method.parameterCount() : method.parameterCount() - 1;
writer.append("if (!").appendMethodBody(method).append(".$native)").ws().append('{').indent().newLine(); writer.append("if (!").appendMethodBody(method).append(".$native)").ws().append('{').indent().newLine();
@ -151,8 +150,8 @@ class JSBodyBloatedEmitter implements JSBodyEmitter {
} }
interface EmissionStrategy { interface EmissionStrategy {
void emitArgument(int argument) throws IOException; void emitArgument(int argument);
void emitModule(String name) throws IOException; void emitModule(String name);
} }
} }

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
interface JSBodyEmitter { interface JSBodyEmitter {
void emit(InjectorContext context) throws IOException; void emit(InjectorContext context);
void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException; void emit(GeneratorContext context, SourceWriter writer, MethodReference methodRef);
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -25,14 +24,14 @@ import org.teavm.model.MethodReference;
public class JSBodyGenerator implements Injector, Generator { public class JSBodyGenerator implements Injector, Generator {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
JSBodyRepository emitterRepository = context.getService(JSBodyRepository.class); JSBodyRepository emitterRepository = context.getService(JSBodyRepository.class);
JSBodyEmitter emitter = emitterRepository.emitters.get(methodRef); JSBodyEmitter emitter = emitterRepository.emitters.get(methodRef);
emitter.emit(context); emitter.emit(context);
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
JSBodyRepository emitterRepository = context.getService(JSBodyRepository.class); JSBodyRepository emitterRepository = context.getService(JSBodyRepository.class);
JSBodyEmitter emitter = emitterRepository.emitters.get(methodRef); JSBodyEmitter emitter = emitterRepository.emitters.get(methodRef);
emitter.emit(context, writer, methodRef); emitter.emit(context, writer, methodRef);

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public class JSExceptionsGenerator implements Injector { public class JSExceptionsGenerator implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "getJavaException": case "getJavaException":
context.getWriter().appendFunction("$rt_javaException").append("("); context.getWriter().appendFunction("$rt_javaException").append("(");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -26,13 +25,12 @@ import org.teavm.model.MethodReference;
public class JSNativeGenerator implements Generator { public class JSNativeGenerator implements Generator {
private JavaScriptTemplate template; private JavaScriptTemplate template;
public JSNativeGenerator(JavaScriptTemplateFactory templateFactory) throws IOException { public JSNativeGenerator(JavaScriptTemplateFactory templateFactory) {
template = templateFactory.createFromResource("org/teavm/jso/impl/JS.js"); template = templateFactory.createFromResource("org/teavm/jso/impl/JS.js");
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
throws IOException {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "function": case "function":
template.builder("jsFunction").withContext(context).build().write(writer, 0); template.builder("jsFunction").withContext(context).build().write(writer, 0);

View File

@ -16,7 +16,6 @@
package org.teavm.jso.impl; package org.teavm.jso.impl;
import static org.teavm.backend.javascript.rendering.RenderingUtil.escapeString; import static org.teavm.backend.javascript.rendering.RenderingUtil.escapeString;
import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.teavm.ast.ConstantExpr; import org.teavm.ast.ConstantExpr;
@ -41,7 +40,7 @@ public class JSNativeInjector implements Injector, DependencyPlugin {
private Set<DependencyNode> functorParamNodes = new HashSet<>(); private Set<DependencyNode> functorParamNodes = new HashSet<>();
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
SourceWriter writer = context.getWriter(); SourceWriter writer = context.getWriter();
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "arrayData": case "arrayData":
@ -162,7 +161,7 @@ public class JSNativeInjector implements Injector, DependencyPlugin {
} }
} }
private void dataToArray(InjectorContext context, String className) throws IOException { private void dataToArray(InjectorContext context, String className) {
var writer = context.getWriter(); var writer = context.getWriter();
writer.appendFunction("$rt_wrapArray").append("(").appendFunction(className).append(",").ws(); writer.appendFunction("$rt_wrapArray").append("(").appendFunction(className).append(",").ws();
context.writeExpr(context.getArgument(0), Precedence.min()); context.writeExpr(context.getArgument(0), Precedence.min());
@ -229,7 +228,7 @@ public class JSNativeInjector implements Injector, DependencyPlugin {
} }
private void renderProperty(Expr property, InjectorContext context) throws IOException { private void renderProperty(Expr property, InjectorContext context) {
SourceWriter writer = context.getWriter(); SourceWriter writer = context.getWriter();
String name = extractPropertyName(property); String name = extractPropertyName(property);
if (name == null) { if (name == null) {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.jso.impl; package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.backend.javascript.rendering.Precedence; import org.teavm.backend.javascript.rendering.Precedence;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
@ -29,7 +28,7 @@ public class JSWrapperGenerator implements Injector, DependencyPlugin {
private DependencyNode externalClassesNode; private DependencyNode externalClassesNode;
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "directJavaToJs": case "directJavaToJs":
case "directJsToJava": case "directJsToJava":

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -41,7 +40,7 @@ public class AsyncMethodGenerator implements Generator, DependencyPlugin, Virtua
private JavaScriptTemplate template; private JavaScriptTemplate template;
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
if (template == null) { if (template == null) {
var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource()); var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource());
template = templateFactory.createFromResource("org/teavm/platform/plugin/Async.js"); template = templateFactory.createFromResource("org/teavm/platform/plugin/Async.js");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
@ -41,7 +40,7 @@ class BuildTimeResourceArray<T extends Resource> implements ResourceArray<T>, Re
} }
@Override @Override
public void write(SourceWriter writer) throws IOException { public void write(SourceWriter writer) {
writer.append('[').tokenBoundary(); writer.append('[').tokenBoundary();
for (int i = 0; i < data.size(); ++i) { for (int i = 0; i < data.size(); ++i) {
if (i > 0) { if (i > 0) {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
@ -42,7 +41,7 @@ class BuildTimeResourceMap<T extends Resource> implements ResourceMap<T>, Resour
} }
@Override @Override
public void write(SourceWriter writer) throws IOException { public void write(SourceWriter writer) {
writer.append('{'); writer.append('{');
boolean first = true; boolean first = true;
for (Map.Entry<String, T> entry : data.entrySet()) { for (Map.Entry<String, T> entry : data.entrySet()) {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.model.FieldReference; import org.teavm.model.FieldReference;
import org.teavm.platform.metadata.StaticFieldResource; import org.teavm.platform.metadata.StaticFieldResource;
@ -32,7 +31,7 @@ class BuildTimeStaticFieldResource implements StaticFieldResource, ResourceWrite
} }
@Override @Override
public void write(SourceWriter writer) throws IOException { public void write(SourceWriter writer) {
writer.appendField(field); writer.appendField(field);
} }
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -33,7 +32,7 @@ class MetadataProviderNativeGenerator implements Generator {
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(), DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
context.getClassLoader(), context.getProperties(), context); context.getClassLoader(), context.getProperties(), context);

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
@ -75,7 +74,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "asJavaClass": case "asJavaClass":
case "classFromResource": case "classFromResource":
@ -92,7 +91,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "prepareNewInstance": case "prepareNewInstance":
generatePrepareNewInstance(context, writer); generatePrepareNewInstance(context, writer);
@ -112,8 +111,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
} }
private void generateWithTemplate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) private void generateWithTemplate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
throws IOException {
if (template == null) { if (template == null) {
template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource()) template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource())
.createFromResource("org/teavm/platform/plugin/Platform.js"); .createFromResource("org/teavm/platform/plugin/Platform.js");
@ -121,7 +119,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0); template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
} }
private void generatePrepareNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { private void generatePrepareNewInstance(GeneratorContext context, SourceWriter writer) {
MethodDependencyInfo newInstanceMethod = context.getDependency().getMethod( MethodDependencyInfo newInstanceMethod = context.getDependency().getMethod(
new MethodReference(Platform.class, "newInstanceImpl", PlatformClass.class, Object.class)); new MethodReference(Platform.class, "newInstanceImpl", PlatformClass.class, Object.class));
writer.append("let c").ws().append("=").ws().append("'$$constructor$$';").softNewLine(); writer.append("let c").ws().append("=").ws().append("'$$constructor$$';").softNewLine();
@ -140,7 +138,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
} }
private void generateLookup(GeneratorContext context, SourceWriter writer) throws IOException { private void generateLookup(GeneratorContext context, SourceWriter writer) {
String param = context.getParameterName(1); String param = context.getParameterName(1);
writer.append("switch").ws().append("(").appendFunction("$rt_ustr").append("(" + param + "))") writer.append("switch").ws().append("(").appendFunction("$rt_ustr").append("(" + param + "))")
.ws().append("{").softNewLine().indent(); .ws().append("{").softNewLine().indent();
@ -153,7 +151,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
private void generateEnumConstants(GeneratorContext context, SourceWriter writer) throws IOException { private void generateEnumConstants(GeneratorContext context, SourceWriter writer) {
writer.append("let c").ws().append("=").ws().append("'$$enumConstants$$';").softNewLine(); writer.append("let c").ws().append("=").ws().append("'$$enumConstants$$';").softNewLine();
for (String clsName : context.getClassSource().getClassNames()) { for (String clsName : context.getClassSource().getClassNames()) {
ClassReader cls = context.getClassSource().get(clsName); ClassReader cls = context.getClassSource().get(clsName);
@ -184,7 +182,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
.append(");").softNewLine(); .append(");").softNewLine();
} }
private void generateAnnotations(GeneratorContext context, SourceWriter writer) throws IOException { private void generateAnnotations(GeneratorContext context, SourceWriter writer) {
writer.append("let c").ws().append("=").ws().append("'$$annotations$$';").softNewLine(); writer.append("let c").ws().append("=").ws().append("'$$annotations$$';").softNewLine();
for (String clsName : context.getClassSource().getClassNames()) { for (String clsName : context.getClassSource().getClassNames()) {
ClassReader annotCls = context.getClassSource().get(clsName + "$$__annotations__$$"); ClassReader annotCls = context.getClassSource().get(clsName + "$$__annotations__$$");

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyAgent;
@ -34,7 +33,7 @@ public class PlatformQueueGenerator implements Injector, DependencyPlugin {
} }
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
} }
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.spi.Generator; import org.teavm.backend.javascript.spi.Generator;
import org.teavm.backend.javascript.spi.GeneratorContext; import org.teavm.backend.javascript.spi.GeneratorContext;
@ -23,7 +22,7 @@ import org.teavm.model.MethodReference;
class ResourceAccessorGenerator implements Generator { class ResourceAccessorGenerator implements Generator {
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
writer.append("let result").ws().append("=").ws().append("[];").softNewLine(); writer.append("let result").ws().append("=").ws().append("[];").softNewLine();
writer.append("for").ws().append("(let key in ").append(context.getParameterName(1)).append(")").ws() writer.append("for").ws().append("(let key in ").append(context.getParameterName(1)).append(")").ws()
.append("{").indent().softNewLine(); .append("{").indent().softNewLine();

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.ast.ConstantExpr; import org.teavm.ast.ConstantExpr;
import org.teavm.ast.Expr; import org.teavm.ast.Expr;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
@ -25,7 +24,7 @@ import org.teavm.model.ValueType;
class ResourceAccessorInjector implements Injector { class ResourceAccessorInjector implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
switch (methodRef.getName()) { switch (methodRef.getName()) {
case "get": case "get":
case "getProperty": case "getProperty":
@ -102,7 +101,7 @@ class ResourceAccessorInjector implements Injector {
} }
} }
private void writePropertyAccessor(InjectorContext context, Expr property) throws IOException { private void writePropertyAccessor(InjectorContext context, Expr property) {
if (property instanceof ConstantExpr) { if (property instanceof ConstantExpr) {
String str = (String) ((ConstantExpr) property).getValue(); String str = (String) ((ConstantExpr) property).getValue();
if (str.isEmpty()) { if (str.isEmpty()) {
@ -119,7 +118,7 @@ class ResourceAccessorInjector implements Injector {
context.getWriter().append(")]"); context.getWriter().append(")]");
} }
private void writeStringExpr(InjectorContext context, Expr expr) throws IOException { private void writeStringExpr(InjectorContext context, Expr expr) {
if (expr instanceof ConstantExpr) { if (expr instanceof ConstantExpr) {
String str = (String) ((ConstantExpr) expr).getValue(); String str = (String) ((ConstantExpr) expr).getValue();
context.getWriter().append('"'); context.getWriter().append('"');

View File

@ -15,9 +15,8 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import java.io.IOException;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
public interface ResourceWriter { public interface ResourceWriter {
void write(SourceWriter writer) throws IOException; void write(SourceWriter writer);
} }

View File

@ -23,7 +23,7 @@ final class ResourceWriterHelper {
private ResourceWriterHelper() { private ResourceWriterHelper() {
} }
public static void write(SourceWriter writer, Object resource) throws IOException { public static void write(SourceWriter writer, Object resource) {
if (resource == null) { if (resource == null) {
writer.append("null"); writer.append("null");
} else { } else {

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.incremental; package org.teavm.incremental;
import java.io.IOException;
import org.teavm.backend.javascript.spi.Injector; import org.teavm.backend.javascript.spi.Injector;
import org.teavm.backend.javascript.spi.InjectorContext; import org.teavm.backend.javascript.spi.InjectorContext;
import org.teavm.model.FieldReference; import org.teavm.model.FieldReference;
@ -23,7 +22,7 @@ import org.teavm.model.MethodReference;
public class EntryPointGenerator implements Injector { public class EntryPointGenerator implements Injector {
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) {
context.getWriter().append("main.result = ("); context.getWriter().append("main.result = (");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
context.getWriter().append(").").appendField(new FieldReference("java.lang.String", "nativeString")); context.getWriter().append(").").appendField(new FieldReference("java.lang.String", "nativeString"));

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.junit; package org.teavm.junit;
import java.io.IOException;
import org.teavm.backend.javascript.TeaVMJavaScriptHost; import org.teavm.backend.javascript.TeaVMJavaScriptHost;
import org.teavm.backend.javascript.codegen.SourceWriter; import org.teavm.backend.javascript.codegen.SourceWriter;
import org.teavm.backend.javascript.rendering.RenderingManager; import org.teavm.backend.javascript.rendering.RenderingManager;
@ -51,18 +50,18 @@ class TestExceptionPlugin implements TeaVMPlugin {
RenderingManager manager; RenderingManager manager;
@Override @Override
public void begin(RenderingManager manager, BuildTarget buildTarget) throws IOException { public void begin(RenderingManager manager, BuildTarget buildTarget) {
this.manager = manager; this.manager = manager;
} }
@Override @Override
public void complete() throws IOException { public void complete() {
renderExceptionMessage(manager.getWriter()); renderExceptionMessage(manager.getWriter());
} }
}); });
} }
private void renderExceptionMessage(SourceWriter writer) throws IOException { private void renderExceptionMessage(SourceWriter writer) {
writer.appendClass("java.lang.Throwable").append(".prototype.getMessage").ws().append("=").ws() writer.appendClass("java.lang.Throwable").append(".prototype.getMessage").ws().append("=").ws()
.append("function()").ws().append("{").indent().softNewLine(); .append("function()").ws().append("{").indent().softNewLine();
writer.append("return ").appendFunction("$rt_ustr").append("(this.") writer.append("return ").appendFunction("$rt_ustr").append("(this.")