mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Refactoring. JavascriptBuilder becomes TeaVM and goes to org.teavm.vm
package, as well as some other classes go to org.teavm.vm.spi. html4j now supports generation of JavaScript that is completely compatible with bck2brwsr without altering HTML page
This commit is contained in:
parent
a1565015c8
commit
226f4c2c8a
|
@ -15,19 +15,19 @@
|
|||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
|
||||
import org.teavm.javascript.JavascriptBuilderHost;
|
||||
import org.teavm.javascript.JavascriptBuilderPlugin;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JCLPlugin implements JavascriptBuilderPlugin {
|
||||
public class JCLPlugin implements TeaVMPlugin {
|
||||
@Override
|
||||
public void install(JavascriptBuilderHost host) {
|
||||
public void install(TeaVMHost host) {
|
||||
host.add(new EnumDependencySupport());
|
||||
host.add(new EnumTransformer());
|
||||
host.add(new ClassLookupDependencySupport());
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.teavm.model.*;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class Renderer implements ExprVisitor, StatementVisitor {
|
||||
public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext {
|
||||
private static final String variableNames = "abcdefghijkmnopqrstuvwxyz";
|
||||
private NamingStrategy naming;
|
||||
private SourceWriter writer;
|
||||
|
@ -57,14 +57,17 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamingStrategy getNaming() {
|
||||
return naming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinifying() {
|
||||
return minifying;
|
||||
}
|
||||
|
@ -73,6 +76,16 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
this.minifying = minifying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListableClassHolderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public void renderRuntime() throws RenderingException {
|
||||
try {
|
||||
renderRuntimeCls();
|
||||
|
|
|
@ -15,12 +15,22 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.NamingStrategy;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface JavascriptResourceRenderer {
|
||||
void render(JavascriptBuildTarget buildTarget) throws IOException;
|
||||
public interface RenderingContext {
|
||||
NamingStrategy getNaming();
|
||||
|
||||
SourceWriter getWriter();
|
||||
|
||||
boolean isMinifying();
|
||||
|
||||
ListableClassReaderSource getClassSource();
|
||||
|
||||
ClassLoader getClassLoader();
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
@ -22,6 +22,6 @@ import java.io.OutputStream;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuildTarget {
|
||||
public interface BuildTarget {
|
||||
OutputStream createResource(String fileName) throws IOException;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -24,7 +24,7 @@ import java.io.OutputStream;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class DirectoryBuildTarget implements JavascriptBuildTarget {
|
||||
public class DirectoryBuildTarget implements BuildTarget {
|
||||
private File directory;
|
||||
|
||||
public DirectoryBuildTarget(File directory) {
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
|
@ -13,13 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.teavm.codegen.*;
|
||||
import org.teavm.common.FiniteExecutor;
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.*;
|
||||
import org.teavm.javascript.ast.ClassNode;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.model.*;
|
||||
|
@ -28,12 +29,15 @@ import org.teavm.model.util.ProgramUtils;
|
|||
import org.teavm.model.util.RegisterAllocator;
|
||||
import org.teavm.optimization.ClassSetOptimizer;
|
||||
import org.teavm.optimization.Devirtualization;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JavascriptBuilder implements JavascriptBuilderHost {
|
||||
public class TeaVM implements TeaVMHost {
|
||||
private JavascriptProcessedClassSource classSource;
|
||||
private DependencyChecker dependencyChecker;
|
||||
private FiniteExecutor executor;
|
||||
|
@ -41,12 +45,13 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
private boolean minifying = true;
|
||||
private boolean bytecodeLogging;
|
||||
private OutputStream logStream = System.out;
|
||||
private Map<String, JavascriptEntryPoint> entryPoints = new HashMap<>();
|
||||
private Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>();
|
||||
private Map<String, String> exportedClasses = new HashMap<>();
|
||||
private List<JavascriptResourceRenderer> ressourceRenderers = new ArrayList<>();
|
||||
private Map<MethodReference, Generator> methodGenerators = new HashMap<>();
|
||||
private List<RendererListener> rendererListeners = new ArrayList<>();
|
||||
private Properties properties = new Properties();
|
||||
|
||||
JavascriptBuilder(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||
TeaVM(ClassHolderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
|
||||
this.classSource = new JavascriptProcessedClassSource(classSource);
|
||||
this.classLoader = classLoader;
|
||||
dependencyChecker = new DependencyChecker(this.classSource, classLoader, executor);
|
||||
|
@ -63,16 +68,17 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
classSource.addTransformer(transformer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(JavascriptResourceRenderer resourceRenderer) {
|
||||
ressourceRenderers.add(resourceRenderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MethodReference methodRef, Generator generator) {
|
||||
methodGenerators.put(methodRef, generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(RendererListener listener) {
|
||||
rendererListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
|
@ -94,18 +100,37 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
this.bytecodeLogging = bytecodeLogging;
|
||||
}
|
||||
|
||||
public JavascriptEntryPoint entryPoint(String name, MethodReference ref) {
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties.clear();
|
||||
if (properties != null) {
|
||||
this.properties.putAll(properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return new Properties(properties);
|
||||
}
|
||||
|
||||
public TeaVMEntryPoint entryPoint(String name, MethodReference ref) {
|
||||
if (entryPoints.containsKey(name)) {
|
||||
throw new IllegalArgumentException("Entry point with public name `" + name + "' already defined " +
|
||||
"for method " + ref);
|
||||
}
|
||||
JavascriptEntryPoint entryPoint = new JavascriptEntryPoint(name, ref,
|
||||
TeaVMEntryPoint entryPoint = new TeaVMEntryPoint(name, ref,
|
||||
dependencyChecker.linkMethod(ref, DependencyStack.ROOT));
|
||||
dependencyChecker.initClass(ref.getClassName(), DependencyStack.ROOT);
|
||||
entryPoints.put(name, entryPoint);
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public TeaVMEntryPoint linkMethod(MethodReference ref) {
|
||||
TeaVMEntryPoint entryPoint = new TeaVMEntryPoint("", ref,
|
||||
dependencyChecker.linkMethod(ref, DependencyStack.ROOT));
|
||||
dependencyChecker.initClass(ref.getClassName(), DependencyStack.ROOT);
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
public void exportType(String name, String className) {
|
||||
if (exportedClasses.containsKey(name)) {
|
||||
throw new IllegalArgumentException("Class with public name `" + name + "' already defined for class " +
|
||||
|
@ -115,6 +140,10 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
exportedClasses.put(name, className);
|
||||
}
|
||||
|
||||
public void linkType(String className) {
|
||||
dependencyChecker.initClass(className, DependencyStack.ROOT);
|
||||
}
|
||||
|
||||
public ClassHolderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
|
@ -135,7 +164,7 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
dependencyChecker.checkForMissingItems();
|
||||
}
|
||||
|
||||
public void build(Appendable writer, JavascriptBuildTarget target) throws RenderingException {
|
||||
public void build(Appendable writer, BuildTarget target) throws RenderingException {
|
||||
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
||||
naming.setMinifying(minifying);
|
||||
|
@ -174,17 +203,27 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
// Just don't do anything
|
||||
}
|
||||
}
|
||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
||||
renderer.renderRuntime();
|
||||
for (Map.Entry<MethodReference, Generator> entry : methodGenerators.entrySet()) {
|
||||
decompiler.addGenerator(entry.getKey(), entry.getValue());
|
||||
}
|
||||
List<ClassNode> clsNodes = decompiler.decompile(classSet.getClassNames());
|
||||
for (ClassNode clsNode : clsNodes) {
|
||||
renderer.render(clsNode);
|
||||
}
|
||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
||||
try {
|
||||
for (Map.Entry<String, JavascriptEntryPoint> entry : entryPoints.entrySet()) {
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.begin(renderer, target);
|
||||
}
|
||||
renderer.renderRuntime();
|
||||
for (ClassNode clsNode : clsNodes) {
|
||||
ClassReader cls = classSet.get(clsNode.getName());
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.beforeClass(cls);
|
||||
}
|
||||
renderer.render(clsNode);
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.afterClass(cls);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
|
||||
sourceWriter.append(entry.getKey()).ws().append("=").ws().appendMethodBody(entry.getValue().reference)
|
||||
.append(";").softNewLine();
|
||||
}
|
||||
|
@ -192,8 +231,8 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
sourceWriter.append(entry.getKey()).ws().append("=").ws().appendClass(entry.getValue()).append(";")
|
||||
.softNewLine();
|
||||
}
|
||||
for (JavascriptResourceRenderer resourceRenderer : ressourceRenderers) {
|
||||
resourceRenderer.render(target);
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.complete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO Error occured", e);
|
||||
|
@ -350,7 +389,7 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
}
|
||||
|
||||
public void installPlugins() {
|
||||
for (JavascriptBuilderPlugin plugin : ServiceLoader.load(JavascriptBuilderPlugin.class, classLoader)) {
|
||||
for (TeaVMPlugin plugin : ServiceLoader.load(TeaVMPlugin.class, classLoader)) {
|
||||
plugin.install(this);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import org.teavm.common.FiniteExecutor;
|
||||
import org.teavm.common.SimpleFiniteExecutor;
|
||||
|
@ -23,7 +23,7 @@ import org.teavm.model.ClassHolderSource;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JavascriptBuilderFactory {
|
||||
public class TeaVMBuilder {
|
||||
ClassHolderSource classSource;
|
||||
ClassLoader classLoader;
|
||||
FiniteExecutor executor = new SimpleFiniteExecutor();
|
||||
|
@ -32,27 +32,30 @@ public class JavascriptBuilderFactory {
|
|||
return classSource;
|
||||
}
|
||||
|
||||
public void setClassSource(ClassHolderSource classSource) {
|
||||
public TeaVMBuilder setClassSource(ClassHolderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
public TeaVMBuilder setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FiniteExecutor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public void setExecutor(FiniteExecutor executor) {
|
||||
public TeaVMBuilder setExecutor(FiniteExecutor executor) {
|
||||
this.executor = executor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JavascriptBuilder create() {
|
||||
return new JavascriptBuilder(classSource, classLoader, executor);
|
||||
public TeaVM build() {
|
||||
return new TeaVM(classSource, classLoader, executor);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm;
|
||||
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -22,12 +22,12 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JavascriptEntryPoint {
|
||||
public class TeaVMEntryPoint {
|
||||
private String publicName;
|
||||
MethodReference reference;
|
||||
private MethodDependency method;
|
||||
|
||||
JavascriptEntryPoint(String publicName, MethodReference reference, MethodDependency method) {
|
||||
TeaVMEntryPoint(String publicName, MethodReference reference, MethodDependency method) {
|
||||
this.publicName = publicName;
|
||||
this.reference = reference;
|
||||
this.method = method;
|
||||
|
@ -38,7 +38,7 @@ public class JavascriptEntryPoint {
|
|||
return publicName;
|
||||
}
|
||||
|
||||
public JavascriptEntryPoint withValue(int argument, String type) {
|
||||
public TeaVMEntryPoint withValue(int argument, String type) {
|
||||
if (argument > reference.parameterCount()) {
|
||||
throw new IllegalArgumentException("Illegal argument #" + argument + " of " + reference.parameterCount());
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.vm.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public abstract class AbstractRendererListener implements RendererListener {
|
||||
@Override
|
||||
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeClass(ClassReader cls) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterClass(ClassReader cls) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() throws IOException {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.vm.spi;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface RendererListener {
|
||||
void begin(RenderingContext context, BuildTarget buildTarget) throws IOException;
|
||||
|
||||
void beforeClass(ClassReader cls) throws IOException;
|
||||
|
||||
void afterClass(ClassReader cls) throws IOException;
|
||||
|
||||
void complete() throws IOException;
|
||||
}
|
|
@ -13,8 +13,9 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm.spi;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
|
@ -24,14 +25,16 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuilderHost {
|
||||
public interface TeaVMHost {
|
||||
void add(DependencyListener dependencyListener);
|
||||
|
||||
void add(ClassHolderTransformer classTransformer);
|
||||
|
||||
void add(JavascriptResourceRenderer resourceRenderer);
|
||||
|
||||
void add(MethodReference methodRef, Generator generator);
|
||||
|
||||
void add(RendererListener listener);
|
||||
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
Properties getProperties();
|
||||
}
|
|
@ -13,12 +13,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript;
|
||||
package org.teavm.vm.spi;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface JavascriptBuilderPlugin {
|
||||
void install(JavascriptBuilderHost host);
|
||||
public interface TeaVMPlugin {
|
||||
void install(TeaVMHost host);
|
||||
}
|
|
@ -99,9 +99,6 @@
|
|||
<transformers>
|
||||
<param>org.teavm.javascript.NullPointerExceptionTransformer</param>
|
||||
</transformers>
|
||||
<additionalScripts>
|
||||
<param>org/netbeans/html/ko4j/knockout-2.2.1.js</param>
|
||||
</additionalScripts>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.html4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.Renderer;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.AbstractRendererListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class EntryPointGenerator extends AbstractRendererListener implements DependencyListener {
|
||||
private List<String> classesToLoad = new ArrayList<>();
|
||||
private SourceWriter writer;
|
||||
|
||||
public EntryPointGenerator(String classesToLoad) {
|
||||
for (String className : classesToLoad.split(",| |;")) {
|
||||
className = className.trim();
|
||||
if (!className.isEmpty()) {
|
||||
this.classesToLoad.add(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
|
||||
writer = context.getWriter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() throws IOException {
|
||||
if (classesToLoad.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
writer.append("function VM() {").softNewLine();
|
||||
writer.append("}").newLine();
|
||||
writer.append("VM.prototype.loadClass = function(className) {").softNewLine().indent();
|
||||
writer.append("switch (className) {").indent().softNewLine();
|
||||
for (String className : classesToLoad) {
|
||||
writer.append("case \"").append(Renderer.escapeString(className)).append("\": ");
|
||||
writer.appendClass(className).append(".$clinit(); break;").softNewLine();
|
||||
}
|
||||
writer.append("default: throw \"Can't load class \" + className;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
writer.append("function bck2brwsr() { return new VM(); }").newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started(DependencyChecker dependencyChecker) {
|
||||
for (String className : classesToLoad) {
|
||||
dependencyChecker.initClass(className, DependencyStack.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
||||
}
|
||||
}
|
|
@ -15,18 +15,25 @@
|
|||
*/
|
||||
package org.teavm.html4j;
|
||||
|
||||
import org.teavm.javascript.JavascriptBuilderHost;
|
||||
import org.teavm.javascript.JavascriptBuilderPlugin;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class HTML4JPlugin implements JavascriptBuilderPlugin {
|
||||
public class HTML4JPlugin implements TeaVMPlugin {
|
||||
@Override
|
||||
public void install(JavascriptBuilderHost host) {
|
||||
public void install(TeaVMHost host) {
|
||||
host.add(new JavaScriptBodyDependency());
|
||||
host.add(new JavaScriptBodyTransformer());
|
||||
host.add(new JCLHacks());
|
||||
host.add(new JavaScriptResourceInterceptor());
|
||||
EntryPointGenerator entryPointGen = new EntryPointGenerator(host.getProperties()
|
||||
.getProperty("html4j.entryPoints", ""));
|
||||
host.add((DependencyListener)entryPointGen);
|
||||
host.add((RendererListener)entryPointGen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.html4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import net.java.html.js.JavaScriptResource;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.javascript.RenderingException;
|
||||
import org.teavm.model.AnnotationReader;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.AbstractRendererListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class JavaScriptResourceInterceptor extends AbstractRendererListener {
|
||||
@Override
|
||||
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
|
||||
boolean hasOneResource = false;
|
||||
for (String className : context.getClassSource().getClassNames()) {
|
||||
ClassReader cls = context.getClassSource().get(className);
|
||||
AnnotationReader annot = cls.getAnnotations().get(JavaScriptResource.class.getName());
|
||||
if (annot == null) {
|
||||
continue;
|
||||
}
|
||||
String path = annot.getValue("value").getString();
|
||||
String packageName = className.substring(0, className.lastIndexOf('.'));
|
||||
String resourceName = packageName.replace('.', '/') + "/" + path;
|
||||
try (InputStream input = context.getClassLoader().getResourceAsStream(resourceName)) {
|
||||
if (input == null) {
|
||||
throw new RenderingException("Error processing JavaScriptResource annotation on class " +
|
||||
className + ". Resource not found: " + resourceName);
|
||||
}
|
||||
@SuppressWarnings("resource")
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(input, writer);
|
||||
writer.close();
|
||||
context.getWriter().append("// Resource " + path + " included by " + className).newLine();
|
||||
context.getWriter().append(writer.toString()).newLine().newLine();
|
||||
}
|
||||
hasOneResource = true;
|
||||
}
|
||||
if (hasOneResource) {
|
||||
context.getWriter().append("// TeaVM generated classes").newLine();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,16 +15,16 @@
|
|||
*/
|
||||
package org.teavm.javascript.ni.plugin;
|
||||
|
||||
import org.teavm.javascript.JavascriptBuilderHost;
|
||||
import org.teavm.javascript.JavascriptBuilderPlugin;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JSObjectBuilderPlugin implements JavascriptBuilderPlugin {
|
||||
public class JSObjectBuilderPlugin implements TeaVMPlugin {
|
||||
@Override
|
||||
public void install(JavascriptBuilderHost host) {
|
||||
public void install(TeaVMHost host) {
|
||||
host.add(new JSObjectClassTransformer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,14 +33,17 @@ import org.apache.maven.plugins.annotations.Parameter;
|
|||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.teavm.common.ThreadPoolFiniteExecutor;
|
||||
import org.teavm.javascript.DirectoryBuildTarget;
|
||||
import org.teavm.javascript.JavascriptBuilder;
|
||||
import org.teavm.javascript.JavascriptBuilderFactory;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.DirectoryBuildTarget;
|
||||
import org.teavm.vm.TeaVM;
|
||||
import org.teavm.vm.TeaVMBuilder;
|
||||
import org.teavm.vm.spi.AbstractRendererListener;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -61,6 +64,7 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
@Parameter(defaultValue = "${project.build.outputDirectory}")
|
||||
private File classFiles;
|
||||
|
||||
@Parameter
|
||||
private String targetFileName = "classes.js";
|
||||
|
||||
@Parameter
|
||||
|
@ -72,6 +76,9 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
@Parameter
|
||||
private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
|
||||
|
||||
@Parameter
|
||||
private Properties properties;
|
||||
|
||||
@Parameter
|
||||
private boolean mainPageIncluded;
|
||||
|
||||
|
@ -92,6 +99,10 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
this.targetDirectory = targetDirectory;
|
||||
}
|
||||
|
||||
public void setTargetFileName(String targetFileName) {
|
||||
this.targetFileName = targetFileName;
|
||||
}
|
||||
|
||||
public void setClassFiles(File classFiles) {
|
||||
this.classFiles = classFiles;
|
||||
}
|
||||
|
@ -124,6 +135,10 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
this.transformers = transformers;
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException {
|
||||
Log log = getLog();
|
||||
|
@ -131,9 +146,8 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
try {
|
||||
ClassLoader classLoader = prepareClassLoader();
|
||||
log.info("Building JavaScript file");
|
||||
JavascriptBuilderFactory builderFactory = new JavascriptBuilderFactory();
|
||||
builderFactory.setClassLoader(classLoader);
|
||||
builderFactory.setClassSource(new ClasspathClassHolderSource(classLoader));
|
||||
TeaVMBuilder vmBuilder = new TeaVMBuilder();
|
||||
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
|
||||
if (numThreads != 1) {
|
||||
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
|
||||
final ThreadPoolFiniteExecutor executor = new ThreadPoolFiniteExecutor(threads);
|
||||
|
@ -142,28 +156,30 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
executor.stop();
|
||||
}
|
||||
};
|
||||
builderFactory.setExecutor(executor);
|
||||
vmBuilder.setExecutor(executor);
|
||||
}
|
||||
JavascriptBuilder builder = builderFactory.create();
|
||||
builder.setMinifying(minifying);
|
||||
builder.setBytecodeLogging(bytecodeLogging);
|
||||
builder.installPlugins();
|
||||
TeaVM vm = vmBuilder.build();
|
||||
vm.setMinifying(minifying);
|
||||
vm.setBytecodeLogging(bytecodeLogging);
|
||||
vm.setProperties(properties);
|
||||
vm.installPlugins();
|
||||
for (ClassHolderTransformer transformer : instantiateTransformers(classLoader)) {
|
||||
builder.add(transformer);
|
||||
vm.add(transformer);
|
||||
}
|
||||
builder.prepare();
|
||||
vm.prepare();
|
||||
if (mainClass != null) {
|
||||
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf(
|
||||
ValueType.object("java.lang.String")), ValueType.VOID);
|
||||
builder.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
||||
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
||||
.withValue(1, "java.lang.String");
|
||||
}
|
||||
targetDirectory.mkdirs();
|
||||
try (FileWriter writer = new FileWriter(new File(targetDirectory, targetFileName))) {
|
||||
if (runtime == RuntimeCopyOperation.MERGED) {
|
||||
resourceToWriter("org/teavm/javascript/runtime.js", writer);
|
||||
writer.append("\n");
|
||||
vm.add(runtimeInjector);
|
||||
}
|
||||
builder.build(writer, new DirectoryBuildTarget(targetDirectory));
|
||||
builder.checkForMissingItems();
|
||||
vm.build(writer, new DirectoryBuildTarget(targetDirectory));
|
||||
vm.checkForMissingItems();
|
||||
log.info("JavaScript file successfully built");
|
||||
}
|
||||
if (runtime == RuntimeCopyOperation.SEPARATE) {
|
||||
|
@ -191,6 +207,17 @@ public class BuildJavascriptMojo extends AbstractMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private AbstractRendererListener runtimeInjector = new AbstractRendererListener() {
|
||||
@Override
|
||||
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
|
||||
@SuppressWarnings("resource")
|
||||
StringWriter writer = new StringWriter();
|
||||
resourceToWriter("org/teavm/javascript/runtime.js", writer);
|
||||
writer.close();
|
||||
context.getWriter().append(writer.toString()).newLine();
|
||||
}
|
||||
};
|
||||
|
||||
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
|
||||
throws MojoExecutionException {
|
||||
List<ClassHolderTransformer> transformerInstances = new ArrayList<>();
|
||||
|
|
|
@ -39,13 +39,13 @@ import org.apache.maven.project.MavenProject;
|
|||
import org.teavm.common.FiniteExecutor;
|
||||
import org.teavm.common.SimpleFiniteExecutor;
|
||||
import org.teavm.common.ThreadPoolFiniteExecutor;
|
||||
import org.teavm.javascript.DirectoryBuildTarget;
|
||||
import org.teavm.javascript.JavascriptBuilder;
|
||||
import org.teavm.javascript.JavascriptBuilderFactory;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||
import org.teavm.testing.JUnitTestAdapter;
|
||||
import org.teavm.testing.TestAdapter;
|
||||
import org.teavm.vm.DirectoryBuildTarget;
|
||||
import org.teavm.vm.TeaVM;
|
||||
import org.teavm.vm.TeaVMBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -311,33 +311,33 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
|
|||
|
||||
private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
|
||||
MethodReference methodRef, String targetName, FiniteExecutor executor) throws IOException {
|
||||
JavascriptBuilderFactory builderFactory = new JavascriptBuilderFactory();
|
||||
builderFactory.setClassLoader(classLoader);
|
||||
builderFactory.setClassSource(classSource);
|
||||
builderFactory.setExecutor(executor);
|
||||
JavascriptBuilder builder = builderFactory.create();
|
||||
builder.setMinifying(minifying);
|
||||
builder.installPlugins();
|
||||
TeaVM vm = new TeaVMBuilder()
|
||||
.setClassLoader(classLoader)
|
||||
.setClassSource(classSource)
|
||||
.setExecutor(executor)
|
||||
.build();
|
||||
vm.setMinifying(minifying);
|
||||
vm.installPlugins();
|
||||
for (ClassHolderTransformer transformer : transformerInstances) {
|
||||
builder.add(transformer);
|
||||
vm.add(transformer);
|
||||
}
|
||||
builder.prepare();
|
||||
vm.prepare();
|
||||
File file = new File(outputDir, targetName);
|
||||
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
|
||||
MethodReference cons = new MethodReference(methodRef.getClassName(),
|
||||
new MethodDescriptor("<init>", ValueType.VOID));
|
||||
builder.entryPoint("initInstance", cons);
|
||||
builder.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
|
||||
builder.exportType("TestClass", cons.getClassName());
|
||||
builder.build(innerWriter, new DirectoryBuildTarget(outputDir));
|
||||
if (!builder.hasMissingItems()) {
|
||||
vm.entryPoint("initInstance", cons);
|
||||
vm.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
|
||||
vm.exportType("TestClass", cons.getClassName());
|
||||
vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
|
||||
if (!vm.hasMissingItems()) {
|
||||
innerWriter.append("\n");
|
||||
innerWriter.append("\nJUnitClient.run();");
|
||||
innerWriter.close();
|
||||
} else {
|
||||
innerWriter.append("JUnitClient.reportError(\n");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
builder.showMissingItems(sb);
|
||||
vm.showMissingItems(sb);
|
||||
escapeStringLiteral(sb.toString(), innerWriter);
|
||||
innerWriter.append(");");
|
||||
getLog().warn("Error building test " + methodRef);
|
||||
|
|
Loading…
Reference in New Issue
Block a user