mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
JS: rewrite more natives with templates, get rid of runtime aliases in minification mode
This commit is contained in:
parent
2756fe4384
commit
32ee8943c1
|
@ -16,10 +16,10 @@
|
|||
package org.teavm.classlib.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -28,39 +28,31 @@ public class ServiceLoaderJSSupport implements Generator {
|
|||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
ServiceLoaderInformation information = context.getService(ServiceLoaderInformation.class);
|
||||
writer.append("if (!").appendClass("java.util.ServiceLoader").append(".$$services$$) {").indent()
|
||||
.softNewLine();
|
||||
writer.appendClass("java.util.ServiceLoader").append(".$$services$$ = true;").softNewLine();
|
||||
for (String serviceType : information.serviceTypes()) {
|
||||
writer.appendClass(serviceType).append(".$$serviceList$$ = [");
|
||||
Collection<? extends String> implementations = information.serviceImplementations(serviceType);
|
||||
boolean first = true;
|
||||
for (String implName : implementations) {
|
||||
if (context.getClassSource().getClassNames().contains(implName)) {
|
||||
if (!first) {
|
||||
writer.append(", ");
|
||||
var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource());
|
||||
var template = templateFactory.createFromResource("org/teavm/classlib/java/util/ServiceLoader.js");
|
||||
var information = context.getService(ServiceLoaderInformation.class);
|
||||
var fragment = template.builder("loadServices")
|
||||
.withContext(context)
|
||||
.withFragment("fillServices", (w, precedence) -> {
|
||||
for (var serviceType : information.serviceTypes()) {
|
||||
writer.appendClass(serviceType).append(".$$serviceList$$ = [");
|
||||
var implementations = information.serviceImplementations(serviceType);
|
||||
boolean first = true;
|
||||
for (var implName : implementations) {
|
||||
if (context.getClassSource().getClassNames().contains(implName)) {
|
||||
if (!first) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
first = false;
|
||||
writer.append("[").appendClass(implName).append(",").ws()
|
||||
.appendMethodBody(new MethodReference(implName, INIT_METHOD))
|
||||
.append("]");
|
||||
}
|
||||
}
|
||||
writer.append("];").softNewLine();
|
||||
}
|
||||
first = false;
|
||||
writer.append("[").appendClass(implName).append(", ").appendMethodBody(
|
||||
new MethodReference(implName, INIT_METHOD))
|
||||
.append("]");
|
||||
}
|
||||
}
|
||||
writer.append("];").softNewLine();
|
||||
}
|
||||
writer.outdent().append("}").softNewLine();
|
||||
String param = context.getParameterName(1);
|
||||
writer.append("var cls = " + param + ";").softNewLine();
|
||||
writer.append("if (!cls.$$serviceList$$) {").indent().softNewLine();
|
||||
writer.append("return $rt_createArray($rt_objcls(), 0);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("var result = $rt_createArray($rt_objcls(), cls.$$serviceList$$.length);").softNewLine();
|
||||
writer.append("for (var i = 0; i < result.data.length; ++i) {").indent().softNewLine();
|
||||
writer.append("var serviceDesc = cls.$$serviceList$$[i];").softNewLine();
|
||||
writer.append("result.data[i] = new serviceDesc[0]();").softNewLine();
|
||||
writer.append("serviceDesc[1](result.data[i]);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return result;").softNewLine();
|
||||
})
|
||||
.build();
|
||||
fragment.write(writer, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
|
|||
var writer = context.getWriter();
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws();
|
||||
writer.append("$rt_charArrayToString").append("(");
|
||||
writer.appendFunction("$rt_charArrayToString").append("(");
|
||||
context.writeExpr(context.getArgument(1));
|
||||
writer.append(".data,").ws();
|
||||
context.writeExpr(context.getArgument(2));
|
||||
|
@ -135,7 +135,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
|
|||
var writer = context.getWriter();
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.append(".").appendField(NATIVE_FIELD).ws().append("=").ws();
|
||||
writer.append("$rt_fullArrayToString").append("(");
|
||||
writer.appendFunction("$rt_fullArrayToString").append("(");
|
||||
context.writeExpr(context.getArgument(1));
|
||||
writer.append(".data)");
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
|
|||
|
||||
private void copyCharsToArray(InjectorContext context) throws IOException {
|
||||
var writer = context.getWriter();
|
||||
writer.append("$rt_stringToCharArray").append("(");
|
||||
writer.appendFunction("$rt_stringToCharArray").append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.append(".").appendField(NATIVE_FIELD);
|
||||
writer.append(",").ws();
|
||||
|
@ -183,7 +183,7 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
|
|||
|
||||
private void fastCharArray(InjectorContext context) throws IOException {
|
||||
var writer = context.getWriter();
|
||||
writer.append("$rt_fastStringToCharArray").append("(");
|
||||
writer.appendFunction("$rt_fastStringToCharArray").append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.append(".").appendField(NATIVE_FIELD);
|
||||
writer.append(")");
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
|||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "newEmptyInstance":
|
||||
context.getWriter().append("new (");
|
||||
context.getWriter().append("new").ws().append("(");
|
||||
context.writeExpr(context.getArgument(0), Precedence.MEMBER_ACCESS);
|
||||
context.getWriter().append('.').appendField(platformClassField);
|
||||
context.getWriter().append(")");
|
||||
|
|
|
@ -75,7 +75,7 @@ public class ClassLoaderNativeGenerator implements Injector {
|
|||
dataChars[i] = (char) dataBytes[i];
|
||||
}
|
||||
RenderingUtil.writeString(writer, resource);
|
||||
writer.ws().append(':').ws();
|
||||
writer.append(':').ws();
|
||||
RenderingUtil.writeString(writer, new String(dataChars));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ public class DoubleGenerator implements Injector {
|
|||
context.getWriter().append(')');
|
||||
return;
|
||||
}
|
||||
context.getWriter().append("$rt_").append(methodRef.getName()).append("(");
|
||||
var functionName = "$rt_" + methodRef.getName();
|
||||
context.getWriter().appendFunction(functionName).append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(")");
|
||||
}
|
||||
|
|
|
@ -25,26 +25,23 @@ public class IntegerNativeGenerator implements Injector {
|
|||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "divideUnsigned":
|
||||
context.getWriter().append("$rt_udiv(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(",").ws();
|
||||
context.writeExpr(context.getArgument(1));
|
||||
context.getWriter().append(")");
|
||||
generateRuntimeCall(context, "$rt_udiv");
|
||||
break;
|
||||
case "remainderUnsigned":
|
||||
context.getWriter().append("$rt_umod(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(",").ws();
|
||||
context.writeExpr(context.getArgument(1));
|
||||
context.getWriter().append(")");
|
||||
generateRuntimeCall(context, "$rt_umod");
|
||||
break;
|
||||
case "compareUnsigned":
|
||||
context.getWriter().append("$rt_ucmp(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(",").ws();
|
||||
context.writeExpr(context.getArgument(1));
|
||||
context.getWriter().append(")");
|
||||
generateRuntimeCall(context, "$rt_ucmp");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void generateRuntimeCall(InjectorContext context, String name) throws IOException {
|
||||
context.getWriter().appendFunction(name).append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(",").ws();
|
||||
context.writeExpr(context.getArgument(1));
|
||||
context.getWriter().append(")");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,12 @@ public class MathNativeGenerator implements Generator {
|
|||
if (name.equals("signum")) {
|
||||
name = "sign";
|
||||
}
|
||||
function(context, writer, "Math." + name, methodRef.parameterCount());
|
||||
function(context, writer, name, methodRef.parameterCount());
|
||||
}
|
||||
|
||||
private void function(GeneratorContext context, SourceWriter writer, String name, int paramCount)
|
||||
throws IOException {
|
||||
writer.append("return ").append(name).append("(");
|
||||
writer.append("return ").append("$rt_globals.Math").append(".").append(name).append("(");
|
||||
for (int i = 0; i < paramCount; ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 2023 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.classlib.java.lang.reflect;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
public class ArrayDependencyPlugin implements DependencyPlugin {
|
||||
private static final String[] primitives = { "Byte", "Short", "Char", "Int", "Long", "Float", "Double",
|
||||
"Boolean" };
|
||||
private static final String[] primitiveWrappers = { "Byte", "Short", "Character", "Integer", "Long",
|
||||
"Float", "Double", "Boolean" };
|
||||
private static final ValueType[] primitiveTypes = { ValueType.BYTE, ValueType.SHORT, ValueType.CHARACTER,
|
||||
ValueType.INTEGER, ValueType.LONG, ValueType.FLOAT, ValueType.DOUBLE, ValueType.BOOLEAN };
|
||||
|
||||
private Set<MethodReference> reachedMethods = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||
if (!reachedMethods.add(method.getReference())) {
|
||||
return;
|
||||
}
|
||||
switch (method.getReference().getName()) {
|
||||
case "getLength":
|
||||
reachGetLength(agent, method);
|
||||
break;
|
||||
case "newInstance":
|
||||
method.getVariable(1).getClassValueNode().addConsumer(t -> {
|
||||
String arrayTypeName;
|
||||
if (t.getName().startsWith("[")) {
|
||||
arrayTypeName = t.getName();
|
||||
} else if (t.getName().startsWith("~")) {
|
||||
arrayTypeName = t.getName().substring(1);
|
||||
} else {
|
||||
arrayTypeName = ValueType.object(t.getName()).toString();
|
||||
}
|
||||
if (!arrayTypeName.startsWith("[[[")) {
|
||||
method.getResult().propagate(agent.getType("[" + arrayTypeName));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "getImpl":
|
||||
reachGet(agent, method);
|
||||
break;
|
||||
case "setImpl":
|
||||
reachSet(agent, method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void reachGetLength(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (!type.getName().startsWith("[")) {
|
||||
MethodReference cons = new MethodReference(IllegalArgumentException.class, "<init>", void.class);
|
||||
agent.linkMethod(cons).use();
|
||||
}
|
||||
});
|
||||
}
|
||||
private void reachGet(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(1).getArrayItem().connect(method.getResult());
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (type.getName().startsWith("[")) {
|
||||
String typeName = type.getName().substring(1);
|
||||
for (int i = 0; i < primitiveTypes.length; ++i) {
|
||||
if (primitiveTypes[i].toString().equals(typeName)) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper, "valueOf",
|
||||
primitiveTypes[i], ValueType.object(wrapper));
|
||||
agent.linkMethod(methodRef).use();
|
||||
method.getResult().propagate(agent.getType("java.lang." + primitiveWrappers[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void reachSet(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(3).connect(method.getVariable(1).getArrayItem());
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (type.getName().startsWith("[")) {
|
||||
String typeName = type.getName().substring(1);
|
||||
for (int i = 0; i < primitiveTypes.length; ++i) {
|
||||
if (primitiveTypes[i].toString().equals(typeName)) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper,
|
||||
primitives[i].toLowerCase() + "Value", primitiveTypes[i]);
|
||||
agent.linkMethod(methodRef).use();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -16,190 +16,22 @@
|
|||
package org.teavm.classlib.java.lang.reflect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplate;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
||||
private static final String[] primitives = { "Byte", "Short", "Char", "Int", "Long", "Float", "Double",
|
||||
"Boolean" };
|
||||
private static final String[] primitiveWrappers = { "Byte", "Short", "Character", "Integer", "Long",
|
||||
"Float", "Double", "Boolean" };
|
||||
private static final ValueType[] primitiveTypes = { ValueType.BYTE, ValueType.SHORT, ValueType.CHARACTER,
|
||||
ValueType.INTEGER, ValueType.LONG, ValueType.FLOAT, ValueType.DOUBLE, ValueType.BOOLEAN };
|
||||
public class ArrayNativeGenerator implements Generator {
|
||||
private JavaScriptTemplate template;
|
||||
|
||||
private Set<MethodReference> reachedMethods = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||
if (!reachedMethods.add(method.getReference())) {
|
||||
return;
|
||||
}
|
||||
switch (method.getReference().getName()) {
|
||||
case "getLength":
|
||||
reachGetLength(agent, method);
|
||||
break;
|
||||
case "newInstance":
|
||||
method.getVariable(1).getClassValueNode().addConsumer(t -> {
|
||||
String arrayTypeName;
|
||||
if (t.getName().startsWith("[")) {
|
||||
arrayTypeName = t.getName();
|
||||
} else if (t.getName().startsWith("~")) {
|
||||
arrayTypeName = t.getName().substring(1);
|
||||
} else {
|
||||
arrayTypeName = ValueType.object(t.getName()).toString();
|
||||
}
|
||||
if (!arrayTypeName.startsWith("[[[")) {
|
||||
method.getResult().propagate(agent.getType("[" + arrayTypeName));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "getImpl":
|
||||
reachGet(agent, method);
|
||||
break;
|
||||
case "setImpl":
|
||||
reachSet(agent, method);
|
||||
break;
|
||||
}
|
||||
public ArrayNativeGenerator(JavaScriptTemplateFactory templateFactory) throws IOException {
|
||||
template = templateFactory.createFromResource("org/teavm/classlib/java/lang/reflect/Array.js");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "getLength":
|
||||
generateGetLength(context, writer);
|
||||
break;
|
||||
case "newInstanceImpl":
|
||||
generateNewInstance(context, writer);
|
||||
break;
|
||||
case "getImpl":
|
||||
generateGet(context, writer);
|
||||
break;
|
||||
case "setImpl":
|
||||
generateSet(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateGetLength(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String array = context.getParameterName(1);
|
||||
writer.append("if (" + array + " === null || " + array + ".constructor.$meta.item === undefined) {")
|
||||
.softNewLine().indent();
|
||||
MethodReference cons = new MethodReference("java.lang.IllegalArgumentException", "<init>", ValueType.VOID);
|
||||
writer.append("$rt_throw(").appendInit(cons).append("());").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return " + array + ".data.length;").softNewLine();
|
||||
}
|
||||
|
||||
private void reachGetLength(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (!type.getName().startsWith("[")) {
|
||||
MethodReference cons = new MethodReference(IllegalArgumentException.class, "<init>", void.class);
|
||||
agent.linkMethod(cons).use();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String type = context.getParameterName(1);
|
||||
String length = context.getParameterName(2);
|
||||
writer.append("if (").append(type).append(".$meta.primitive) {").softNewLine().indent();
|
||||
for (String primitive : primitives) {
|
||||
writer.append("if (" + type + " == $rt_" + primitive.toLowerCase() + "cls) {").indent().softNewLine();
|
||||
writer.append("return $rt_create" + primitive + "Array(" + length + ");").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
writer.outdent().append("} else {").indent().softNewLine();
|
||||
writer.append("return $rt_createArray(" + type + ", " + length + ")").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
private void generateGet(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String array = context.getParameterName(1);
|
||||
writer.append("var item = " + array + ".data[" + context.getParameterName(2) + "];").softNewLine();
|
||||
writer.append("var type = " + array + ".constructor.$meta.item;").softNewLine();
|
||||
for (int i = 0; i < primitives.length; ++i) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper, "valueOf",
|
||||
primitiveTypes[i], ValueType.object(wrapper));
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
if (cls == null || cls.getMethod(methodRef.getDescriptor()) == null) {
|
||||
continue;
|
||||
}
|
||||
writer.append("if (type === $rt_" + primitives[i].toLowerCase() + "cls) {").indent().softNewLine();
|
||||
writer.append("return ").appendMethodBody(methodRef).append("(item);").softNewLine();
|
||||
writer.outdent().append("} else ");
|
||||
}
|
||||
writer.append("{").indent().softNewLine();
|
||||
writer.append("return item;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
private void generateSet(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String array = context.getParameterName(1);
|
||||
String item = context.getParameterName(3);
|
||||
writer.append("var type = " + array + ".constructor.$meta.item;").softNewLine();
|
||||
boolean first = true;
|
||||
for (int i = 0; i < primitives.length; ++i) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper, primitives[i].toLowerCase() + "Value",
|
||||
primitiveTypes[i]);
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
if (cls == null || cls.getMethod(methodRef.getDescriptor()) == null) {
|
||||
continue;
|
||||
}
|
||||
if (!first) {
|
||||
writer.append(" else ");
|
||||
}
|
||||
first = false;
|
||||
writer.append("if (type === $rt_" + primitives[i].toLowerCase() + "cls) {").indent().softNewLine();
|
||||
writer.append(item + " = ").appendMethodBody(methodRef).append("(" + item + ");").softNewLine();
|
||||
writer.outdent().append("}");
|
||||
}
|
||||
writer.softNewLine();
|
||||
writer.append(array + ".data[" + context.getParameterName(2) + "] = " + item + ";").softNewLine();
|
||||
}
|
||||
|
||||
private void reachGet(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(1).getArrayItem().connect(method.getResult());
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (type.getName().startsWith("[")) {
|
||||
String typeName = type.getName().substring(1);
|
||||
for (int i = 0; i < primitiveTypes.length; ++i) {
|
||||
if (primitiveTypes[i].toString().equals(typeName)) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper, "valueOf",
|
||||
primitiveTypes[i], ValueType.object(wrapper));
|
||||
agent.linkMethod(methodRef).use();
|
||||
method.getResult().propagate(agent.getType("java.lang." + primitiveWrappers[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void reachSet(DependencyAgent agent, MethodDependency method) {
|
||||
method.getVariable(3).connect(method.getVariable(1).getArrayItem());
|
||||
method.getVariable(1).addConsumer(type -> {
|
||||
if (type.getName().startsWith("[")) {
|
||||
String typeName = type.getName().substring(1);
|
||||
for (int i = 0; i < primitiveTypes.length; ++i) {
|
||||
if (primitiveTypes[i].toString().equals(typeName)) {
|
||||
String wrapper = "java.lang." + primitiveWrappers[i];
|
||||
MethodReference methodRef = new MethodReference(wrapper,
|
||||
primitives[i].toLowerCase() + "Value", primitiveTypes[i]);
|
||||
agent.linkMethod(methodRef).use();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.teavm.runtime.RuntimeObject;
|
|||
|
||||
public final class TArray extends TObject {
|
||||
@GeneratedBy(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayDependencyPlugin.class)
|
||||
@DelegateTo("getLengthLowLevel")
|
||||
@NoSideEffects
|
||||
public static native int getLength(TObject array) throws TIllegalArgumentException;
|
||||
|
@ -48,7 +48,7 @@ public final class TArray extends TObject {
|
|||
return array.size;
|
||||
}
|
||||
|
||||
@PluggableDependency(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayDependencyPlugin.class)
|
||||
public static TObject newInstance(Class<?> componentType, int length) throws TNegativeArraySizeException {
|
||||
if (componentType == null) {
|
||||
throw new TNullPointerException();
|
||||
|
@ -89,12 +89,12 @@ public final class TArray extends TObject {
|
|||
}
|
||||
|
||||
@GeneratedBy(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayDependencyPlugin.class)
|
||||
@NoSideEffects
|
||||
private static native TObject getImpl(TObject array, int index);
|
||||
|
||||
@GeneratedBy(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayDependencyPlugin.class)
|
||||
@NoSideEffects
|
||||
private static native void setImpl(TObject array, int index, TObject value);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function init() {
|
||||
this[teavm_javaField("java.lang.ref.ReferenceQueue", "inner")] = [];
|
||||
if (teavm_javaMethodExists("java.lang.ref.ReferenceQueue", "reportNext(Ljava/lang/ref/Reference;)Z")) {
|
||||
this[teavm_javaField("java.lang.ref.ReferenceQueue", "registry")] =
|
||||
new (teavm_globals.FinalizationRegistry)(ref => {
|
||||
if (!teavm_javaMethod("java.lang.ref.ReferenceQueue",
|
||||
"reportNext(Ljava/lang/ref/Reference;)Z")(this, ref)) {
|
||||
this[teavm_javaField("java.lang.ref.ReferenceQueue", "inner")].push(ref);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function poll() {
|
||||
var value = this[teavm_javaField("java.lang.ref.ReferenceQueue", "inner")];
|
||||
return typeof value !== 'undefined' ? value : null;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function init(target, queue) {
|
||||
let supported = typeof teavm_globals.WeakRef !== 'undefined';
|
||||
let value = supported ? new teavm_globals.WeakRef(target) : target;
|
||||
this[teavm_javaField("java.lang.ref.WeakReference", "value")] = value;
|
||||
if (queue !== null && supported) {
|
||||
let registry = queue[teavm_javaField("java.lang.ref.ReferenceQueue", "registry")];
|
||||
if (registry !== null) {
|
||||
registry.register(target, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
function get() {
|
||||
let value = this[teavm_javaField("java.lang.ref.WeakReference", "value")];
|
||||
if (typeof teavm_globals.WeakRef !== 'undefined') {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
let result = value.deref();
|
||||
return typeof result !== 'undefined' ? result : null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function clear() {
|
||||
this[teavm_javaField("java.lang.ref.WeakReference", "value")] = null;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function getLength(array) {
|
||||
if (array === null || array.constructor.$meta.item === 'undefined') {
|
||||
$rt_throw(teavm_javaConstructor("java.lang.IllegalArgumentException", "()V")());
|
||||
}
|
||||
return array.data.length;
|
||||
}
|
||||
|
||||
function newInstanceImpl(type, length) {
|
||||
if (type.$meta.primitive) {
|
||||
switch (type) {
|
||||
case $rt_booleanArrayCls: return $rt_createBooleanArray(length);
|
||||
case $rt_byteArrayCls: return $rt_createByteArray(length);
|
||||
case $rt_shortArrayCls: return $rt_createShortArray(length);
|
||||
case $rt_charArrayCls: return $rt_createCharArray(length);
|
||||
case $rt_intArrayCls: return $rt_createIntArray(length);
|
||||
case $rt_longArrayCls: return $rt_createLongArray(length);
|
||||
case $rt_floatArrayCls: return $rt_createFloatArray(length);
|
||||
case $rt_doubleArrayCls: return $rt_createDoubleArray(length);
|
||||
}
|
||||
}
|
||||
return $rt_createArray(type, length);
|
||||
}
|
||||
|
||||
function getImpl(array, index) {
|
||||
var item = array.data[index];
|
||||
var type = array.constructor.$meta.item;
|
||||
if (teavm_javaMethodExists("java.lang.Boolean", "valueOf(Z)Ljava/lang/Boolean;") && type === $rt_booleancls) {
|
||||
return teavm_javaMethod("java.lang.Boolean", "valueOf(Z)Ljava/lang/Boolean;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Byte", "valueOf(B)Ljava/lang/Byte;") && type === $rt_bytecls) {
|
||||
return teavm_javaMethod("java.lang.Byte", "valueOf(B)Ljava/lang/Byte;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Short", "valueOf(S)Ljava/lang/Short;") && type === $rt_shortcls) {
|
||||
return teavm_javaMethod("java.lang.Short", "valueOf(S)Ljava/lang/Short;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Character", "valueOf(C)Ljava/lang/Character;")
|
||||
&& type === $rt_charcls) {
|
||||
return teavm_javaMethod("java.lang.Character", "valueOf(C)Ljava/lang/Character;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Integer", "valueOf(I)Ljava/lang/Integer;") && type === $rt_intcls) {
|
||||
return teavm_javaMethod("java.lang.Integer", "valueOf(I)Ljava/lang/Integer;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Long", "valueOf(J)Ljava/lang/Long;") && type === $rt_longcls) {
|
||||
return teavm_javaMethod("java.lang.Long", "valueOf(J)Ljava/lang/Long;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Float", "valueOf(F)Ljava/lang/Float;") && type === $rt_floatcls) {
|
||||
return teavm_javaMethod("java.lang.Float", "valueOf(F)Ljava/lang/Float;")(item);
|
||||
} else if (teavm_javaMethodExists("java.lang.Double", "valueOf(D)Ljava/lang/Double;") && type === $rt_doublecls) {
|
||||
return teavm_javaMethod("java.lang.Double", "valueOf(D)Ljava/lang/Double;")(item);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
function setImpl(array, index, value) {
|
||||
var type = array.constructor.$meta.item;
|
||||
if (teavm_javaMethodExists("java.lang.Boolean", "booleanValue()Z") && type === $rt_booleancls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Boolean", "booleanValue()Z")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Byte", "byteValue()B") && type === $rt_booleancls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Byte", "byteValue()B")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Short", "shortValue()S") && type === $rt_shortcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Short", "shortValue()S")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Character", "charValue()C") && type === $rt_charcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Character", "charValue()C")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Integer", "intValue()I") && type === $rt_intcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Integer", "intValue()I")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Long", "longValue()J") && type === $rt_longcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Long", "longValue()J")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Float", "floatValue()F") && type === $rt_floatcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Float", "floatValue()F")(value);
|
||||
} else if (teavm_javaMethodExists("java.lang.Double", "doubleValue()D") && type === $rt_floatcls) {
|
||||
array.data[index] = teavm_javaMethod("java.lang.Double", "doubleValue()D")(value);
|
||||
} else {
|
||||
array.data[index] = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function loadServices(cls) {
|
||||
let serviceLoader = teavm_javaClass("java.util.ServiceLoader");
|
||||
if (!serviceLoader.$$services$$) {
|
||||
serviceLoader.$$services$$ = true;
|
||||
teavm_fragment("fillServices");
|
||||
}
|
||||
|
||||
let serviceList = cls.$$serviceList$$;
|
||||
if (!serviceList) {
|
||||
return $rt_createArray($rt_objcls(), 0);
|
||||
}
|
||||
|
||||
let result = $rt_createArray($rt_objcls(), serviceList.length);
|
||||
for (let i = 0; i < serviceList.length; ++i) {
|
||||
let serviceDesc = serviceList[i];
|
||||
let instance = new serviceDesc[0]();
|
||||
serviceDesc[1](instance);
|
||||
result.data[i] = instance;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -171,7 +171,10 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
public void setController(TeaVMTargetController controller) {
|
||||
this.controller = controller;
|
||||
|
||||
var weakRefGenerator = new WeakReferenceGenerator();
|
||||
templateFactory = new JavaScriptTemplateFactory(controller.getClassLoader(),
|
||||
controller.getDependencyInfo().getClassSource());
|
||||
|
||||
var weakRefGenerator = new WeakReferenceGenerator(templateFactory);
|
||||
methodGenerators.put(new MethodReference(WeakReference.class, "<init>", Object.class,
|
||||
ReferenceQueue.class, void.class), weakRefGenerator);
|
||||
methodGenerators.put(new MethodReference(WeakReference.class, "get", Object.class), weakRefGenerator);
|
||||
|
@ -180,9 +183,6 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
var refQueueGenerator = new ReferenceQueueGenerator();
|
||||
methodGenerators.put(new MethodReference(ReferenceQueue.class, "<init>", void.class), refQueueGenerator);
|
||||
methodGenerators.put(new MethodReference(ReferenceQueue.class, "poll", Reference.class), refQueueGenerator);
|
||||
|
||||
templateFactory = new JavaScriptTemplateFactory(controller.getClassLoader(),
|
||||
controller.getDependencyInfo().getClassSource());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -480,7 +480,6 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
|
||||
if (renderer.isLongLibraryUsed()) {
|
||||
runtimeRenderer.renderHandWrittenRuntime("long.js");
|
||||
renderer.renderLongRuntimeAliases();
|
||||
}
|
||||
if (renderer.isThreadLibraryUsed()) {
|
||||
runtimeRenderer.renderHandWrittenRuntime("thread.js");
|
||||
|
@ -491,10 +490,10 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
for (var entry : controller.getEntryPoints().entrySet()) {
|
||||
sourceWriter.append("$rt_exports.").append(entry.getKey()).ws().append("=").ws();
|
||||
var ref = entry.getValue().getMethod();
|
||||
sourceWriter.append("$rt_mainStarter(").appendMethodBody(ref);
|
||||
sourceWriter.appendFunction("$rt_mainStarter").append("(").appendMethodBody(ref);
|
||||
sourceWriter.append(");").newLine();
|
||||
sourceWriter.append("$rt_exports.").append(entry.getKey()).append(".").append("javaException")
|
||||
.ws().append("=").ws().append("$rt_javaException;").newLine();
|
||||
.ws().append("=").ws().appendFunction("$rt_javaException").append(";").newLine();
|
||||
}
|
||||
|
||||
for (var listener : rendererListeners) {
|
||||
|
|
|
@ -16,56 +16,33 @@
|
|||
package org.teavm.backend.javascript.intrinsics.ref;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplate;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class ReferenceQueueGenerator implements Generator {
|
||||
private static final FieldReference INNER_FIELD = new FieldReference(ReferenceQueue.class.getName(), "inner");
|
||||
private static final FieldReference REGISTRY_FIELD = new FieldReference(ReferenceQueue.class.getName(),
|
||||
"registry");
|
||||
private static final MethodReference REPORT_METHOD = new MethodReference(ReferenceQueue.class,
|
||||
"reportNext", Reference.class, boolean.class);
|
||||
private JavaScriptTemplate template;
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
ensureTemplate(context);
|
||||
switch (methodRef.getName()) {
|
||||
case "<init>":
|
||||
generateInitMethod(context, writer);
|
||||
template.builder("init").withContext(context).build().write(writer, 0);
|
||||
break;
|
||||
case "poll":
|
||||
generatePollMethod(context, writer);
|
||||
template.builder("poll").withContext(context).build().write(writer, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInitMethod(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append(context.getParameterName(0)).append(".").appendField(INNER_FIELD).ws().append("=")
|
||||
.ws().append("[];").softNewLine();
|
||||
|
||||
if (context.getDependency().getMethod(REPORT_METHOD) != null) {
|
||||
generateFinalizationRegistry(context, writer);
|
||||
private void ensureTemplate(GeneratorContext context) throws IOException {
|
||||
if (template == null) {
|
||||
template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource())
|
||||
.createFromResource("org/teavm/classlib/java/lang/ref/ReferenceQueue.js");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFinalizationRegistry(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append(context.getParameterName(0)).append(".").appendField(REGISTRY_FIELD).ws().append("=")
|
||||
.ws().append("new $rt_globals.FinalizationRegistry(ref").ws().append("=>").appendBlockStart();
|
||||
writer.appendIf().append("!").appendMethodBody(REPORT_METHOD).append("(")
|
||||
.append(context.getParameterName(0)).append(",").ws().append("ref))").ws();
|
||||
writer.append(context.getParameterName(0)).append(".").appendField(INNER_FIELD)
|
||||
.append(".push(ref)").softNewLine();
|
||||
writer.appendBlockEnd().append(");").softNewLine();
|
||||
}
|
||||
|
||||
private void generatePollMethod(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var value").ws().append("=").ws().append(context.getParameterName(0))
|
||||
.append(".").appendField(INNER_FIELD).append(".shift();").softNewLine();
|
||||
writer.append("return typeof value").ws().append("!==").ws().append("'undefined'").ws()
|
||||
.append("?").ws().append("value").ws().append(":").ws().append("null;").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,82 +16,34 @@
|
|||
package org.teavm.backend.javascript.intrinsics.ref;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||
import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplate;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class WeakReferenceGenerator implements Generator {
|
||||
private JavaScriptTemplate template;
|
||||
|
||||
public WeakReferenceGenerator(JavaScriptTemplateFactory templateFactory) {
|
||||
try {
|
||||
template = templateFactory.createFromResource("org/teavm/classlib/java/lang/ref/WeakReference.js");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "<init>":
|
||||
generateConstructor(context, writer);
|
||||
template.builder("init").withContext(context).build().write(writer, 0);
|
||||
break;
|
||||
case "get":
|
||||
generateGet(context, writer);
|
||||
break;
|
||||
case "clear":
|
||||
generateClear(context, writer);
|
||||
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateConstructor(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var supported").ws().append("=").ws();
|
||||
isSupported(writer).append(";").softNewLine();
|
||||
writer.append("var value").ws().append("=").ws().append("supported").ws()
|
||||
.append("?").ws().append("new $rt_globals.WeakRef(")
|
||||
.append(context.getParameterName(1)).append(")").ws();
|
||||
writer.append(":").ws().append(context.getParameterName(0)).append(";").softNewLine();
|
||||
|
||||
writer.append(context.getParameterName(0)).append(".")
|
||||
.appendField(new FieldReference(WeakReference.class.getName(), "value"))
|
||||
.ws().append("=").ws().append("value;").softNewLine();
|
||||
|
||||
writer.appendIf().append(context.getParameterName(2)).ws().append("!==").ws().append("null")
|
||||
.ws().append("&&").ws().append("supported)")
|
||||
.appendBlockStart();
|
||||
|
||||
writer.append("var registry").ws().append("=").ws()
|
||||
.append(context.getParameterName(2)).append(".")
|
||||
.appendField(new FieldReference(ReferenceQueue.class.getName(), "registry")).append(";")
|
||||
.softNewLine();
|
||||
writer.appendIf().append("registry").ws().append("!==").ws().append("null)").ws();
|
||||
writer.append("registry.register(").append(context.getParameterName(1))
|
||||
.append(",").ws().append(context.getParameterName(0)).append(");").softNewLine();
|
||||
|
||||
writer.appendBlockEnd();
|
||||
}
|
||||
|
||||
private void generateGet(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var value").ws().append("=").ws().append(context.getParameterName(0)).append(".")
|
||||
.appendField(new FieldReference(WeakReference.class.getName(), "value"))
|
||||
.append(";").softNewLine();
|
||||
|
||||
writer.appendIf();
|
||||
isSupported(writer).append(")").appendBlockStart();
|
||||
writer.appendIf().append("value").ws().append("===").ws().append("null)")
|
||||
.ws().append("return null;").softNewLine();
|
||||
writer.append("var result").ws().append("=").ws().append("value.deref();").softNewLine();
|
||||
writer.append("return typeof result").ws().append("!==").ws().append("'undefined'")
|
||||
.ws().append("?").ws().append("result").ws().append(":").ws().append("null;").softNewLine();
|
||||
writer.appendElse();
|
||||
writer.append("return value;").softNewLine();
|
||||
writer.appendBlockEnd();
|
||||
}
|
||||
|
||||
private void generateClear(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append(context.getParameterName(0)).append(".")
|
||||
.appendField(new FieldReference(WeakReference.class.getName(), "value")).ws();
|
||||
writer.append("=").ws().append("null;").softNewLine();
|
||||
}
|
||||
|
||||
private SourceWriter isSupported(SourceWriter writer) throws IOException {
|
||||
return writer.append("typeof ").append("$rt_globals.WeakRef").ws().append("!==").ws()
|
||||
.append("'undefined'");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class DefaultGlobalNameWriter implements Function<String, NameEmitter> {
|
|||
@Override
|
||||
public NameEmitter apply(String s) {
|
||||
if (s.startsWith("$rt_") || s.startsWith("Long_") || s.equals("Long")) {
|
||||
return prec -> writer.append(s);
|
||||
return prec -> writer.appendFunction(s);
|
||||
}
|
||||
return prec -> writer.append("$rt_globals").append('.').append(s);
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
try {
|
||||
int start = writer.getOffset();
|
||||
writer.append("$rt_stringPool([");
|
||||
writer.appendFunction("$rt_stringPool").append("([");
|
||||
for (int i = 0; i < context.getStringPool().size(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(',').ws();
|
||||
|
@ -223,9 +223,9 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
|
||||
private void renderJavaStringToString() throws IOException {
|
||||
writer.appendClass("java.lang.String").append(".prototype.toString").ws().append("=").ws()
|
||||
.append("function()").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $rt_ustr(this);").softNewLine();
|
||||
writer.appendClass("java.lang.String").append(".prototype.toString").ws().append("=").ws().append("()")
|
||||
.ws().append("=>").ws().append("{").indent().softNewLine();
|
||||
writer.append("return ").appendFunction("$rt_ustr").append("(this);").softNewLine();
|
||||
writer.outdent().append("};").newLine();
|
||||
writer.appendClass("java.lang.String").append(".prototype.valueOf").ws().append("=").ws()
|
||||
.appendClass("java.lang.String").append(".prototype.toString;").softNewLine();
|
||||
|
@ -233,8 +233,9 @@ public class Renderer implements RenderingManager {
|
|||
|
||||
private void renderJavaObjectToString() throws IOException {
|
||||
writer.appendClass("java.lang.Object").append(".prototype.toString").ws().append("=").ws()
|
||||
.append("function()").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $rt_ustr(").appendMethodBody(Object.class, "toString", String.class).append("(this));")
|
||||
.append("()").ws().append("=>").ws().append("{").indent().softNewLine();
|
||||
writer.append("return ").appendFunction("$rt_ustr").append("(")
|
||||
.appendMethodBody(Object.class, "toString", String.class).append("(this));")
|
||||
.softNewLine();
|
||||
writer.outdent().append("};").newLine();
|
||||
}
|
||||
|
@ -242,7 +243,7 @@ public class Renderer implements RenderingManager {
|
|||
private void renderTeaVMClass() throws IOException {
|
||||
writer.appendClass("java.lang.Object").append(".prototype.__teavm_class__").ws().append("=").ws()
|
||||
.append("function()").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $dbg_class(this);").softNewLine();
|
||||
writer.append("return ").appendFunction("$dbg_class").append("(this);").softNewLine();
|
||||
writer.outdent().append("};").newLine();
|
||||
}
|
||||
|
||||
|
@ -250,42 +251,6 @@ public class Renderer implements RenderingManager {
|
|||
sizeByClass.put(className, sizeByClass.getOrDefault(className, 0) + sz);
|
||||
}
|
||||
|
||||
private void renderCommonRuntimeAliases() throws IOException {
|
||||
renderRuntimeAliases("$rt_throw", "$rt_compare", "$rt_nullCheck", "$rt_cls", "$rt_createArray",
|
||||
"$rt_isInstance", "$rt_nativeThread", "$rt_suspending", "$rt_resuming", "$rt_invalidPointer",
|
||||
"$rt_s", "$rt_eraseClinit", "$rt_imul", "$rt_wrapException", "$rt_checkBounds",
|
||||
"$rt_checkUpperBound", "$rt_checkLowerBound", "$rt_wrapFunction0", "$rt_wrapFunction1",
|
||||
"$rt_wrapFunction2", "$rt_wrapFunction3", "$rt_wrapFunction4",
|
||||
"$rt_classWithoutFields", "$rt_createArrayFromData", "$rt_createCharArrayFromData",
|
||||
"$rt_createByteArrayFromData", "$rt_createShortArrayFromData", "$rt_createIntArrayFromData",
|
||||
"$rt_createBooleanArrayFromData", "$rt_createFloatArrayFromData", "$rt_createDoubleArrayFromData",
|
||||
"$rt_createLongArrayFromData", "$rt_createBooleanArray", "$rt_createByteArray",
|
||||
"$rt_createShortArray", "$rt_createCharArray", "$rt_createIntArray", "$rt_createLongArray",
|
||||
"$rt_createFloatArray", "$rt_createDoubleArray", "$rt_compare",
|
||||
"$rt_castToClass", "$rt_castToInterface", "$rt_equalDoubles",
|
||||
"$rt_str", "Long_toNumber", "Long_fromInt", "Long_fromNumber", "Long_create", "Long_ZERO",
|
||||
"$rt_intern", "$rt_substring", "$rt_ustr",
|
||||
"Long_hi", "Long_lo");
|
||||
}
|
||||
|
||||
public void renderLongRuntimeAliases() throws IOException {
|
||||
renderRuntimeAliases("Long_add", "Long_sub", "Long_mul", "Long_div", "Long_rem", "Long_or", "Long_and",
|
||||
"Long_xor", "Long_shl", "Long_shr", "Long_shru", "Long_compare", "Long_eq", "Long_ne",
|
||||
"Long_lt", "Long_le", "Long_gt", "Long_ge", "Long_not", "Long_neg");
|
||||
}
|
||||
|
||||
private void renderRuntimeAliases(String... names) throws IOException {
|
||||
boolean first = true;
|
||||
for (String name : names) {
|
||||
if (!first) {
|
||||
writer.softNewLine();
|
||||
}
|
||||
first = false;
|
||||
writer.append("var ").appendFunction(name).ws().append('=').ws().append(name).append(";").softNewLine();
|
||||
}
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
public void prepare(List<PreparedClass> classes) {
|
||||
if (minifying) {
|
||||
NamingOrderer orderer = new NamingOrderer();
|
||||
|
@ -300,13 +265,6 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
|
||||
public boolean render(List<PreparedClass> classes) throws RenderingException {
|
||||
if (minifying) {
|
||||
try {
|
||||
renderCommonRuntimeAliases();
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException(e);
|
||||
}
|
||||
}
|
||||
int index = 0;
|
||||
for (PreparedClass cls : classes) {
|
||||
int start = writer.getOffset();
|
||||
|
@ -527,7 +485,7 @@ public class Renderer implements RenderingManager {
|
|||
|
||||
int start = writer.getOffset();
|
||||
try {
|
||||
writer.append("$rt_packages([");
|
||||
writer.appendFunction("$rt_packages").append("([");
|
||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, metadataRequirements);
|
||||
writer.append("]);").newLine();
|
||||
|
||||
|
@ -545,7 +503,7 @@ public class Renderer implements RenderingManager {
|
|||
|
||||
private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes,
|
||||
ClassMetadataRequirements metadataRequirements) throws IOException {
|
||||
writer.append("$rt_metadata([");
|
||||
writer.appendFunction("$rt_metadata").append("([");
|
||||
boolean first = true;
|
||||
for (PreparedClass cls : classes) {
|
||||
if (!first) {
|
||||
|
|
|
@ -305,40 +305,40 @@ public abstract class RenderingContext {
|
|||
}
|
||||
|
||||
for (int i = 0; i < arrayCount; ++i) {
|
||||
writer.append("$rt_arraycls(");
|
||||
writer.appendFunction("$rt_arraycls").append("(");
|
||||
}
|
||||
|
||||
if (type instanceof ValueType.Object) {
|
||||
ValueType.Object objType = (ValueType.Object) type;
|
||||
writer.appendClass(objType.getClassName());
|
||||
} else if (type instanceof ValueType.Void) {
|
||||
writer.append("$rt_voidcls");
|
||||
writer.appendFunction("$rt_voidcls");
|
||||
} else if (type instanceof ValueType.Primitive) {
|
||||
ValueType.Primitive primitiveType = (ValueType.Primitive) type;
|
||||
switch (primitiveType.getKind()) {
|
||||
case BOOLEAN:
|
||||
writer.append("$rt_booleancls");
|
||||
writer.appendFunction("$rt_booleancls");
|
||||
break;
|
||||
case CHARACTER:
|
||||
writer.append("$rt_charcls");
|
||||
writer.appendFunction("$rt_charcls");
|
||||
break;
|
||||
case BYTE:
|
||||
writer.append("$rt_bytecls");
|
||||
writer.appendFunction("$rt_bytecls");
|
||||
break;
|
||||
case SHORT:
|
||||
writer.append("$rt_shortcls");
|
||||
writer.appendFunction("$rt_shortcls");
|
||||
break;
|
||||
case INTEGER:
|
||||
writer.append("$rt_intcls");
|
||||
writer.appendFunction("$rt_intcls");
|
||||
break;
|
||||
case LONG:
|
||||
writer.append("$rt_longcls");
|
||||
writer.appendFunction("$rt_longcls");
|
||||
break;
|
||||
case FLOAT:
|
||||
writer.append("$rt_floatcls");
|
||||
writer.appendFunction("$rt_floatcls");
|
||||
break;
|
||||
case DOUBLE:
|
||||
writer.append("$rt_doublecls");
|
||||
writer.appendFunction("$rt_doublecls");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("The type is not renderable");
|
||||
|
|
|
@ -1414,32 +1414,32 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
|||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case BOOLEAN:
|
||||
writer.append("$rt_createBooleanMultiArray(");
|
||||
writer.appendFunction("$rt_createBooleanMultiArray").append("(");
|
||||
break;
|
||||
case BYTE:
|
||||
writer.append("$rt_createByteMultiArray(");
|
||||
writer.appendFunction("$rt_createByteMultiArray").append("(");
|
||||
break;
|
||||
case SHORT:
|
||||
writer.append("$rt_createShortMultiArray(");
|
||||
writer.appendFunction("$rt_createShortMultiArray").append("(");
|
||||
break;
|
||||
case INTEGER:
|
||||
writer.append("$rt_createIntMultiArray(");
|
||||
writer.appendFunction("$rt_createIntMultiArray").append("(");
|
||||
break;
|
||||
case LONG:
|
||||
writer.append("$rt_createLongMultiArray(");
|
||||
writer.appendFunction("$rt_createLongMultiArray").append("(");
|
||||
break;
|
||||
case FLOAT:
|
||||
writer.append("$rt_createFloatMultiArray(");
|
||||
writer.appendFunction("$rt_createFloatMultiArray").append("(");
|
||||
break;
|
||||
case DOUBLE:
|
||||
writer.append("$rt_createDoubleMultiArray(");
|
||||
writer.appendFunction("$rt_createDoubleMultiArray").append("(");
|
||||
break;
|
||||
case CHARACTER:
|
||||
writer.append("$rt_createCharMultiArray(");
|
||||
writer.appendFunction("$rt_createCharMultiArray").append("(");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
writer.append("$rt_createMultiArray(");
|
||||
writer.appendFunction("$rt_createMultiArray").append("(");
|
||||
context.typeToClsString(writer, type);
|
||||
writer.append(",").ws();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.backend.javascript.templating;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.IntFunction;
|
||||
import org.mozilla.javascript.ast.AstNode;
|
||||
import org.mozilla.javascript.ast.FunctionNode;
|
||||
|
@ -42,6 +43,7 @@ public class JavaScriptTemplate {
|
|||
public static class FragmentBuilder {
|
||||
private FunctionNode node;
|
||||
private IntFunction<SourceFragment> parameters;
|
||||
private Map<String, SourceFragment> fragments = new HashMap<>();
|
||||
|
||||
private FragmentBuilder(FunctionNode node) {
|
||||
this.node = node;
|
||||
|
@ -53,7 +55,12 @@ public class JavaScriptTemplate {
|
|||
}
|
||||
|
||||
public FragmentBuilder withContext(GeneratorContext context) {
|
||||
return withParameters(param -> (writer, precedence) -> writer.append(context.getParameterName(param + 1)));
|
||||
return withParameters(param -> (writer, precedence) -> writer.append(context.getParameterName(param)));
|
||||
}
|
||||
|
||||
public FragmentBuilder withFragment(String name, SourceFragment fragment) {
|
||||
fragments.put(name, fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceFragment build() {
|
||||
|
@ -62,13 +69,16 @@ public class JavaScriptTemplate {
|
|||
for (var i = 0; i < node.getParams().size(); ++i) {
|
||||
var param = node.getParams().get(i);
|
||||
if (param instanceof Name) {
|
||||
nameParameters.put(((Name) param).getIdentifier(), intParameters.apply(i));
|
||||
nameParameters.put(((Name) param).getIdentifier(), intParameters.apply(i + 1));
|
||||
}
|
||||
}
|
||||
var thisFragment = parameters.apply(0);
|
||||
var body = node.getBody();
|
||||
return (writer, precedence) -> {
|
||||
var astWriter = new TemplatingAstWriter(writer, nameParameters, node);
|
||||
for (var entry : fragments.entrySet()) {
|
||||
astWriter.setFragment(entry.getKey(), entry.getValue());
|
||||
}
|
||||
if (node.getSymbolTable() != null) {
|
||||
for (var name : node.getSymbolTable().keySet()) {
|
||||
astWriter.currentScopes.put(name, node);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.backend.javascript.templating;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.mozilla.javascript.ast.ElementGet;
|
||||
import org.mozilla.javascript.ast.FunctionCall;
|
||||
|
@ -34,6 +35,7 @@ import org.teavm.model.MethodReference;
|
|||
public class TemplatingAstWriter extends AstWriter {
|
||||
private Map<String, SourceFragment> names;
|
||||
private Scope scope;
|
||||
private Map<String, SourceFragment> fragments = new HashMap<>();
|
||||
|
||||
public TemplatingAstWriter(SourceWriter writer, Map<String, SourceFragment> names, Scope scope) {
|
||||
super(writer, new DefaultGlobalNameWriter(writer));
|
||||
|
@ -49,6 +51,10 @@ public class TemplatingAstWriter extends AstWriter {
|
|||
}
|
||||
}
|
||||
|
||||
public void setFragment(String name, SourceFragment fragment) {
|
||||
fragments.put(name, fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean intrinsic(FunctionCall node, int precedence) throws IOException {
|
||||
if (node.getTarget() instanceof Name) {
|
||||
|
@ -70,6 +76,8 @@ public class TemplatingAstWriter extends AstWriter {
|
|||
return writeJavaConstructor(node);
|
||||
case "teavm_javaClassInit":
|
||||
return writeJavaClassInit(node);
|
||||
case "teavm_fragment":
|
||||
return writeFragment(node);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -129,6 +137,19 @@ public class TemplatingAstWriter extends AstWriter {
|
|||
return true;
|
||||
}
|
||||
|
||||
private boolean writeFragment(FunctionCall node) throws IOException {
|
||||
if (node.getArguments().size() != 1) {
|
||||
return false;
|
||||
}
|
||||
var fragmentArg = node.getArguments().get(0);
|
||||
if (!(fragmentArg instanceof StringLiteral)) {
|
||||
return false;
|
||||
}
|
||||
var fragment = fragments.get(((StringLiteral) fragmentArg).getValue());
|
||||
fragment.write(writer, AstWriter.PRECEDENCE_COMMA + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void print(ElementGet node) throws IOException {
|
||||
if (node.getElement() instanceof FunctionCall) {
|
||||
|
@ -209,7 +230,7 @@ public class TemplatingAstWriter extends AstWriter {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (definingScope == null && scope != null) {
|
||||
if (definingScope == null) {
|
||||
writer.appendFunction(node.getIdentifier());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
var $rt_intern
|
||||
if (teavm_javaMethodExists("java.lang.String", "intern()Ljava/lang/String;")) {
|
||||
$rt_intern = function() {
|
||||
var map = Object.create(null);
|
||||
var map = teavm_globals.Object.create(null);
|
||||
|
||||
var get;
|
||||
if (typeof WeakRef !== 'undefined') {
|
||||
var registry = new FinalizationRegistry(value => {
|
||||
if (typeof teavm_globals.WeakRef !== 'undefined') {
|
||||
var registry = new teavm_globals.FinalizationRegistry(value => {
|
||||
delete map[value];
|
||||
});
|
||||
|
||||
|
@ -32,7 +32,7 @@ if (teavm_javaMethodExists("java.lang.String", "intern()Ljava/lang/String;")) {
|
|||
var result = typeof ref !== 'undefined' ? ref.deref() : void 0;
|
||||
if (typeof result !== 'object') {
|
||||
result = str;
|
||||
map[key] = new WeakRef(result);
|
||||
map[key] = new teavm_globals.WeakRef(result);
|
||||
registry.register(result, key);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -41,7 +41,7 @@ var Long_shr;
|
|||
var Long_shru;
|
||||
var Long_not;
|
||||
|
||||
if (typeof BigInt !== 'function') {
|
||||
if (typeof teavm_globals.BigInt !== 'function') {
|
||||
Long_eq = function(a, b) {
|
||||
return a.hi === b.hi && a.lo === b.lo;
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ if (typeof BigInt !== 'function') {
|
|||
|
||||
function Long_divRem(a, b) {
|
||||
if (b.lo === 0 && b.hi === 0) {
|
||||
throw new Error("Division by zero");
|
||||
throw new teavm_globals.Error("Division by zero");
|
||||
}
|
||||
var positive = Long_isNegative(a) === Long_isNegative(b);
|
||||
if (Long_isNegative(a)) {
|
||||
|
@ -286,7 +286,7 @@ if (typeof BigInt !== 'function') {
|
|||
|
||||
function Long_udivRem(a, b) {
|
||||
if (b.lo === 0 && b.hi === 0) {
|
||||
throw new Error("Division by zero");
|
||||
throw new teavm_globals.Error("Division by zero");
|
||||
}
|
||||
a = new LongInt(a.lo, a.hi, 0);
|
||||
b = new LongInt(b.lo, b.hi, 0);
|
||||
|
@ -599,79 +599,81 @@ if (typeof BigInt !== 'function') {
|
|||
}
|
||||
|
||||
Long_add = function(a, b) {
|
||||
return BigInt.asIntN(64, a + b);
|
||||
return teavm_globals.BigInt.asIntN(64, a + b);
|
||||
}
|
||||
|
||||
Long_inc = function(a) {
|
||||
return BigInt.asIntN(64, a + 1);
|
||||
return teavm_globals.BigInt.asIntN(64, a + 1);
|
||||
}
|
||||
|
||||
Long_dec = function(a) {
|
||||
return BigInt.asIntN(64, a - 1);
|
||||
return teavm_globals.BigInt.asIntN(64, a - 1);
|
||||
}
|
||||
|
||||
Long_neg = function(a) {
|
||||
return BigInt.asIntN(64, -a);
|
||||
return teavm_globals.BigInt.asIntN(64, -a);
|
||||
}
|
||||
|
||||
Long_sub = function(a, b) {
|
||||
return BigInt.asIntN(64, a - b);
|
||||
return teavm_globals.BigInt.asIntN(64, a - b);
|
||||
}
|
||||
|
||||
Long_compare = function(a, b) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
Long_ucompare = function(a, b) {
|
||||
a = BigInt.asUintN(64, a);
|
||||
b = BigInt.asUintN(64, b);
|
||||
a = teavm_globals.BigInt.asUintN(64, a);
|
||||
b = teavm_globals.BigInt.asUintN(64, b);
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
Long_mul = function(a, b) {
|
||||
return BigInt.asIntN(64, a * b);
|
||||
return teavm_globals.BigInt.asIntN(64, a * b);
|
||||
}
|
||||
|
||||
Long_div = function(a, b) {
|
||||
return BigInt.asIntN(64, a / b);
|
||||
return teavm_globals.BigInt.asIntN(64, a / b);
|
||||
}
|
||||
|
||||
Long_udiv = function(a, b) {
|
||||
return BigInt.asIntN(64, BigInt.asUintN(64, a) / BigInt.asUintN(64, b));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, a) /
|
||||
teavm_globals.BigInt.asUintN(64, b));
|
||||
}
|
||||
|
||||
Long_rem = function(a, b) {
|
||||
return BigInt.asIntN(64, a % b);
|
||||
return teavm_globals.BigInt.asIntN(64, a % b);
|
||||
}
|
||||
|
||||
Long_urem = function(a, b) {
|
||||
return BigInt.asIntN(64, BigInt.asUintN(64, a) % BigInt.asUintN(64, b));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, a) %
|
||||
teavm_globals.BigInt.asUintN(64, b));
|
||||
}
|
||||
|
||||
Long_and = function(a, b) {
|
||||
return BigInt.asIntN(64, a & b);
|
||||
return teavm_globals.BigInt.asIntN(64, a & b);
|
||||
}
|
||||
|
||||
Long_or = function(a, b) {
|
||||
return BigInt.asIntN(64, a | b);
|
||||
return teavm_globals.BigInt.asIntN(64, a | b);
|
||||
}
|
||||
|
||||
Long_xor = function(a, b) {
|
||||
return BigInt.asIntN(64, a ^ b);
|
||||
return teavm_globals.BigInt.asIntN(64, a ^ b);
|
||||
}
|
||||
|
||||
Long_shl = function(a, b) {
|
||||
return BigInt.asIntN(64, a << BigInt(b & 63));
|
||||
return teavm_globals.BigInt.asIntN(64, a << teavm_globals.BigInt(b & 63));
|
||||
}
|
||||
|
||||
Long_shr = function(a, b) {
|
||||
return BigInt.asIntN(64, a >> BigInt(b & 63));
|
||||
return teavm_globals.BigInt.asIntN(64, a >> teavm_globals.BigInt(b & 63));
|
||||
}
|
||||
|
||||
Long_shru = function(a, b) {
|
||||
return BigInt.asIntN(64, BigInt.asUintN(64, a) >> BigInt(b & 63));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, a) >> teavm_globals.BigInt(b & 63));
|
||||
}
|
||||
|
||||
Long_not = function(a) {
|
||||
return BigInt.asIntN(64, ~a);
|
||||
return teavm_globals.BigInt.asIntN(64, ~a);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ function $rt_castToClass(obj, cls) {
|
|||
return obj;
|
||||
}
|
||||
function $rt_createArray(cls, sz) {
|
||||
var data = new Array(sz);
|
||||
var data = new teavm_globals.Array(sz);
|
||||
data.fill(null);
|
||||
return new ($rt_arraycls(cls))(data);
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ function $rt_wrapArray(cls, data) {
|
|||
return new ($rt_arraycls(cls))(data);
|
||||
}
|
||||
function $rt_createUnfilledArray(cls, sz) {
|
||||
return new ($rt_arraycls(cls))(new Array(sz));
|
||||
return new ($rt_arraycls(cls))(new teavm_globals.Array(sz));
|
||||
}
|
||||
var $rt_createLongArray;
|
||||
var $rt_createLongArrayFromData;
|
||||
if (typeof BigInt64Array !== 'function') {
|
||||
if (typeof teavm_globals.BigInt64Array !== 'function') {
|
||||
$rt_createLongArray = function(sz) {
|
||||
var data = new Array(sz);
|
||||
var data = new teavm_globals.Array(sz);
|
||||
var arr = new $rt_longArrayCls(data);
|
||||
data.fill(Long_ZERO);
|
||||
return arr;
|
||||
|
@ -84,69 +84,69 @@ if (typeof BigInt64Array !== 'function') {
|
|||
}
|
||||
} else {
|
||||
$rt_createLongArray = function (sz) {
|
||||
return new $rt_longArrayCls(new BigInt64Array(sz));
|
||||
return new $rt_longArrayCls(new teavm_globals.BigInt64Array(sz));
|
||||
}
|
||||
$rt_createLongArrayFromData = function(data) {
|
||||
var buffer = new BigInt64Array(data.length);
|
||||
var buffer = new teavm_globals.BigInt64Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_longArrayCls(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
function $rt_createCharArray(sz) {
|
||||
return new $rt_charArrayCls(new Uint16Array(sz));
|
||||
return new $rt_charArrayCls(new teavm_globals.Uint16Array(sz));
|
||||
}
|
||||
function $rt_createCharArrayFromData(data) {
|
||||
var buffer = new Uint16Array(data.length);
|
||||
var buffer = new teavm_globals.Uint16Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_charArrayCls(buffer);
|
||||
}
|
||||
function $rt_createByteArray(sz) {
|
||||
return new $rt_byteArrayCls(new Int8Array(sz));
|
||||
return new $rt_byteArrayCls(new teavm_globals.Int8Array(sz));
|
||||
}
|
||||
function $rt_createByteArrayFromData(data) {
|
||||
var buffer = new Int8Array(data.length);
|
||||
var buffer = new teavm_globals.Int8Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_byteArrayCls(buffer);
|
||||
}
|
||||
function $rt_createShortArray(sz) {
|
||||
return new $rt_shortArrayCls(new Int16Array(sz));
|
||||
return new $rt_shortArrayCls(new teavm_globals.Int16Array(sz));
|
||||
}
|
||||
function $rt_createShortArrayFromData(data) {
|
||||
var buffer = new Int16Array(data.length);
|
||||
var buffer = new teavm_globals.Int16Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_shortArrayCls(buffer);
|
||||
}
|
||||
function $rt_createIntArray(sz) {
|
||||
return new $rt_intArrayCls(new Int32Array(sz));
|
||||
return new $rt_intArrayCls(new teavm_globals.Int32Array(sz));
|
||||
}
|
||||
function $rt_createIntArrayFromData(data) {
|
||||
var buffer = new Int32Array(data.length);
|
||||
var buffer = new teavm_globals.Int32Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_intArrayCls(buffer);
|
||||
}
|
||||
function $rt_createBooleanArray(sz) {
|
||||
return new $rt_booleanArrayCls(new Int8Array(sz));
|
||||
return new $rt_booleanArrayCls(new teavm_globals.Int8Array(sz));
|
||||
}
|
||||
function $rt_createBooleanArrayFromData(data) {
|
||||
var buffer = new Int8Array(data.length);
|
||||
var buffer = new teavm_globals.Int8Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_booleanArrayCls(buffer);
|
||||
}
|
||||
|
||||
function $rt_createFloatArray(sz) {
|
||||
return new $rt_floatArrayCls(new Float32Array(sz));
|
||||
return new $rt_floatArrayCls(new teavm_globals.Float32Array(sz));
|
||||
}
|
||||
function $rt_createFloatArrayFromData(data) {
|
||||
var buffer = new Float32Array(data.length);
|
||||
var buffer = new teavm_globals.Float32Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_floatArrayCls(buffer);
|
||||
}
|
||||
function $rt_createDoubleArray(sz) {
|
||||
return new $rt_doubleArrayCls(new Float64Array(sz));
|
||||
return new $rt_doubleArrayCls(new teavm_globals.Float64Array(sz));
|
||||
}
|
||||
function $rt_createDoubleArrayFromData(data) {
|
||||
var buffer = new Float64Array(data.length);
|
||||
var buffer = new teavm_globals.Float64Array(data.length);
|
||||
buffer.set(data);
|
||||
return new $rt_doubleArrayCls(buffer);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ function $rt_arraycls(cls) {
|
|||
$rt_objcls().call(this);
|
||||
this.data = data;
|
||||
}
|
||||
JavaArray.prototype = Object.create($rt_objcls().prototype);
|
||||
JavaArray.prototype = teavm_globals.Object.create($rt_objcls().prototype);
|
||||
JavaArray.prototype.type = cls;
|
||||
JavaArray.prototype.constructor = JavaArray;
|
||||
JavaArray.prototype.toString = function() {
|
||||
|
@ -239,16 +239,16 @@ var $rt_voidcls = $rt_createPrimitiveCls("void", "V");
|
|||
function $rt_throw(ex) {
|
||||
throw $rt_exception(ex);
|
||||
}
|
||||
var $rt_javaExceptionProp = Symbol("javaException")
|
||||
var $rt_javaExceptionProp = teavm_globals.Symbol("javaException")
|
||||
function $rt_exception(ex) {
|
||||
var err = ex.$jsException;
|
||||
if (!err) {
|
||||
var javaCause = $rt_throwableCause(ex);
|
||||
var jsCause = javaCause !== null ? javaCause.$jsException : undefined;
|
||||
var cause = typeof jsCause === "object" ? { cause : jsCause } : undefined;
|
||||
var jsCause = javaCause !== null ? javaCause.$jsException : void 0;
|
||||
var cause = typeof jsCause === "object" ? { cause : jsCause } : void 0;
|
||||
err = new JavaError("Java exception thrown", cause);
|
||||
if (typeof Error.captureStackTrace === "function") {
|
||||
Error.captureStackTrace(err);
|
||||
if (typeof teavm_globals.Error.captureStackTrace === "function") {
|
||||
teavm_globals.Error.captureStackTrace(err);
|
||||
}
|
||||
err[$rt_javaExceptionProp] = ex;
|
||||
ex.$jsException = err;
|
||||
|
@ -293,7 +293,7 @@ function $rt_createMultiArray(cls, dimensions) {
|
|||
return $rt_createArray(cls, dimensions[first]);
|
||||
}
|
||||
}
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, first));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, first));
|
||||
var firstDim = dimensions[first] | 0;
|
||||
for (i = 0; i < arrays.length; i = (i + 1) | 0) {
|
||||
arrays[i] = $rt_createArray(cls, firstDim);
|
||||
|
@ -301,7 +301,7 @@ function $rt_createMultiArray(cls, dimensions) {
|
|||
return $rt_createMultiArrayImpl(cls, arrays, dimensions, first);
|
||||
}
|
||||
function $rt_createByteMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_bytecls, dimensions);
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ function $rt_createByteMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_bytecls, arrays, dimensions);
|
||||
}
|
||||
function $rt_createCharMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_charcls, dimensions);
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ function $rt_createCharMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_charcls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createBooleanMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_booleancls, dimensions);
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ function $rt_createBooleanMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_booleancls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createShortMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_shortcls, dimensions);
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ function $rt_createShortMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_shortcls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createIntMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_intcls, dimensions);
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ function $rt_createIntMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_intcls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createLongMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_longcls, dimensions);
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ function $rt_createLongMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_longcls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createFloatMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_floatcls, dimensions);
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ function $rt_createFloatMultiArray(dimensions) {
|
|||
return $rt_createMultiArrayImpl($rt_floatcls, arrays, dimensions, 0);
|
||||
}
|
||||
function $rt_createDoubleMultiArray(dimensions) {
|
||||
var arrays = new Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
var arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
|
||||
if (arrays.length === 0) {
|
||||
return $rt_createMultiArray($rt_doublecls, dimensions);
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ var $rt_putStderr = typeof $rt_putStderrCustom === "function"
|
|||
var $rt_packageData = null;
|
||||
function $rt_packages(data) {
|
||||
var i = 0;
|
||||
var packages = new Array(data.length);
|
||||
var packages = new teavm_globals.Array(data.length);
|
||||
for (var j = 0; j < data.length; ++j) {
|
||||
var prefixIndex = data[i++];
|
||||
var prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
|
||||
|
@ -508,7 +508,7 @@ function $rt_metadata(data) {
|
|||
m.supertypes = data[i++];
|
||||
if (m.superclass) {
|
||||
m.supertypes.push(m.superclass);
|
||||
cls.prototype = Object.create(m.superclass.prototype);
|
||||
cls.prototype = teavm_globals.Object.create(m.superclass.prototype);
|
||||
} else {
|
||||
cls.prototype = {};
|
||||
}
|
||||
|
@ -583,7 +583,7 @@ function $rt_wrapFunction4(f) {
|
|||
}
|
||||
function $rt_threadStarter(f) {
|
||||
return function() {
|
||||
var args = Array.prototype.slice.apply(arguments);
|
||||
var args = teavm_globals.Array.prototype.slice.apply(arguments);
|
||||
$rt_startThread(function() {
|
||||
f.apply(this, args);
|
||||
});
|
||||
|
@ -604,7 +604,7 @@ function $rt_mainStarter(f) {
|
|||
var $rt_stringPool_instance;
|
||||
function $rt_stringPool(strings) {
|
||||
$rt_stringClassInit();
|
||||
$rt_stringPool_instance = new Array(strings.length);
|
||||
$rt_stringPool_instance = new teavm_globals.Array(strings.length);
|
||||
for (var i = 0; i < strings.length; ++i) {
|
||||
$rt_stringPool_instance[i] = $rt_intern($rt_str(strings[i]));
|
||||
}
|
||||
|
@ -616,15 +616,15 @@ function $rt_eraseClinit(target) {
|
|||
return target.$clinit = function() {};
|
||||
}
|
||||
|
||||
var $rt_numberConversionBuffer = new ArrayBuffer(16);
|
||||
var $rt_numberConversionView = new DataView($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionFloatArray = new Float32Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionDoubleArray = new Float64Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionIntArray = new Int32Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionBuffer = new teavm_globals.ArrayBuffer(16);
|
||||
var $rt_numberConversionView = new teavm_globals.DataView($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionFloatArray = new teavm_globals.Float32Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionDoubleArray = new teavm_globals.Float64Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionIntArray = new teavm_globals.Int32Array($rt_numberConversionBuffer);
|
||||
|
||||
var $rt_doubleToRawLongBits;
|
||||
var $rt_longBitsToDouble;
|
||||
if (typeof BigInt !== 'function') {
|
||||
if (typeof teavm_globals.BigInt !== 'function') {
|
||||
$rt_doubleToRawLongBits = function(n) {
|
||||
$rt_numberConversionView.setFloat64(0, n, true);
|
||||
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
|
||||
|
@ -634,21 +634,23 @@ if (typeof BigInt !== 'function') {
|
|||
$rt_numberConversionView.setInt32(4, n.hi, true);
|
||||
return $rt_numberConversionView.getFloat64(0, true);
|
||||
}
|
||||
} else if (typeof BigInt64Array !== 'function') {
|
||||
} else if (typeof teavm_globals.BigInt64Array !== 'function') {
|
||||
$rt_doubleToRawLongBits = function(n) {
|
||||
$rt_numberConversionView.setFloat64(0, n, true);
|
||||
var lo = $rt_numberConversionView.getInt32(0, true);
|
||||
var hi = $rt_numberConversionView.getInt32(4, true);
|
||||
return BigInt.asIntN(64, BigInt.asUintN(32, BigInt(lo)) | (BigInt(hi) << BigInt(32)));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
|
||||
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
|
||||
}
|
||||
$rt_longBitsToDouble = function(n) {
|
||||
$rt_numberConversionView.setFloat64(0, n, true);
|
||||
var lo = $rt_numberConversionView.getInt32(0, true);
|
||||
var hi = $rt_numberConversionView.getInt32(4, true);
|
||||
return BigInt.asIntN(64, BigInt.asUintN(32, BigInt(lo)) | (BigInt(hi) << BigInt(32)));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
|
||||
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
|
||||
}
|
||||
} else {
|
||||
var $rt_numberConversionLongArray = new BigInt64Array($rt_numberConversionBuffer);
|
||||
var $rt_numberConversionLongArray = new teavm_globals.BigInt64Array($rt_numberConversionBuffer);
|
||||
$rt_doubleToRawLongBits = function(n) {
|
||||
$rt_numberConversionDoubleArray[0] = n;
|
||||
return $rt_numberConversionLongArray[0];
|
||||
|
@ -679,14 +681,14 @@ function $rt_equalDoubles(a, b) {
|
|||
|
||||
var JavaError;
|
||||
if (typeof Reflect === 'object') {
|
||||
var defaultMessage = Symbol("defaultMessage");
|
||||
var defaultMessage = teavm_globals.Symbol("defaultMessage");
|
||||
JavaError = function JavaError(message, cause) {
|
||||
var self = Reflect.construct(Error, [undefined, cause], JavaError);
|
||||
Object.setPrototypeOf(self, JavaError.prototype);
|
||||
var self = teavm_globals.Reflect.construct(teavm_globals.Error, [void 0, cause], JavaError);
|
||||
teavm_globals.Object.setPrototypeOf(self, JavaError.prototype);
|
||||
self[defaultMessage] = message;
|
||||
return self;
|
||||
}
|
||||
JavaError.prototype = Object.create(Error.prototype, {
|
||||
JavaError.prototype = teavm_globals.Object.create(teavm_globals.Error.prototype, {
|
||||
constructor: {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
|
@ -710,11 +712,13 @@ if (typeof Reflect === 'object') {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
JavaError = Error;
|
||||
JavaError = teavm_globals.Error;
|
||||
}
|
||||
|
||||
function $rt_javaException(e) {
|
||||
return e instanceof Error && typeof e[$rt_javaExceptionProp] === 'object' ? e[$rt_javaExceptionProp] : null;
|
||||
return e instanceof teavm_globals.Error && typeof e[$rt_javaExceptionProp] === 'object'
|
||||
? e[$rt_javaExceptionProp]
|
||||
: null;
|
||||
}
|
||||
function $rt_jsException(e) {
|
||||
return typeof e.$jsException === 'object' ? e.$jsException : null;
|
||||
|
@ -785,7 +789,7 @@ var Long_fromNumber;
|
|||
var Long_toNumber;
|
||||
var Long_hi;
|
||||
var Long_lo;
|
||||
if (typeof BigInt !== "function") {
|
||||
if (typeof teavm_globals.BigInt !== "function") {
|
||||
Long.prototype.toString = function() {
|
||||
var result = [];
|
||||
var n = this;
|
||||
|
@ -796,7 +800,7 @@ if (typeof BigInt !== "function") {
|
|||
var radix = new Long(10, 0);
|
||||
do {
|
||||
var divRem = Long_divRem(n, radix);
|
||||
result.push(String.fromCharCode(48 + divRem[1].lo));
|
||||
result.push(teavm_globals.String.fromCharCode(48 + divRem[1].lo));
|
||||
n = divRem[0];
|
||||
} while (n.lo !== 0 || n.hi !== 0);
|
||||
result = result.reverse().join('');
|
||||
|
@ -830,28 +834,29 @@ if (typeof BigInt !== "function") {
|
|||
return val.lo;
|
||||
}
|
||||
} else {
|
||||
Long_ZERO = BigInt(0);
|
||||
Long_ZERO = teavm_globals.BigInt(0);
|
||||
Long_create = function(lo, hi) {
|
||||
return BigInt.asIntN(64, BigInt.asUintN(64, BigInt(lo))
|
||||
| BigInt.asUintN(64, (BigInt(hi) << BigInt(32))));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, teavm_globals.BigInt(lo))
|
||||
| teavm_globals.BigInt.asUintN(64, (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32))));
|
||||
}
|
||||
Long_fromInt = function(val) {
|
||||
return BigInt.asIntN(64, BigInt(val | 0));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(val | 0));
|
||||
}
|
||||
Long_fromNumber = function(val) {
|
||||
return BigInt.asIntN(64, BigInt(val >= 0 ? Math.floor(val) : Math.ceil(val)));
|
||||
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(
|
||||
val >= 0 ? teavm_globals.Math.floor(val) : teavm_globals.Math.ceil(val)));
|
||||
}
|
||||
Long_toNumber = function(val) {
|
||||
return Number(val);
|
||||
return teavm_globals.Number(val);
|
||||
}
|
||||
Long_hi = function(val) {
|
||||
return Number(BigInt.asIntN(64, val >> BigInt(32))) | 0;
|
||||
return teavm_globals.Number(teavm_globals.BigInt.asIntN(64, val >> teavm_globals.BigInt(32))) | 0;
|
||||
}
|
||||
Long_lo = function(val) {
|
||||
return Number(BigInt.asIntN(32, val)) | 0;
|
||||
return teavm_globals.Number(teavm_globals.BigInt.asIntN(32, val)) | 0;
|
||||
}
|
||||
}
|
||||
var $rt_imul = Math.imul || function(a, b) {
|
||||
var $rt_imul = teavm_globals.Math.imul || function(a, b) {
|
||||
var ah = (a >>> 16) & 0xFFFF;
|
||||
var al = a & 0xFFFF;
|
||||
var bh = (b >>> 16) & 0xFFFF;
|
||||
|
@ -902,8 +907,8 @@ function $rt_charArrayToString(array, offset, count) {
|
|||
var result = "";
|
||||
var limit = offset + count;
|
||||
for (var i = offset; i < limit; i = (i + 1024) | 0) {
|
||||
var next = Math.min(limit, (i + 1024) | 0);
|
||||
result += String.fromCharCode.apply(null, array.subarray(i, next));
|
||||
var next = teavm_globals.Math.min(limit, (i + 1024) | 0);
|
||||
result += teavm_globals.String.fromCharCode.apply(null, array.subarray(i, next));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -916,7 +921,7 @@ function $rt_stringToCharArray(string, begin, dst, dstBegin, count) {
|
|||
}
|
||||
}
|
||||
function $rt_fastStringToCharArray(string) {
|
||||
var array = new Uint16Array(string.length);
|
||||
var array = new teavm_globals.Uint16Array(string.length);
|
||||
for (var i = 0; i < array.length; ++i) {
|
||||
array[i] = string.charCodeAt(i);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ function $rt_startThread(runner, callback) {
|
|||
}
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback(result);
|
||||
} else if (result instanceof Error) {
|
||||
} else if (result instanceof teavm_globals.Error) {
|
||||
throw result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,14 +46,14 @@ TeaVMThread.prototype.suspend = function(callback) {
|
|||
};
|
||||
TeaVMThread.prototype.start = function(callback) {
|
||||
if (this.status !== 3) {
|
||||
throw new Error("Thread already started");
|
||||
throw new teavm_globals.Error("Thread already started");
|
||||
}
|
||||
if ($rt_currentNativeThread !== null) {
|
||||
throw new Error("Another thread is running");
|
||||
throw new teavm_globals.Error("Another thread is running");
|
||||
}
|
||||
this.status = 0;
|
||||
this.completeCallback = callback ? callback : function(result) {
|
||||
if (result instanceof Error) {
|
||||
this.completeCallback = callback ? callback : (result) => {
|
||||
if (result instanceof teavm_globals.Error) {
|
||||
throw result;
|
||||
}
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ TeaVMThread.prototype.start = function(callback) {
|
|||
};
|
||||
TeaVMThread.prototype.resume = function() {
|
||||
if ($rt_currentNativeThread !== null) {
|
||||
throw new Error("Another thread is running");
|
||||
throw new teavm_globals.Error("Another thread is running");
|
||||
}
|
||||
this.status = 2;
|
||||
this.run();
|
||||
|
@ -80,9 +80,7 @@ TeaVMThread.prototype.run = function() {
|
|||
var self = this;
|
||||
var callback = this.suspendCallback;
|
||||
this.suspendCallback = null;
|
||||
callback(function() {
|
||||
self.resume();
|
||||
});
|
||||
callback(() => self.resume());
|
||||
} else if (this.status === 0) {
|
||||
this.completeCallback(result);
|
||||
}
|
||||
|
@ -99,7 +97,7 @@ function $rt_resuming() {
|
|||
function $rt_suspend(callback) {
|
||||
var nativeThread = $rt_nativeThread();
|
||||
if (nativeThread === null) {
|
||||
throw new Error("Suspension point reached from non-threading context (perhaps, from native JS method).");
|
||||
throw new teavm_globals.Error("Suspension point reached from non-threading context (perhaps, from native JS method).");
|
||||
}
|
||||
return nativeThread.suspend(callback);
|
||||
}
|
||||
|
@ -111,5 +109,5 @@ function $rt_nativeThread() {
|
|||
return $rt_currentNativeThread;
|
||||
}
|
||||
function $rt_invalidPointer() {
|
||||
throw new Error("Invalid recorded state");
|
||||
throw new teavm_globals.Error("Invalid recorded state");
|
||||
}
|
|
@ -25,12 +25,12 @@ public class JSExceptionsGenerator implements Injector {
|
|||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "getJavaException":
|
||||
context.getWriter().append("$rt_javaException(");
|
||||
context.getWriter().appendFunction("$rt_javaException").append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(")");
|
||||
break;
|
||||
case "getJSException":
|
||||
context.getWriter().append("$rt_jsException(");
|
||||
context.getWriter().appendFunction("$rt_jsException").append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(")");
|
||||
break;
|
||||
|
|
|
@ -44,7 +44,7 @@ public class JSWrapperGenerator implements Injector, DependencyPlugin {
|
|||
context.getWriter().append("(");
|
||||
}
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(" instanceof ").append("$rt_objcls").append("()");
|
||||
context.getWriter().append(" instanceof ").appendFunction("$rt_objcls").append("()");
|
||||
if (context.getPrecedence().ordinal() >= Precedence.COMPARISON.ordinal()) {
|
||||
context.getWriter().append(")");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.teavm.backend.javascript.spi.Generator;
|
|||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributor;
|
||||
import org.teavm.backend.javascript.spi.VirtualMethodContributorContext;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplate;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
|
@ -36,53 +38,30 @@ import org.teavm.model.ValueType;
|
|||
public class AsyncMethodGenerator implements Generator, DependencyPlugin, VirtualMethodContributor {
|
||||
private static final MethodDescriptor completeMethod = new MethodDescriptor("complete", Object.class, void.class);
|
||||
private static final MethodDescriptor errorMethod = new MethodDescriptor("error", Throwable.class, void.class);
|
||||
private JavaScriptTemplate template;
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
MethodReference asyncRef = getAsyncReference(context.getClassSource(), methodRef);
|
||||
writer.append("var thread").ws().append('=').ws().append("$rt_nativeThread();").softNewLine();
|
||||
writer.append("var javaThread").ws().append('=').ws().append("$rt_getThread();").softNewLine();
|
||||
writer.append("if").ws().append("(thread.isResuming())").ws().append("{").indent().softNewLine();
|
||||
writer.append("thread.status").ws().append("=").ws().append("0;").softNewLine();
|
||||
writer.append("var result").ws().append("=").ws().append("thread.attribute;").softNewLine();
|
||||
writer.append("if").ws().append("(result instanceof Error)").ws().append("{").indent().softNewLine();
|
||||
writer.append("throw result;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return result;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
||||
writer.append("var callback").ws().append("=").ws().append("function()").ws().append("{};").softNewLine();
|
||||
writer.append("callback.").appendMethod(completeMethod).ws().append("=").ws()
|
||||
.append("function(val)").ws().append("{").indent().softNewLine();
|
||||
writer.append("thread.attribute").ws().append('=').ws().append("val;").softNewLine();
|
||||
writer.append("$rt_setThread(javaThread);").softNewLine();
|
||||
writer.append("thread.resume();").softNewLine();
|
||||
writer.outdent().append("};").softNewLine();
|
||||
writer.append("callback.").appendMethod(errorMethod).ws().append("=").ws()
|
||||
.append("function(e)").ws().append("{").indent().softNewLine();
|
||||
writer.append("thread.attribute").ws().append('=').ws().append("$rt_exception(e);").softNewLine();
|
||||
writer.append("$rt_setThread(javaThread);").softNewLine();
|
||||
writer.append("thread.resume();").softNewLine();
|
||||
writer.outdent().append("};").softNewLine();
|
||||
writer.append("callback").ws().append("=").ws().appendMethodBody(AsyncCallbackWrapper.class, "create",
|
||||
AsyncCallback.class, AsyncCallbackWrapper.class).append("(callback);").softNewLine();
|
||||
writer.append("thread.suspend(function()").ws().append("{").indent().softNewLine();
|
||||
writer.append("try").ws().append("{").indent().softNewLine();
|
||||
writer.appendMethodBody(asyncRef).append('(');
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||
int start = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
||||
for (int i = start; i <= methodRef.parameterCount(); ++i) {
|
||||
writer.append(context.getParameterName(i));
|
||||
writer.append(',').ws();
|
||||
if (template == null) {
|
||||
var templateFactory = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource());
|
||||
template = templateFactory.createFromResource("org/teavm/platform/plugin/Async.js");
|
||||
}
|
||||
writer.append("callback);").softNewLine();
|
||||
writer.outdent().append("}").ws().append("catch($e)").ws().append("{").indent().softNewLine();
|
||||
writer.append("callback.").appendMethod(errorMethod).append("($rt_exception($e));")
|
||||
.softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.outdent().append("});").softNewLine();
|
||||
writer.append("return null;").softNewLine();
|
||||
MethodReference asyncRef = getAsyncReference(context.getClassSource(), methodRef);
|
||||
template.builder("asyncMethod")
|
||||
.withContext(context)
|
||||
.withFragment("callMethod", (w, p) -> {
|
||||
w.appendMethodBody(asyncRef).append('(');
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||
int start = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
||||
for (int i = start; i <= methodRef.parameterCount(); ++i) {
|
||||
w.append(context.getParameterName(i));
|
||||
w.append(',').ws();
|
||||
}
|
||||
w.append("callback);").softNewLine();
|
||||
})
|
||||
.build()
|
||||
.write(writer, 0);
|
||||
}
|
||||
|
||||
private MethodReference getAsyncReference(ClassReaderSource classSource, MethodReference methodRef) {
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.teavm.backend.javascript.spi.Generator;
|
|||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.backend.javascript.spi.Injector;
|
||||
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplate;
|
||||
import org.teavm.backend.javascript.templating.JavaScriptTemplateFactory;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
|
@ -36,6 +38,8 @@ import org.teavm.platform.PlatformClass;
|
|||
import org.teavm.platform.PlatformRunnable;
|
||||
|
||||
public class PlatformGenerator implements Generator, Injector, DependencyPlugin {
|
||||
private JavaScriptTemplate template;
|
||||
|
||||
@Override
|
||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||
switch (method.getReference().getName()) {
|
||||
|
@ -90,37 +94,37 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "newInstanceImpl":
|
||||
generateNewInstance(context, writer);
|
||||
break;
|
||||
case "prepareNewInstance":
|
||||
generatePrepareNewInstance(context, writer);
|
||||
break;
|
||||
case "lookupClass":
|
||||
generateLookup(context, writer);
|
||||
break;
|
||||
case "clone":
|
||||
generateClone(context, writer);
|
||||
break;
|
||||
case "startThread":
|
||||
generateSchedule(context, writer, false);
|
||||
break;
|
||||
case "schedule":
|
||||
generateSchedule(context, writer, true);
|
||||
break;
|
||||
case "getEnumConstants":
|
||||
generateEnumConstants(context, writer);
|
||||
break;
|
||||
case "getAnnotations":
|
||||
generateAnnotations(context, writer);
|
||||
break;
|
||||
default:
|
||||
generateWithTemplate(context, writer, methodRef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateWithTemplate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
if (template == null) {
|
||||
template = new JavaScriptTemplateFactory(context.getClassLoader(), context.getClassSource())
|
||||
.createFromResource("org/teavm/platform/plugin/Platform.js");
|
||||
}
|
||||
template.builder(methodRef.getName()).withContext(context).build().write(writer, 0);
|
||||
}
|
||||
|
||||
private void generatePrepareNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
MethodDependencyInfo newInstanceMethod = context.getDependency().getMethod(
|
||||
new MethodReference(Platform.class, "newInstanceImpl", PlatformClass.class, Object.class));
|
||||
writer.append("var c").ws().append("=").ws().append("'$$constructor$$';").softNewLine();
|
||||
writer.append("let c").ws().append("=").ws().append("'$$constructor$$';").softNewLine();
|
||||
if (newInstanceMethod != null) {
|
||||
for (String clsName : newInstanceMethod.getResult().getTypes()) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
|
@ -136,71 +140,21 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
}
|
||||
}
|
||||
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String cls = context.getParameterName(1);
|
||||
|
||||
writer.append("if").ws().append("($rt_resuming())").ws().append("{").indent().softNewLine();
|
||||
writer.append("var $r = $rt_nativeThread().pop();").softNewLine();
|
||||
writer.append(cls + ".$$constructor$$($r);").softNewLine();
|
||||
writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $rt_nativeThread().push($r);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return $r;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
||||
writer.append("if").ws().append("(!").append(cls).append(".hasOwnProperty('$$constructor$$'))")
|
||||
.ws().append("{").indent().softNewLine();
|
||||
writer.append("return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
||||
writer.append("var $r").ws().append('=').ws().append("new ").append(cls).append("();").softNewLine();
|
||||
writer.append(cls).append(".$$constructor$$($r);").softNewLine();
|
||||
writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $rt_nativeThread().push($r);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return $r;").softNewLine();
|
||||
}
|
||||
|
||||
private void generateLookup(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String param = context.getParameterName(1);
|
||||
writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent();
|
||||
writer.append("switch").ws().append("(").appendFunction("$rt_ustr").append("(" + param + "))")
|
||||
.ws().append("{").softNewLine().indent();
|
||||
for (String name : context.getClassSource().getClassNames()) {
|
||||
writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ")
|
||||
writer.append("case \"" + name + "\":").ws().appendClass(name).append(".$clinit();").ws()
|
||||
.append("return ").appendClass(name).append(";").softNewLine();
|
||||
}
|
||||
writer.append("default: return null;").softNewLine();
|
||||
writer.append("default:").ws().append("return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String obj = context.getParameterName(1);
|
||||
writer.append("var copy").ws().append("=").ws().append("new ").append(obj).append(".constructor();")
|
||||
.softNewLine();
|
||||
writer.append("for").ws().append("(var field in " + obj + ")").ws().append("{").softNewLine().indent();
|
||||
writer.append("if").ws().append("(!" + obj + ".hasOwnProperty(field))").ws().append("{").softNewLine().indent();
|
||||
writer.append("continue;").softNewLine().outdent().append("}").softNewLine();
|
||||
writer.append("copy[field]").ws().append("=").ws().append(obj).append("[field];")
|
||||
.softNewLine().outdent().append("}").softNewLine();
|
||||
writer.append("return copy;").softNewLine();
|
||||
}
|
||||
|
||||
private void generateSchedule(GeneratorContext context, SourceWriter writer, boolean timeout) throws IOException {
|
||||
MethodReference launchRef = new MethodReference(Platform.class, "launchThread",
|
||||
PlatformRunnable.class, void.class);
|
||||
String runnable = context.getParameterName(1);
|
||||
writer.append("return setTimeout(function()").ws().append("{").indent().softNewLine();
|
||||
if (timeout) {
|
||||
writer.appendMethodBody(launchRef);
|
||||
} else {
|
||||
writer.append("$rt_threadStarter(").appendMethodBody(launchRef).append(")");
|
||||
}
|
||||
writer.append("(").append(runnable).append(");").softNewLine();
|
||||
writer.outdent().append("},").ws().append(timeout ? context.getParameterName(2) : "0")
|
||||
.append(");").softNewLine();
|
||||
}
|
||||
|
||||
private void generateEnumConstants(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var c").ws().append("=").ws().append("'$$enumConstants$$';").softNewLine();
|
||||
writer.append("let c").ws().append("=").ws().append("'$$enumConstants$$';").softNewLine();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("values",
|
||||
|
@ -214,8 +168,8 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
|
||||
MethodReference selfRef = new MethodReference(Platform.class, "getEnumConstants",
|
||||
PlatformClass.class, Enum[].class);
|
||||
writer.appendMethodBody(selfRef).ws().append("=").ws().append("function(cls)").ws().append("{").softNewLine()
|
||||
.indent();
|
||||
writer.appendMethodBody(selfRef).ws().append("=").ws().append("cls").ws().append("=>").ws()
|
||||
.append("{").softNewLine().indent();
|
||||
writer.append("if").ws().append("(!cls.hasOwnProperty(c))").ws().append("{").indent().softNewLine();
|
||||
writer.append("return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
@ -231,7 +185,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
}
|
||||
|
||||
private void generateAnnotations(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var c").ws().append("=").ws().append("'$$annotations$$';").softNewLine();
|
||||
writer.append("let c").ws().append("=").ws().append("'$$annotations$$';").softNewLine();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
ClassReader annotCls = context.getClassSource().get(clsName + "$$__annotations__$$");
|
||||
if (annotCls != null) {
|
||||
|
@ -244,8 +198,8 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
|
||||
MethodReference selfRef = new MethodReference(Platform.class, "getAnnotations", PlatformClass.class,
|
||||
Annotation[].class);
|
||||
writer.appendMethodBody(selfRef).ws().append("=").ws().append("function(cls)").ws().append("{").softNewLine()
|
||||
.indent();
|
||||
writer.appendMethodBody(selfRef).ws().append("=").ws().append("cls").ws().append("=>").ws()
|
||||
.append("{").softNewLine().indent();
|
||||
writer.append("if").ws().append("(!cls.hasOwnProperty(c))").ws().append("{").indent().softNewLine();
|
||||
writer.append("return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
|
|
@ -24,8 +24,9 @@ import org.teavm.model.MethodReference;
|
|||
class ResourceAccessorGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
writer.append("var result = [];").softNewLine();
|
||||
writer.append("for (var key in ").append(context.getParameterName(1)).append(") {").indent().softNewLine();
|
||||
writer.append("let result").ws().append("=").ws().append("[];").softNewLine();
|
||||
writer.append("for").ws().append("(let key in ").append(context.getParameterName(1)).append(")").ws()
|
||||
.append("{").indent().softNewLine();
|
||||
writer.append("result.push(key);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return result;").softNewLine();
|
||||
|
|
|
@ -95,7 +95,7 @@ class ResourceAccessorInjector implements Injector {
|
|||
context.getWriter().append('(');
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().ws().append("!==").ws().append("null").ws().append("?").ws();
|
||||
context.getWriter().append("$rt_ustr(");
|
||||
context.getWriter().appendFunction("$rt_ustr").append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(")").ws().append(':').ws().append("null)");
|
||||
break;
|
||||
|
@ -114,7 +114,7 @@ class ResourceAccessorInjector implements Injector {
|
|||
return;
|
||||
}
|
||||
}
|
||||
context.getWriter().append("[$rt_ustr(");
|
||||
context.getWriter().append("[").appendFunction("$rt_ustr").append("(");
|
||||
context.writeExpr(property);
|
||||
context.getWriter().append(")]");
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ class ResourceAccessorInjector implements Injector {
|
|||
context.getWriter().append('"');
|
||||
return;
|
||||
}
|
||||
context.getWriter().append("$rt_ustr(");
|
||||
context.getWriter().appendFunction("$rt_ustr").append("(");
|
||||
context.writeExpr(expr);
|
||||
context.getWriter().append(")");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function asyncMethod() {
|
||||
let thread = $rt_nativeThread();
|
||||
let javaThread = $rt_getThread();
|
||||
if (thread.isResuming()) {
|
||||
thread.status = 0;
|
||||
let result = thread.attribute;
|
||||
if (result instanceof teavm_globals.Error) {
|
||||
throw result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let callback = function() {};
|
||||
callback[teavm_javaVirtualMethod("complete(Ljava/lang/Object;)V")] = val => {
|
||||
thread.attribute = val;
|
||||
$rt_setThread(javaThread);
|
||||
thread.resume();
|
||||
}
|
||||
callback[teavm_javaVirtualMethod("error(Ljava/lang/Throwable;)V")] = e => {
|
||||
thread.attribute = $rt_exception(e);
|
||||
$rt_setThread(javaThread);
|
||||
thread.resume();
|
||||
}
|
||||
callback = teavm_javaMethod("org.teavm.platform.plugin.AsyncCallbackWrapper",
|
||||
"create(Lorg/teavm/interop/AsyncCallback;)Lorg/teavm/platform/plugin/AsyncCallbackWrapper;")(callback);
|
||||
thread.suspend(() => {
|
||||
try {
|
||||
teavm_fragment("callMethod");
|
||||
} catch ($e) {
|
||||
callback[teavm_javaVirtualMethod("error(Ljava/lang/Throwable;)V")]($e);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
function newInstanceImpl(cls) {
|
||||
let thread = $rt_nativeThread();
|
||||
if ($rt_resuming()) {
|
||||
let r = thread.pop();
|
||||
cls.$$constructor$$(r);
|
||||
if ($rt_suspending()) {
|
||||
return thread.push(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!cls.hasOwnProperty("$$constructor$$")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let r = new cls();
|
||||
cls.$$constructor$$(r);
|
||||
if ($rt_suspending()) {
|
||||
thread.push(r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function clone(obj) {
|
||||
let copy = new obj.constructor();
|
||||
for (let field in obj) {
|
||||
if (obj.hasOwnProperty(field)) {
|
||||
copy[field] = obj[field];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
function startThread(runnable) {
|
||||
teavm_globals.setTimeout(() => {
|
||||
$rt_threadStarter(teavm_javaMethod("org.teavm.platform.Platform",
|
||||
"launchThread(Lorg/teavm/platform/PlatformRunnable;)V"))(runnable);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function schedule(runnable, timeout) {
|
||||
teavm_globals.setTimeout(() => {
|
||||
teavm_javaMethod("org.teavm.platform.Platform",
|
||||
"launchThread(Lorg/teavm/platform/PlatformRunnable;)V")(runnable);
|
||||
}, timeout);
|
||||
}
|
|
@ -65,8 +65,8 @@ class TestExceptionPlugin implements TeaVMPlugin {
|
|||
private void renderExceptionMessage(SourceWriter writer) throws IOException {
|
||||
writer.appendClass("java.lang.Throwable").append(".prototype.getMessage").ws().append("=").ws()
|
||||
.append("function()").ws().append("{").indent().softNewLine();
|
||||
writer.append("return $rt_ustr(this.").appendMethod("getMessage", String.class).append("());")
|
||||
.softNewLine();
|
||||
writer.append("return ").appendFunction("$rt_ustr").append("(this.")
|
||||
.appendMethod("getMessage", String.class).append("());").softNewLine();
|
||||
writer.outdent().append("};").newLine();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user