mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Refactoring JSO implementation
This commit is contained in:
parent
bae388a778
commit
6986f1c02a
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.function.Function;
|
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.jso.plugin.JSODependencyListener.ExposedClass;
|
||||
import org.teavm.jso.impl.JSDependencyListener.ExposedClass;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
|
@ -28,12 +28,12 @@ import org.teavm.vm.spi.RendererListener;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class JSOAliasRenderer implements RendererListener {
|
||||
class JSAliasRenderer implements RendererListener {
|
||||
private static String variableChars = "abcdefghijklmnopqrstuvwxyz";
|
||||
private JSODependencyListener dependencyListener;
|
||||
private JSDependencyListener dependencyListener;
|
||||
private SourceWriter writer;
|
||||
|
||||
public JSOAliasRenderer(JSODependencyListener dependencyListener) {
|
||||
public JSAliasRenderer(JSDependencyListener dependencyListener) {
|
||||
this.dependencyListener = dependencyListener;
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.mozilla.javascript.ast.AstNode;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
@ -78,18 +78,18 @@ import org.teavm.model.util.ProgramUtils;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class JavascriptNativeProcessor {
|
||||
class JSClassProcessor {
|
||||
private ClassReaderSource classSource;
|
||||
private Program program;
|
||||
private List<Instruction> replacement = new ArrayList<>();
|
||||
private NativeJavascriptClassRepository nativeRepos;
|
||||
private JSTypeHelper typeHelper;
|
||||
private Diagnostics diagnostics;
|
||||
private int methodIndexGenerator;
|
||||
private Map<MethodReference, MethodReader> overridenMethodCache = new HashMap<>();
|
||||
|
||||
public JavascriptNativeProcessor(ClassReaderSource classSource) {
|
||||
public JSClassProcessor(ClassReaderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
nativeRepos = new NativeJavascriptClassRepository(classSource);
|
||||
typeHelper = new JSTypeHelper(classSource);
|
||||
}
|
||||
|
||||
public ClassReaderSource getClassSource() {
|
||||
|
@ -97,11 +97,11 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
|
||||
public boolean isNative(String className) {
|
||||
return nativeRepos.isJavaScriptClass(className);
|
||||
return typeHelper.isJavaScriptClass(className);
|
||||
}
|
||||
|
||||
public boolean isNativeImplementation(String className) {
|
||||
return nativeRepos.isJavaScriptImplementation(className);
|
||||
return typeHelper.isJavaScriptImplementation(className);
|
||||
}
|
||||
|
||||
public void setDiagnostics(Diagnostics diagnostics) {
|
||||
|
@ -109,7 +109,7 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
|
||||
public MethodReference isFunctor(String className) {
|
||||
if (!nativeRepos.isJavaScriptImplementation(className)) {
|
||||
if (!typeHelper.isJavaScriptImplementation(className)) {
|
||||
return null;
|
||||
}
|
||||
ClassReader cls = classSource.get(className);
|
||||
|
@ -138,7 +138,7 @@ class JavascriptNativeProcessor {
|
|||
public void processClass(ClassHolder cls) {
|
||||
Set<MethodDescriptor> preservedMethods = new HashSet<>();
|
||||
for (String iface : cls.getInterfaces()) {
|
||||
if (nativeRepos.isJavaScriptClass(iface)) {
|
||||
if (typeHelper.isJavaScriptClass(iface)) {
|
||||
addPreservedMethods(iface, preservedMethods);
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ class JavascriptNativeProcessor {
|
|||
return processJSBodyInvocation(repository, method, callLocation, invoke);
|
||||
}
|
||||
|
||||
if (!nativeRepos.isJavaScriptClass(invoke.getMethod().getClassName())) {
|
||||
if (!typeHelper.isJavaScriptClass(invoke.getMethod().getClassName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -452,14 +452,14 @@ class JavascriptNativeProcessor {
|
|||
name = redefinedMethodName.getString();
|
||||
}
|
||||
}
|
||||
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
|
||||
if (method.getResultType() != ValueType.VOID && !typeHelper.isSupportedType(method.getResultType())) {
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
|
||||
+ "declaration", invoke.getMethod());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ValueType arg : method.getParameterTypes()) {
|
||||
if (!isSupportedType(arg)) {
|
||||
if (!typeHelper.isSupportedType(arg)) {
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
|
||||
+ "or constructor declaration", invoke.getMethod());
|
||||
return false;
|
||||
|
@ -521,12 +521,13 @@ class JavascriptNativeProcessor {
|
|||
if (!isStatic) {
|
||||
ValueType paramType = ValueType.object(methodToProcess.getOwnerName());
|
||||
paramTypes[offset++] = paramType;
|
||||
if (!isSupportedType(paramType)) {
|
||||
if (!typeHelper.isSupportedType(paramType)) {
|
||||
diagnostics.error(location, "Non-static JSBody method {{m0}} is owned by non-JS class {{c1}}",
|
||||
methodToProcess.getReference(), methodToProcess.getOwnerName());
|
||||
}
|
||||
}
|
||||
if (methodToProcess.getResultType() != ValueType.VOID && !isSupportedType(methodToProcess.getResultType())) {
|
||||
if (methodToProcess.getResultType() != ValueType.VOID
|
||||
&& !typeHelper.isSupportedType(methodToProcess.getResultType())) {
|
||||
diagnostics.error(location, "JSBody method {{m0}} returns unsupported type {{t1}}",
|
||||
methodToProcess.getReference(), methodToProcess.getResultType());
|
||||
}
|
||||
|
@ -579,8 +580,9 @@ class JavascriptNativeProcessor {
|
|||
} else {
|
||||
expr = rootNode;
|
||||
}
|
||||
JavaInvocationValidator javaValidator = new JavaInvocationValidator(classSource, diagnostics);
|
||||
javaValidator.validate(location, expr);
|
||||
JavaInvocationProcessor javaInvocationProcessor = new JavaInvocationProcessor(typeHelper,
|
||||
classSource, diagnostics);
|
||||
javaInvocationProcessor.validate(location, expr);
|
||||
repository.emitters.put(proxyMethod, new JSBodyAstEmitter(isStatic, expr, parameterNames));
|
||||
}
|
||||
repository.methodMap.put(methodToProcess.getReference(), proxyMethod);
|
||||
|
@ -1078,7 +1080,7 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
|
||||
private boolean isProperGetter(MethodDescriptor desc) {
|
||||
if (desc.parameterCount() > 0 || !isSupportedType(desc.getResultType())) {
|
||||
if (desc.parameterCount() > 0 || !typeHelper.isSupportedType(desc.getResultType())) {
|
||||
return false;
|
||||
}
|
||||
if (desc.getResultType().equals(ValueType.BOOLEAN)) {
|
||||
|
@ -1090,7 +1092,7 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
|
||||
private boolean isProperSetter(MethodDescriptor desc) {
|
||||
if (desc.parameterCount() != 1 || !isSupportedType(desc.parameterType(0))
|
||||
if (desc.parameterCount() != 1 || !typeHelper.isSupportedType(desc.parameterType(0))
|
||||
|| desc.getResultType() != ValueType.VOID) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1106,13 +1108,13 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
|
||||
private boolean isProperGetIndexer(MethodDescriptor desc) {
|
||||
return desc.parameterCount() == 1 && isSupportedType(desc.parameterType(0))
|
||||
&& isSupportedType(desc.getResultType());
|
||||
return desc.parameterCount() == 1 && typeHelper.isSupportedType(desc.parameterType(0))
|
||||
&& typeHelper.isSupportedType(desc.getResultType());
|
||||
}
|
||||
|
||||
private boolean isProperSetIndexer(MethodDescriptor desc) {
|
||||
return desc.parameterCount() == 2 && isSupportedType(desc.parameterType(0))
|
||||
&& isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID;
|
||||
return desc.parameterCount() == 2 && typeHelper.isSupportedType(desc.parameterType(0))
|
||||
&& typeHelper.isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID;
|
||||
}
|
||||
|
||||
private String cutPrefix(String name, int prefixLength) {
|
||||
|
@ -1125,25 +1127,4 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
return Character.toLowerCase(name.charAt(prefixLength)) + name.substring(prefixLength + 1);
|
||||
}
|
||||
|
||||
private boolean isSupportedType(ValueType type) {
|
||||
if (type == ValueType.VOID) {
|
||||
return false;
|
||||
}
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case LONG:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
} else if (type instanceof ValueType.Array) {
|
||||
return isSupportedType(((ValueType.Array) type).getItemType());
|
||||
} else if (type instanceof ValueType.Object) {
|
||||
String typeName = ((ValueType.Object) type).getClassName();
|
||||
return typeName.equals("java.lang.String") || nativeRepos.isJavaScriptClass(typeName);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -38,7 +38,7 @@ import org.teavm.model.MethodReader;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class JSODependencyListener extends AbstractDependencyListener {
|
||||
class JSDependencyListener extends AbstractDependencyListener {
|
||||
private Map<String, ExposedClass> exposedClasses = new HashMap<>();
|
||||
private ClassReaderSource classSource;
|
||||
private DependencyAgent agent;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
@ -28,8 +28,8 @@ public class JSOPlugin implements TeaVMPlugin {
|
|||
JSBodyRepository repository = new JSBodyRepository();
|
||||
host.registerService(JSBodyRepository.class, repository);
|
||||
host.add(new JSObjectClassTransformer(repository));
|
||||
JSODependencyListener dependencyListener = new JSODependencyListener();
|
||||
JSOAliasRenderer aliasRenderer = new JSOAliasRenderer(dependencyListener);
|
||||
JSDependencyListener dependencyListener = new JSDependencyListener();
|
||||
JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener);
|
||||
host.add(dependencyListener);
|
||||
host.add(aliasRenderer);
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassHolder;
|
||||
|
@ -27,7 +27,7 @@ import org.teavm.model.MethodReference;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JSObjectClassTransformer implements ClassHolderTransformer {
|
||||
private JavascriptNativeProcessor processor;
|
||||
private JSClassProcessor processor;
|
||||
private JSBodyRepository repository;
|
||||
|
||||
public JSObjectClassTransformer(JSBodyRepository repository) {
|
||||
|
@ -37,7 +37,7 @@ public class JSObjectClassTransformer implements ClassHolderTransformer {
|
|||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
if (processor == null || processor.getClassSource() != innerSource) {
|
||||
processor = new JavascriptNativeProcessor(innerSource);
|
||||
processor = new JSClassProcessor(innerSource);
|
||||
}
|
||||
processor.setDiagnostics(diagnostics);
|
||||
processor.processClass(cls);
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import org.mozilla.javascript.CompilerEnvirons;
|
||||
import org.mozilla.javascript.ErrorReporter;
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -21,17 +21,18 @@ import org.teavm.jso.JSObject;
|
|||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class NativeJavascriptClassRepository {
|
||||
class JSTypeHelper {
|
||||
private ClassReaderSource classSource;
|
||||
private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>();
|
||||
private Map<String, Boolean> knownJavaScriptImplementations = new HashMap<>();
|
||||
|
||||
public NativeJavascriptClassRepository(ClassReaderSource classSource) {
|
||||
public JSTypeHelper(ClassReaderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
knownJavaScriptClasses.put(JSObject.class.getName(), true);
|
||||
}
|
||||
|
@ -82,4 +83,25 @@ class NativeJavascriptClassRepository {
|
|||
}
|
||||
return cls.getInterfaces().stream().anyMatch(iface -> isJavaScriptClass(iface));
|
||||
}
|
||||
|
||||
public boolean isSupportedType(ValueType type) {
|
||||
if (type == ValueType.VOID) {
|
||||
return false;
|
||||
}
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case LONG:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
} else if (type instanceof ValueType.Array) {
|
||||
return isSupportedType(((ValueType.Array) type).getItemType());
|
||||
} else if (type instanceof ValueType.Object) {
|
||||
String typeName = ((ValueType.Object) type).getClassName();
|
||||
return typeName.equals("java.lang.String") || isJavaScriptClass(typeName);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import org.mozilla.javascript.Token;
|
||||
import org.mozilla.javascript.ast.AstNode;
|
||||
|
@ -34,12 +34,14 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class JavaInvocationValidator implements NodeVisitor {
|
||||
class JavaInvocationProcessor implements NodeVisitor {
|
||||
private ClassReaderSource classSource;
|
||||
private JSTypeHelper typeHelper;
|
||||
private Diagnostics diagnostics;
|
||||
private CallLocation location;
|
||||
|
||||
public JavaInvocationValidator(ClassReaderSource classSource, Diagnostics diagnostics) {
|
||||
public JavaInvocationProcessor(JSTypeHelper typeHelper, ClassReaderSource classSource, Diagnostics diagnostics) {
|
||||
this.typeHelper = typeHelper;
|
||||
this.classSource = classSource;
|
||||
this.diagnostics = diagnostics;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.jso.plugin;
|
||||
package org.teavm.jso.impl;
|
||||
|
||||
import org.mozilla.javascript.ErrorReporter;
|
||||
import org.mozilla.javascript.EvaluatorException;
|
|
@ -1 +1 @@
|
|||
org.teavm.jso.plugin.JSOPlugin
|
||||
org.teavm.jso.impl.JSOPlugin
|
|
@ -25,6 +25,8 @@ import org.mozilla.javascript.Context;
|
|||
import org.mozilla.javascript.ast.AstRoot;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.codegen.SourceWriterBuilder;
|
||||
import org.teavm.jso.impl.AstWriter;
|
||||
import org.teavm.jso.impl.JSParser;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue
Block a user