Fix bug in JSO that led to improper generation of functor wrappers

This commit is contained in:
konsoletyper 2014-10-05 17:12:45 +04:00
parent 137c7f633d
commit 0c4aeec667
4 changed files with 28 additions and 49 deletions

View File

@ -17,7 +17,6 @@ package org.teavm.jso;
import java.util.Iterator;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.InjectedBy;
/**
@ -54,7 +53,7 @@ public final class JS {
@InjectedBy(JSNativeGenerator.class)
public static native JSObject getGlobal();
@GeneratedBy(JSNativeGenerator.class)
@InjectedBy(JSNativeGenerator.class)
public static native JSObject wrap(String str);
@InjectedBy(JSNativeGenerator.class)
@ -116,7 +115,7 @@ public final class JS {
@InjectedBy(JSNativeGenerator.class)
public static native double unwrapDouble(JSObject obj);
@GeneratedBy(JSNativeGenerator.class)
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native String unwrapString(JSObject obj);

View File

@ -21,12 +21,9 @@ import org.teavm.dependency.*;
import org.teavm.javascript.ast.ConstantExpr;
import org.teavm.javascript.ast.Expr;
import org.teavm.javascript.ast.InvocationExpr;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.javascript.ni.Injector;
import org.teavm.javascript.ni.InjectorContext;
import org.teavm.model.ClassReader;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference;
@ -34,18 +31,7 @@ import org.teavm.model.MethodReference;
*
* @author Alexey Andreev
*/
public class JSNativeGenerator implements Generator, Injector, DependencyPlugin {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
throws IOException {
if (methodRef.getName().equals("wrap")) {
generateWrapString(context, writer);
} else if (methodRef.getName().equals("unwrapString")) {
writer.append("return $rt_str(").append(context.getParameterName(1)).append(");")
.softNewLine();
}
}
public class JSNativeGenerator implements Injector, DependencyPlugin {
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
SourceWriter writer = context.getWriter();
@ -101,11 +87,22 @@ public class JSNativeGenerator implements Generator, Injector, DependencyPlugin
writer.append("))");
break;
case "wrap":
if (methodRef.getDescriptor().parameterType(0).isObject("java.lang.String")) {
writer.append("$rt_ustr(");
context.writeExpr(context.getArgument(0));
writer.append(")");
} else {
context.writeExpr(context.getArgument(0));
}
break;
case "function":
generateFunction(context);
break;
case "unwrapString":
writer.append("$rt_str(");
context.writeExpr(context.getArgument(0));
writer.append(")");
break;
default:
if (methodRef.getName().startsWith("unwrap")) {
context.writeExpr(context.getArgument(0));
@ -146,26 +143,15 @@ public class JSNativeGenerator implements Generator, Injector, DependencyPlugin
}
}
private void generateWrapString(GeneratorContext context, SourceWriter writer) throws IOException {
FieldReference charsField = new FieldReference("java.lang.String", "characters");
writer.append("var result = \"\";").softNewLine();
writer.append("var data = ").append(context.getParameterName(1)).append('.')
.appendField(charsField).append(".data;").softNewLine();
writer.append("for (var i = 0; i < data.length; i = (i + 1) | 0) {").indent().softNewLine();
writer.append("result += String.fromCharCode(data[i]);").softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("return result;").softNewLine();
}
private void generateFunction(InjectorContext context) throws IOException {
SourceWriter writer = context.getWriter();
writer.append("(function($instance, $property) { return function()").ws().append("{").indent().softNewLine();
writer.append("return $property.apply($instance, arguments);").softNewLine();
writer.append("(function($instance,").ws().append("$property)").ws().append("{").ws()
.append("return function()").ws().append("{").indent().softNewLine();
writer.append("return $instance[$property].apply($instance,").ws().append("arguments);").softNewLine();
writer.outdent().append("};})(");
context.writeExpr(context.getArgument(0));
writer.append(", ");
context.writeExpr(context.getArgument(0));
renderProperty(context.getArgument(1), context);
writer.append(",").ws();
context.writeExpr(context.getArgument(1));
writer.append(")");
}

View File

@ -187,8 +187,7 @@ class JavascriptNativeProcessor {
Variable nameVar = addStringWrap(addString(propertyName));
InvokeInstruction insn = new InvokeInstruction();
insn.setType(InvocationType.SPECIAL);
insn.setMethod(new MethodReference(JS.class.getName(), "get", ValueType.object(JSObject.class.getName()),
ValueType.object(JSObject.class.getName()), ValueType.object(JSObject.class.getName())));
insn.setMethod(new MethodReference(JS.class, "get", JSObject.class, JSObject.class, JSObject.class));
insn.setReceiver(receiver);
insn.getArguments().add(instance);
insn.getArguments().add(nameVar);
@ -199,9 +198,8 @@ class JavascriptNativeProcessor {
Variable nameVar = addStringWrap(addString(propertyName));
InvokeInstruction insn = new InvokeInstruction();
insn.setType(InvocationType.SPECIAL);
insn.setMethod(new MethodReference(JS.class.getName(), "set",
ValueType.object(JSObject.class.getName()), ValueType.object(JSObject.class.getName()),
ValueType.object(JSObject.class.getName()), ValueType.VOID));
insn.setMethod(new MethodReference(JS.class, "set", JSObject.class, JSObject.class,
JSObject.class, void.class));
insn.getArguments().add(instance);
insn.getArguments().add(nameVar);
insn.getArguments().add(value);
@ -211,8 +209,7 @@ class JavascriptNativeProcessor {
private void addIndexerGet(Variable array, Variable index, Variable receiver) {
InvokeInstruction insn = new InvokeInstruction();
insn.setType(InvocationType.SPECIAL);
insn.setMethod(new MethodReference(JS.class.getName(), "get", ValueType.object(JSObject.class.getName()),
ValueType.object(JSObject.class.getName()), ValueType.object(JSObject.class.getName())));
insn.setMethod(new MethodReference(JS.class, "get", JSObject.class, JSObject.class, JSObject.class));
insn.setReceiver(receiver);
insn.getArguments().add(array);
insn.getArguments().add(index);
@ -222,9 +219,8 @@ class JavascriptNativeProcessor {
private void addIndexerSet(Variable array, Variable index, Variable value) {
InvokeInstruction insn = new InvokeInstruction();
insn.setType(InvocationType.SPECIAL);
insn.setMethod(new MethodReference(JS.class.getName(), "set",
ValueType.object(JSObject.class.getName()), ValueType.object(JSObject.class.getName()),
ValueType.object(JSObject.class.getName()), ValueType.VOID));
insn.setMethod(new MethodReference(JS.class, "set", JSObject.class, JSObject.class,
JSObject.class, void.class));
insn.getArguments().add(array);
insn.getArguments().add(index);
insn.getArguments().add(value);
@ -322,9 +318,7 @@ class JavascriptNativeProcessor {
Variable nameVar = addStringWrap(addString(name));
InvokeInstruction insn = new InvokeInstruction();
insn.setType(InvocationType.SPECIAL);
insn.setMethod(new MethodReference(JS.class.getName(), "function",
ValueType.object(JSObject.class.getName()), ValueType.object(JSObject.class.getName()),
ValueType.object(JSObject.class.getName())));
insn.setMethod(new MethodReference(JS.class, "function", JSObject.class, JSObject.class, JSObject.class));
insn.setReceiver(functor);
insn.getArguments().add(var);
insn.getArguments().add(nameVar);

View File

@ -81,7 +81,7 @@
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>
<mainClass>org.teavm.samples.hello.Client</mainClass>
<runtime>SEPARATE</runtime>
<minifying>true</minifying>
<minifying>false</minifying>
<debugInformationGenerated>true</debugInformationGenerated>
<sourceMapsGenerated>true</sourceMapsGenerated>
<sourceFilesCopied>true</sourceFilesCopied>