Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ public void setIsAnnotation(boolean isAnnotation) {
private boolean finalClass;
private boolean isEnum;
private static Set<String> writableFields = new HashSet<String>();

static void cleanup() {
arrayTypes.clear();
writableFields.clear();
mainClass = null;
saveUnitTests = false;
}

/**
*
Expand Down Expand Up @@ -170,6 +177,10 @@ public void addField(ByteCodeField m) {
public String generateCSharpCode() {
return "";
}

public String generateJavascriptCode(List<ByteCodeClass> allClasses) {
return JavascriptMethodGenerator.generateClassJavascript(this, allClasses);
}

public void addWritableField(String field) {
writableFields.add(field);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ public String extension() {
return "c";
}

},
OUTPUT_TYPE_JAVASCRIPT {
@Override
public String extension() {
return "js";
}

};

public abstract String extension();
Expand Down Expand Up @@ -144,7 +151,7 @@ public static void main(String[] args) throws Exception {
}

if(args.length != 9) {
System.out.println("We accept 9 arguments output type (ios, csharp, clean), input directory, output directory, app name, package name, app dispaly name, version, type (ios/iphone/ipad) and additional frameworks");
System.out.println("We accept 9 arguments output type (ios, csharp, clean, javascript), input directory, output directory, app name, package name, app dispaly name, version, type (ios/iphone/ipad) and additional frameworks");
System.exit(1);
return;
}
Expand All @@ -163,6 +170,8 @@ public static void main(String[] args) throws Exception {
output = OutputType.OUTPUT_TYPE_CSHARP;
} else if(args[0].equalsIgnoreCase("clean")) {
output = OutputType.OUTPUT_TYPE_CLEAN;
} else if(args[0].equalsIgnoreCase("javascript")) {
output = OutputType.OUTPUT_TYPE_JAVASCRIPT;
}
String[] sourceDirectories = args[1].split(";");
File[] sources = new File[sourceDirectories.length];
Expand All @@ -189,6 +198,9 @@ public static void main(String[] args) throws Exception {
case OUTPUT_TYPE_CLEAN:
handleCleanOutput(b, sources, dest, appName);
break;
case OUTPUT_TYPE_JAVASCRIPT:
handleJavascriptOutput(b, sources, dest, appName);
break;
default:
handleDefaultOutput(b, sources, dest);
}
Expand Down Expand Up @@ -250,6 +262,18 @@ private static void handleCleanOutput(ByteCodeTranslator b, File[] sources, File
writeCmakeProject(root, srcRoot, appName);
}

private static void handleJavascriptOutput(ByteCodeTranslator b, File[] sources, File dest, String appName) throws Exception {
File root = new File(dest, "dist");
root.mkdirs();
if(verbose) {
System.out.println("Root is: " + root.getAbsolutePath());
}
File srcRoot = new File(root, appName + "-js");
srcRoot.mkdirs();
b.execute(sources, srcRoot);
Parser.writeOutput(srcRoot);
}

private static void handleIosOutput(ByteCodeTranslator b, File[] sources, File dest, String appName, String appPackageName, String appDisplayName, String appVersion, String appType, String addFrameworks) throws Exception {
File root = new File(dest, "dist");
root.mkdirs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,44 @@ public void addToConstantPool() {
public boolean isSynchronizedMethod() {
return synchronizedMethod;
}

public List<Instruction> getInstructions() {
return instructions;
}

public List<ByteCodeMethodArg> getArguments() {
return arguments;
}

public ByteCodeMethodArg getReturnType() {
return returnType;
}

public int getMaxStack() {
return maxStack;
}

public int getMaxLocals() {
return maxLocals;
}

public boolean isConstructor() {
return constructor;
}

public String getMethodIdentifier() {
StringBuilder b = new StringBuilder();
b.append(clsName).append("_");
if(methodName.equals("<init>")) {
b.append("__INIT__");
} else if(methodName.equals("<clinit>")) {
b.append("__CLINIT__");
} else {
b.append(getCMethodName());
}
appendMethodSignatureSuffixFromDesc(desc, b, new ArrayList<String>());
return b.toString();
}

private boolean hasLocalVariableWithIndex(char qualifier, int index) {
for (LocalVariable lv : localVariables) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.codename1.tools.translator;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

final class JavascriptBundleWriter {
private static final String RESOURCE_ROOT = "/javascript/";

private JavascriptBundleWriter() {
}

static void write(File outputDirectory, List<ByteCodeClass> classes) throws IOException {
writeRuntime(outputDirectory);
writeTranslatedClasses(outputDirectory, classes);
writeWorker(outputDirectory);
writeIndex(outputDirectory);
}

private static void writeRuntime(File outputDirectory) throws IOException {
writeResource(outputDirectory, "parparvm_runtime.js", "parparvm_runtime.js");
}

private static void writeTranslatedClasses(File outputDirectory, List<ByteCodeClass> classes) throws IOException {
StringBuilder out = new StringBuilder();
for (ByteCodeClass cls : classes) {
out.append(cls.generateJavascriptCode(classes)).append('\n');
}
ByteCodeClass mainClass = ByteCodeClass.getMainClass();
if (mainClass != null) {
out.append("jvm.setMain(\"").append(mainClass.getClsName()).append("\", \"")
.append(JavascriptNameUtil.methodIdentifier(mainClass.getClsName(), "main", "([Ljava/lang/String;)V"))
.append("\");\n");
}
Files.write(new File(outputDirectory, "translated_app.js").toPath(),
out.toString().getBytes(StandardCharsets.UTF_8));
}

private static void writeWorker(File outputDirectory) throws IOException {
List<String> nativeScripts = new ArrayList<String>();
File[] files = outputDirectory.listFiles();
if (files != null) {
for (File file : files) {
String name = file.getName();
if (!name.endsWith(".js")) {
continue;
}
if ("parparvm_runtime.js".equals(name) || "translated_app.js".equals(name) || "worker.js".equals(name)) {
continue;
}
nativeScripts.add(name);
}
}

StringBuilder imports = new StringBuilder();
imports.append("importScripts('parparvm_runtime.js');\n");
for (String script : nativeScripts) {
imports.append("importScripts('").append(script).append("');\n");
}
imports.append("importScripts('translated_app.js');\n");

String worker = loadResource("worker.js").replace("/*__IMPORTS__*/", imports.toString().trim());
Files.write(new File(outputDirectory, "worker.js").toPath(), worker.getBytes(StandardCharsets.UTF_8));
}

private static void writeIndex(File outputDirectory) throws IOException {
writeResource(outputDirectory, "index.html", "index.html");
}

private static void writeResource(File outputDirectory, String targetName, String resourceName) throws IOException {
Files.write(new File(outputDirectory, targetName).toPath(),
loadResource(resourceName).getBytes(StandardCharsets.UTF_8));
}

private static String loadResource(String resourceName) throws IOException {
InputStream input = JavascriptBundleWriter.class.getResourceAsStream(RESOURCE_ROOT + resourceName);
if (input == null) {
throw new IOException("Missing javascript backend resource " + resourceName);
}
try {
byte[] data = new byte[8192];
StringBuilder out = new StringBuilder();
int len;
while ((len = input.read(data)) > -1) {
out.append(new String(data, 0, len, StandardCharsets.UTF_8));
}
return out.toString();
} finally {
input.close();
}
}
}
Loading
Loading