Fixes bugs in JSO and building resources

This commit is contained in:
Alexey Andreev 2014-03-26 23:15:55 +04:00
parent ae60a7b4a0
commit bf68cf4b7d
9 changed files with 129 additions and 44 deletions

View File

@ -120,6 +120,11 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return classSource;
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public String generateClassName() {
return "$$tmp$$.TempClass" + classNameSuffix++;

View File

@ -338,6 +338,21 @@ class DependencyGraphBuilder {
@Override
public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) {
useRunners.add(new TypePropagationRunner(nodes[receiver.getIndex()], "[" + itemType));
final String className = extractClassName(itemType);
if (className != null) {
useRunners.add(new Runnable() {
@Override public void run() {
dependencyChecker.initClass(className, callerStack);
}
});
}
}
private String extractClassName(ValueType itemType) {
while (itemType instanceof ValueType.Array) {
itemType = ((ValueType.Array)itemType).getItemType();
}
return itemType instanceof ValueType.Object ? ((ValueType.Object)itemType).getClassName() : null;
}
@Override

View File

@ -27,6 +27,8 @@ import org.teavm.model.MethodReference;
public interface DependencyInfo {
ClassReaderSource getClassSource();
ClassLoader getClassLoader();
boolean isMethodAchievable(MethodReference methodRef);
Collection<MethodReference> getAchievableMethods();

View File

@ -33,6 +33,13 @@ public class DirectoryBuildTarget implements BuildTarget {
@Override
public OutputStream createResource(String fileName) throws IOException {
int index = fileName.lastIndexOf('/');
if (index >= 0) {
File dir = new File(directory, fileName.substring(0, index));
if (!dir.exists()) {
dir.mkdirs();
}
}
return new FileOutputStream(new File(directory, fileName));
}
}

View File

@ -166,6 +166,48 @@ public final class JS {
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f, JSObject g);
@InjectedBy(JSNativeGenerator.class)
@PluggableDependency(JSNativeGenerator.class)
public static native JSObject instantiate(JSObject instance, JSObject constructor, JSObject a, JSObject b,
JSObject c, JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
public static <T extends JSObject> Iterable<T> iterate(final JSArray<T> array) {
return new Iterable<T>() {
@Override public Iterator<T> iterator() {

View File

@ -1,40 +1,16 @@
/*
* Copyright 2014 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.jso;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Alexey Andreev
*/
public interface JSConstructor<T extends JSObject> extends JSFunction {
T construct();
T construct(JSObject a);
T construct(JSObject a, JSObject b);
T construct(JSObject a, JSObject b, JSObject c);
T construct(JSObject a, JSObject b, JSObject c, JSObject d);
T construct(JSObject a, JSObject b, JSObject c, JSObject d, JSObject e);
T construct(JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f);
T construct(JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f, JSObject g);
T construct(JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JSConstructor {
String value() default "";
}

View File

@ -20,9 +20,12 @@ package org.teavm.jso;
* @author Alexey Andreev
*/
public interface JSGlobal extends JSObject {
@JSProperty
JSConstructor<JSArray<JSObject>> getArray();
@JSConstructor
JSObject newObject();
@JSProperty
JSConstructor<JSObject> getObject();
@JSConstructor
<T extends JSObject> JSArray<T> newArray();
@JSConstructor
<T extends JSObject> JSArray<T> newArray(int sz);
}

View File

@ -87,6 +87,19 @@ public class JSNativeGenerator implements Generator, Injector, DependencyPlugin
}
writer.append(')');
break;
case "instantiate":
writer.append("(new ");
context.writeExpr(context.getArgument(0));
renderProperty(context.getArgument(1), context);
writer.append('(');
for (int i = 2; i < context.argumentCount(); ++i) {
if (i > 2) {
writer.append(',').ws();
}
context.writeExpr(context.getArgument(i));
}
writer.append("))");
break;
case "wrap":
context.writeExpr(context.getArgument(0));
break;

View File

@ -89,7 +89,7 @@ class JavascriptNativeProcessor {
}
} else if (isProperSetter(method.getDescriptor())) {
Variable wrapped = wrap(invoke.getArguments().get(0), method.parameterType(0));
addPropertySet(cutPrefix(method.getName(), 3), invoke.getArguments().get(0), wrapped);
addPropertySet(cutPrefix(method.getName(), 3), invoke.getInstance(), wrapped);
} else {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript property declaration");
@ -112,25 +112,47 @@ class JavascriptNativeProcessor {
"a proper native JavaScript indexer declaration");
}
} else {
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method declaration");
String name = method.getName();
AnnotationReader constructorAnnot = method.getAnnotations().get(JSConstructor.class.getName());
boolean isConstructor = false;
if (constructorAnnot != null) {
if (!isSupportedType(method.getResultType())) {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript constructor declaration");
}
AnnotationValue nameVal = constructorAnnot.getValue("value");
name = nameVal != null ? constructorAnnot.getValue("value").getString() : "";
if (name.isEmpty()) {
if (!method.getName().startsWith("new") || method.getName().length() == 3) {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"declared as a native JavaScript constructor, but its name does " +
"not satisfy conventions");
}
name = method.getName().substring(3);
}
isConstructor = true;
} else {
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method declaration");
}
}
for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) {
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method declaration");
"a proper native JavaScript method or constructor declaration");
}
}
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
InvokeInstruction newInvoke = new InvokeInstruction();
ValueType[] signature = new ValueType[method.parameterCount() + 3];
Arrays.fill(signature, ValueType.object(JSObject.class.getName()));
newInvoke.setMethod(new MethodReference(JS.class.getName(), "invoke", signature));
newInvoke.setMethod(new MethodReference(JS.class.getName(),
isConstructor ? "instantiate" : "invoke", signature));
newInvoke.setType(InvocationType.SPECIAL);
newInvoke.setReceiver(result);
newInvoke.getArguments().add(invoke.getInstance());
newInvoke.getArguments().add(addStringWrap(addString(method.getName())));
newInvoke.getArguments().add(addStringWrap(addString(name)));
for (int k = 0; k < invoke.getArguments().size(); ++k) {
Variable arg = wrapArgument(invoke.getArguments().get(k), method.parameterType(k));
newInvoke.getArguments().add(arg);