mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Make JS function out of JS object when casting to JSFunctor interface
This commit is contained in:
parent
5035c58533
commit
6551f3eb68
|
@ -61,6 +61,7 @@ import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
import org.teavm.model.instructions.CastInstruction;
|
||||||
import org.teavm.model.instructions.ExitInstruction;
|
import org.teavm.model.instructions.ExitInstruction;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
@ -252,25 +253,55 @@ class JSClassProcessor {
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
if (!(insn instanceof InvokeInstruction)) {
|
if (insn instanceof CastInstruction) {
|
||||||
continue;
|
replacement.clear();
|
||||||
}
|
CallLocation callLocation = new CallLocation(methodToProcess.getReference(), insn.getLocation());
|
||||||
InvokeInstruction invoke = (InvokeInstruction) insn;
|
if (processCast((CastInstruction) insn, callLocation)) {
|
||||||
|
insn.insertNextAll(replacement);
|
||||||
|
insn.delete();
|
||||||
|
}
|
||||||
|
} else if (insn instanceof InvokeInstruction) {
|
||||||
|
InvokeInstruction invoke = (InvokeInstruction) insn;
|
||||||
|
|
||||||
MethodReader method = getMethod(invoke.getMethod());
|
MethodReader method = getMethod(invoke.getMethod());
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CallLocation callLocation = new CallLocation(methodToProcess.getReference(), insn.getLocation());
|
CallLocation callLocation = new CallLocation(methodToProcess.getReference(), insn.getLocation());
|
||||||
replacement.clear();
|
replacement.clear();
|
||||||
if (processInvocation(method, callLocation, invoke, methodToProcess)) {
|
if (processInvocation(method, callLocation, invoke, methodToProcess)) {
|
||||||
insn.insertNextAll(replacement);
|
insn.insertNextAll(replacement);
|
||||||
insn.delete();
|
insn.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean processCast(CastInstruction cast, CallLocation location) {
|
||||||
|
if (!(cast.getTargetType() instanceof ValueType.Object)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String targetClassName = ((ValueType.Object) cast.getTargetType()).getClassName();
|
||||||
|
if (!typeHelper.isJavaScriptClass(targetClassName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ClassReader targetClass = classSource.get(targetClassName);
|
||||||
|
if (targetClass.getAnnotations().get(JSFunctor.class.getName()) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable result = marshaller.unwrapFunctor(location, cast.getValue(), targetClass);
|
||||||
|
AssignInstruction assign = new AssignInstruction();
|
||||||
|
assign.setLocation(location.getSourceLocation());
|
||||||
|
assign.setAssignee(result);
|
||||||
|
assign.setReceiver(cast.getReceiver());
|
||||||
|
replacement.add(assign);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean processInvocation(MethodReader method, CallLocation callLocation, InvokeInstruction invoke,
|
private boolean processInvocation(MethodReader method, CallLocation callLocation, InvokeInstruction invoke,
|
||||||
MethodHolder methodToProcess) {
|
MethodHolder methodToProcess) {
|
||||||
if (method.getAnnotations().get(JSBody.class.getName()) != null) {
|
if (method.getAnnotations().get(JSBody.class.getName()) != null) {
|
||||||
|
|
|
@ -76,8 +76,8 @@ public class JSNativeGenerator implements Injector, DependencyPlugin, Generator
|
||||||
String thisName = context.getParameterName(1);
|
String thisName = context.getParameterName(1);
|
||||||
String methodName = context.getParameterName(2);
|
String methodName = context.getParameterName(2);
|
||||||
|
|
||||||
writer.append("if").ws().append("(").append(thisName).ws().append("===").ws().append("null)").ws()
|
writer.append("if").ws().append("(typeof ").append(thisName).ws().append("!==").ws().append("\"function\")")
|
||||||
.append("return null;").softNewLine();
|
.ws().append("return ").append(thisName).append(";").softNewLine();
|
||||||
writer.append("var result").ws().append("=").ws().append("{};").softNewLine();
|
writer.append("var result").ws().append("=").ws().append("{};").softNewLine();
|
||||||
writer.append("result[").append(methodName).append("]").ws().append("=").ws().append(thisName)
|
writer.append("result[").append(methodName).append("]").ws().append("=").ws().append(thisName)
|
||||||
.append(";").softNewLine();
|
.append(";").softNewLine();
|
||||||
|
|
|
@ -462,7 +462,7 @@ class JSValueMarshaller {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable unwrapFunctor(CallLocation location, Variable var, ClassReader type) {
|
Variable unwrapFunctor(CallLocation location, Variable var, ClassReader type) {
|
||||||
if (!isProperFunctor(type)) {
|
if (!isProperFunctor(type)) {
|
||||||
diagnostics.error(location, "Wrong functor: {{c0}}", type.getName());
|
diagnostics.error(location, "Wrong functor: {{c0}}", type.getName());
|
||||||
return var;
|
return var;
|
||||||
|
|
|
@ -83,6 +83,12 @@ public class FunctorTest {
|
||||||
assertEquals("q,w", function.foo("q", "w"));
|
assertEquals("q,w", function.foo("q", "w"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void castToFunctor() {
|
||||||
|
JSBiFunction f = getBiFunctionAsObject().cast();
|
||||||
|
assertEquals(23042, f.foo(23, 42));
|
||||||
|
}
|
||||||
|
|
||||||
@JSBody(params = { "f", "a", "b" }, script = "return '(' + f(a, b) + ')';")
|
@JSBody(params = { "f", "a", "b" }, script = "return '(' + f(a, b) + ')';")
|
||||||
private static native String testMethod(JSBiFunction f, int a, int b);
|
private static native String testMethod(JSBiFunction f, int a, int b);
|
||||||
|
|
||||||
|
@ -95,6 +101,12 @@ public class FunctorTest {
|
||||||
+ "};")
|
+ "};")
|
||||||
private static native JSBiFunction getBiFunction();
|
private static native JSBiFunction getBiFunction();
|
||||||
|
|
||||||
|
@JSBody(script = ""
|
||||||
|
+ "return function(a, b) {"
|
||||||
|
+ "return a * 1000 + b;"
|
||||||
|
+ "};")
|
||||||
|
private static native JSObject getBiFunctionAsObject();
|
||||||
|
|
||||||
@JSBody(script = ""
|
@JSBody(script = ""
|
||||||
+ "return function(a, b) {"
|
+ "return function(a, b) {"
|
||||||
+ "return a + ',' + b;"
|
+ "return a + ',' + b;"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user