From 82b11f285e947ebdcba4ebb64ec049704eb85523 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 3 Dec 2017 20:47:20 +0300 Subject: [PATCH] Make async methods work in bootstrap TeaVM --- .../plugin/AsyncDependencyListener.java | 31 +++++++++++++++++++ .../platform/plugin/AsyncMethodProcessor.java | 9 ------ .../platform/plugin/PlatformGenerator.java | 2 +- .../teavm/platform/plugin/PlatformPlugin.java | 16 ++++++++++ 4 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 platform/src/main/java/org/teavm/platform/plugin/AsyncDependencyListener.java diff --git a/platform/src/main/java/org/teavm/platform/plugin/AsyncDependencyListener.java b/platform/src/main/java/org/teavm/platform/plugin/AsyncDependencyListener.java new file mode 100644 index 000000000..87d80eab3 --- /dev/null +++ b/platform/src/main/java/org/teavm/platform/plugin/AsyncDependencyListener.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017 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.platform.plugin; + +import org.teavm.dependency.AbstractDependencyListener; +import org.teavm.dependency.DependencyAgent; +import org.teavm.dependency.MethodDependency; +import org.teavm.interop.Async; +import org.teavm.model.CallLocation; + +public class AsyncDependencyListener extends AbstractDependencyListener { + @Override + public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) { + if (method.getMethod() != null && method.getMethod().getAnnotations().get(Async.class.getName()) != null) { + new AsyncMethodGenerator().methodReached(agent, method, location); + } + } +} diff --git a/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java b/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java index c79de90d0..095c72221 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java +++ b/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java @@ -16,11 +16,8 @@ package org.teavm.platform.plugin; import org.teavm.backend.javascript.spi.GeneratedBy; -import org.teavm.dependency.PluggableDependency; import org.teavm.diagnostics.Diagnostics; import org.teavm.interop.Async; -import org.teavm.model.AnnotationHolder; -import org.teavm.model.AnnotationValue; import org.teavm.model.CallLocation; import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolderTransformer; @@ -53,12 +50,6 @@ public class AsyncMethodProcessor implements ClassHolderTransformer { + "both be either static or non-static", method.getReference(), asyncMethod.getReference()); } - AnnotationHolder annot = new AnnotationHolder(GeneratedBy.class.getName()); - annot.getValues().put("value", new AnnotationValue(ValueType.parse(AsyncMethodGenerator.class))); - method.getAnnotations().add(annot); - annot = new AnnotationHolder(PluggableDependency.class.getName()); - annot.getValues().put("value", new AnnotationValue(ValueType.parse(AsyncMethodGenerator.class))); - method.getAnnotations().add(annot); } } } diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java index 990cddd2d..9c1f89b49 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java @@ -166,7 +166,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin MethodReference launchRef = new MethodReference(Platform.class, "launchThread", PlatformRunnable.class, void.class); String runnable = context.getParameterName(1); - writer.append("return window.setTimeout(function()").ws().append("{").indent().softNewLine(); + writer.append("return setTimeout(function()").ws().append("{").indent().softNewLine(); if (timeout) { writer.appendMethodBody(launchRef); } else { diff --git a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java index 23dd3ccf5..68801bb82 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java +++ b/platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java @@ -21,7 +21,10 @@ import org.teavm.backend.wasm.TeaVMWasmHost; import org.teavm.backend.wasm.intrinsics.WasmIntrinsic; import org.teavm.backend.wasm.intrinsics.WasmIntrinsicManager; import org.teavm.backend.wasm.model.expression.WasmExpression; +import org.teavm.interop.Async; import org.teavm.interop.PlatformMarker; +import org.teavm.model.ClassReader; +import org.teavm.model.MethodReader; import org.teavm.model.MethodReference; import org.teavm.platform.Platform; import org.teavm.platform.PlatformQueue; @@ -37,6 +40,18 @@ public class PlatformPlugin implements TeaVMPlugin { host.add(new ResourceTransformer()); host.add(new ResourceAccessorTransformer(host)); host.add(new ResourceAccessorDependencyListener()); + host.getExtension(TeaVMJavaScriptHost.class).addGeneratorProvider(context -> { + ClassReader cls = context.getClassSource().get(context.getMethod().getClassName()); + if (cls == null) { + return null; + } + MethodReader method = cls.getMethod(context.getMethod().getDescriptor()); + if (method == null) { + return null; + } + return method.getAnnotations().get(Async.class.getName()) != null + ? new AsyncMethodGenerator() : null; + }); } else if (!isBootstrap()) { host.add(new StringAmplifierTransformer()); } @@ -68,6 +83,7 @@ public class PlatformPlugin implements TeaVMPlugin { host.add(new EnumDependencySupport()); host.add(new AnnotationDependencySupport()); host.add(new PlatformDependencyListener()); + host.add(new AsyncDependencyListener()); TeaVMPluginUtil.handleNatives(host, Platform.class); TeaVMPluginUtil.handleNatives(host, PlatformQueue.class);