mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
html4j: add toString method to enums passed to JavaScript via html4j API
This commit is contained in:
parent
c4ada881d2
commit
1993060824
|
@ -25,10 +25,13 @@ public class HTML4JPlugin implements TeaVMPlugin {
|
||||||
if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
|
if (host.getExtension(TeaVMJavaScriptHost.class) == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
host.add(new JavaScriptBodyDependency());
|
|
||||||
|
JavaScriptBodyDependency bodyDependency = new JavaScriptBodyDependency();
|
||||||
|
host.add(bodyDependency);
|
||||||
host.add(new JavaScriptBodyTransformer());
|
host.add(new JavaScriptBodyTransformer());
|
||||||
host.add(new JCLHacks());
|
host.add(new JCLHacks());
|
||||||
|
|
||||||
host.getExtension(TeaVMJavaScriptHost.class).add(new JavaScriptResourceInterceptor());
|
host.getExtension(TeaVMJavaScriptHost.class).add(new JavaScriptResourceInterceptor());
|
||||||
|
host.getExtension(TeaVMJavaScriptHost.class).add(new JavaScriptObjectEnhancer(bodyDependency));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,11 @@ import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
private DependencyNode allClassesNode;
|
private DependencyNode allClassesNode;
|
||||||
private Map<MethodReference, Set<MethodReference>> achievedMethods = new HashMap<>();
|
private Map<MethodReference, Set<MethodReference>> reachedMethods = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyAgent agent) {
|
public void started(DependencyAgent agent) {
|
||||||
|
@ -50,9 +47,13 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
allClassesNode.setTag("JavaScriptBody:global");
|
allClassesNode.setTag("JavaScriptBody:global");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OneDirectionalConnection implements DependencyConsumer {
|
public String[] getClassesPassedToJavaScript() {
|
||||||
|
return allClassesNode.getTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class OneDirectionalConnection implements DependencyConsumer {
|
||||||
private DependencyNode target;
|
private DependencyNode target;
|
||||||
public OneDirectionalConnection(DependencyNode target) {
|
OneDirectionalConnection(DependencyNode target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
@Override public void consume(DependencyType type) {
|
@Override public void consume(DependencyType type) {
|
||||||
|
@ -71,14 +72,14 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
Set<MethodReference> methodsToAchieve = achievedMethods.get(method.getReference());
|
Set<MethodReference> methodsToReach = reachedMethods.get(method.getReference());
|
||||||
if (methodsToAchieve != null) {
|
if (methodsToReach != null) {
|
||||||
for (MethodReference methodToAchieve : methodsToAchieve) {
|
for (MethodReference methodToReach : methodsToReach) {
|
||||||
agent.linkMethod(methodToAchieve, location);
|
agent.linkMethod(methodToReach, location);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
achievedMethods.put(method.getReference(), new HashSet<MethodReference>());
|
reachedMethods.put(method.getReference(), new HashSet<>());
|
||||||
if (method.isMissing()) {
|
if (method.isMissing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,6 +95,15 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < method.getParameterCount(); ++i) {
|
for (int i = 0; i < method.getParameterCount(); ++i) {
|
||||||
method.getVariable(i).connect(allClassesNode);
|
method.getVariable(i).connect(allClassesNode);
|
||||||
|
method.getVariable(i).addConsumer(type -> {
|
||||||
|
if (agent.getClassSource().isSuperType("java.lang.Enum", type.getName()).orElse(false)) {
|
||||||
|
MethodReference toStringMethod = new MethodReference(type.getName(), "toString",
|
||||||
|
ValueType.parse(String.class));
|
||||||
|
MethodDependency dependency = agent.linkMethod(toStringMethod, location);
|
||||||
|
dependency.getVariable(0).propagate(type);
|
||||||
|
dependency.use();
|
||||||
|
}
|
||||||
|
});
|
||||||
allClassesNode.addConsumer(new OneDirectionalConnection(method.getVariable(i).getArrayItem()));
|
allClassesNode.addConsumer(new OneDirectionalConnection(method.getVariable(i).getArrayItem()));
|
||||||
allClassesNode.addConsumer(new OneDirectionalConnection(method.getVariable(i).getArrayItem()
|
allClassesNode.addConsumer(new OneDirectionalConnection(method.getVariable(i).getArrayItem()
|
||||||
.getArrayItem()));
|
.getArrayItem()));
|
||||||
|
@ -157,11 +167,11 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GeneratorJsCallback extends JsCallback {
|
class GeneratorJsCallback extends JsCallback {
|
||||||
private DependencyAgent agent;
|
private DependencyAgent agent;
|
||||||
private MethodDependency caller;
|
private MethodDependency caller;
|
||||||
private CallLocation location;
|
private CallLocation location;
|
||||||
public GeneratorJsCallback(DependencyAgent agent, MethodDependency caller, CallLocation location) {
|
GeneratorJsCallback(DependencyAgent agent, MethodDependency caller, CallLocation location) {
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
this.caller = caller;
|
this.caller = caller;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
@ -171,7 +181,7 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
|
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
|
||||||
MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc);
|
MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc);
|
||||||
MethodDependency methodDep = agent.linkMethod(ref, location);
|
MethodDependency methodDep = agent.linkMethod(ref, location);
|
||||||
achievedMethods.get(caller.getReference()).add(ref);
|
reachedMethods.get(caller.getReference()).add(ref);
|
||||||
if (!methodDep.isMissing()) {
|
if (!methodDep.isMissing()) {
|
||||||
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
||||||
methodDep.use();
|
methodDep.use();
|
||||||
|
@ -186,12 +196,12 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VirtualCallbackConsumer implements DependencyConsumer {
|
class VirtualCallbackConsumer implements DependencyConsumer {
|
||||||
private DependencyAgent agent;
|
private DependencyAgent agent;
|
||||||
private MethodReader superMethod;
|
private MethodReader superMethod;
|
||||||
private ClassReader superClass;
|
private ClassReader superClass;
|
||||||
private MethodDependency caller;
|
private MethodDependency caller;
|
||||||
public VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod, MethodDependency caller) {
|
VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod, MethodDependency caller) {
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
this.superMethod = superMethod;
|
this.superMethod = superMethod;
|
||||||
this.caller = caller;
|
this.caller = caller;
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.html4j;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
|
import org.teavm.backend.javascript.rendering.RenderingManager;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.vm.BuildTarget;
|
||||||
|
import org.teavm.vm.spi.RendererListener;
|
||||||
|
|
||||||
|
public class JavaScriptObjectEnhancer implements RendererListener {
|
||||||
|
private ClassReaderSource classSource;
|
||||||
|
private SourceWriter writer;
|
||||||
|
private JavaScriptBodyDependency dependencyListener;
|
||||||
|
|
||||||
|
public JavaScriptObjectEnhancer(JavaScriptBodyDependency dependencyListener) {
|
||||||
|
this.dependencyListener = dependencyListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin(RenderingManager context, BuildTarget buildTarget) throws IOException {
|
||||||
|
classSource = context.getClassSource();
|
||||||
|
writer = context.getWriter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void complete() throws IOException {
|
||||||
|
for (String className : dependencyListener.getClassesPassedToJavaScript()) {
|
||||||
|
if (classSource.isSuperType("java.lang.Enum", className).orElse(false)) {
|
||||||
|
MethodReference toStringMethod = new MethodReference(className, "toString",
|
||||||
|
ValueType.parse(String.class));
|
||||||
|
writer.appendClass(className).append(".prototype.toString").ws().append("=").ws()
|
||||||
|
.append("function()").ws().append("{").indent().newLine();
|
||||||
|
writer.append("return $rt_ustr(").appendMethodBody(toStringMethod).append("(this));").softNewLine();
|
||||||
|
writer.outdent().append("};").softNewLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -236,7 +236,7 @@ public class JavaScriptTCKTest extends JavaScriptBodyTest {
|
||||||
|
|
||||||
@Test @Override
|
@Test @Override
|
||||||
public void toStringOfAnEnum() {
|
public void toStringOfAnEnum() {
|
||||||
//super.toStringOfAnEnum();
|
super.toStringOfAnEnum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Override
|
@Test @Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user