-
Notifications
You must be signed in to change notification settings - Fork 434
Expand file tree
/
Copy pathJavascriptBundleWriter.java
More file actions
137 lines (123 loc) · 5.18 KB
/
JavascriptBundleWriter.java
File metadata and controls
137 lines (123 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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.Collections;
import java.util.Comparator;
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);
writeProtocol(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();
List<ByteCodeClass> sorted = new ArrayList<ByteCodeClass>(classes);
Collections.sort(sorted, new Comparator<ByteCodeClass>() {
@Override
public int compare(ByteCodeClass a, ByteCodeClass b) {
int priorityDiff = bootstrapPriority(a) - bootstrapPriority(b);
if (priorityDiff != 0) {
return priorityDiff;
}
return a.getClsName().compareTo(b.getClsName());
}
});
for (ByteCodeClass cls : sorted) {
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 int bootstrapPriority(ByteCodeClass cls) {
String name = cls.getClsName();
if ("java_lang_Object".equals(name)) {
return 0;
}
if ("java_lang_Class".equals(name)) {
return 1;
}
if ("java_lang_String".equals(name)) {
return 2;
}
if ("java_lang_Throwable".equals(name)) {
return 3;
}
if (name.startsWith("java_lang_String_")) {
return 4;
}
if (name.startsWith("java_lang_")) {
return 5;
}
return 10;
}
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 writeProtocol(File outputDirectory) throws IOException {
writeResource(outputDirectory, "vm_protocol.md", "vm_protocol.md");
}
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();
}
}
}