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 java.util.Iterator;
import org.teavm.dependency.PluggableDependency; import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.InjectedBy; import org.teavm.javascript.ni.InjectedBy;
/** /**
@ -54,7 +53,7 @@ public final class JS {
@InjectedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
public static native JSObject getGlobal(); public static native JSObject getGlobal();
@GeneratedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
public static native JSObject wrap(String str); public static native JSObject wrap(String str);
@InjectedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
@ -116,7 +115,7 @@ public final class JS {
@InjectedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
public static native double unwrapDouble(JSObject obj); public static native double unwrapDouble(JSObject obj);
@GeneratedBy(JSNativeGenerator.class) @InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class) @PluggableDependency(JSNativeGenerator.class)
public static native String unwrapString(JSObject obj); 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.ConstantExpr;
import org.teavm.javascript.ast.Expr; import org.teavm.javascript.ast.Expr;
import org.teavm.javascript.ast.InvocationExpr; 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.Injector;
import org.teavm.javascript.ni.InjectorContext; import org.teavm.javascript.ni.InjectorContext;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReader; import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
@ -34,18 +31,7 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class JSNativeGenerator implements Generator, Injector, DependencyPlugin { public class JSNativeGenerator implements 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();
}
}
@Override @Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException { public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
SourceWriter writer = context.getWriter(); SourceWriter writer = context.getWriter();
@ -101,11 +87,22 @@ public class JSNativeGenerator implements Generator, Injector, DependencyPlugin
writer.append("))"); writer.append("))");
break; break;
case "wrap": case "wrap":
context.writeExpr(context.getArgument(0)); 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; break;
case "function": case "function":
generateFunction(context); generateFunction(context);
break; break;
case "unwrapString":
writer.append("$rt_str(");
context.writeExpr(context.getArgument(0));
writer.append(")");
break;
default: default:
if (methodRef.getName().startsWith("unwrap")) { if (methodRef.getName().startsWith("unwrap")) {
context.writeExpr(context.getArgument(0)); 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 { private void generateFunction(InjectorContext context) throws IOException {
SourceWriter writer = context.getWriter(); SourceWriter writer = context.getWriter();
writer.append("(function($instance, $property) { return function()").ws().append("{").indent().softNewLine(); writer.append("(function($instance,").ws().append("$property)").ws().append("{").ws()
writer.append("return $property.apply($instance, arguments);").softNewLine(); .append("return function()").ws().append("{").indent().softNewLine();
writer.append("return $instance[$property].apply($instance,").ws().append("arguments);").softNewLine();
writer.outdent().append("};})("); writer.outdent().append("};})(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
writer.append(", "); writer.append(",").ws();
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(1));
renderProperty(context.getArgument(1), context);
writer.append(")"); writer.append(")");
} }

View File

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

View File

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