From aad95014fed10c8d5e4d94c237aa08e44e600257 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 12 Mar 2015 11:44:17 +0400 Subject: [PATCH] Fix error in Object.wait. Make junit working with new async approach --- .../org/teavm/classlib/java/lang/TObject.java | 6 ++ .../resources/org/teavm/javascript/runtime.js | 15 +++-- .../teavm/tooling/test/res/junit-support.js | 64 +++++++++++++------ .../teavm/classlib/java/lang/ObjectTest.java | 11 ++++ 4 files changed, 73 insertions(+), 23 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 6229e2073..cdf71e91b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -97,6 +97,12 @@ public class TObject { o.monitor.count += count; callback.complete(null); return; + } else if (o.monitor.owner == null) { + o.monitor.owner = thread; + TThread.setCurrentThread(thread); + o.monitor.count += count; + callback.complete(null); + return; } o.monitor.enteringThreads.add(new PlatformRunnable() { @Override public void run() { diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index c27ddba15..22823bf23 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -442,6 +442,7 @@ function TeaVMThread(runner) { this.suspendCallback = null; this.runner = runner; this.attribute = null; + this.completeCallback = null; } TeaVMThread.prototype.push = function(value) { this.stack.push(value); @@ -460,7 +461,7 @@ TeaVMThread.prototype.suspend = function(callback) { this.suspendCallback = callback; this.status = 1; } -TeaVMThread.prototype.start = function() { +TeaVMThread.prototype.start = function(callback) { if (this.status != 3) { throw new Error("Thread already started"); } @@ -468,6 +469,7 @@ TeaVMThread.prototype.start = function() { throw new Error("Another thread is running"); } this.status = 0; + this.completeCallback = callback ? callback : function() {}; this.run(); } TeaVMThread.prototype.resume = function() { @@ -479,8 +481,11 @@ TeaVMThread.prototype.resume = function() { } TeaVMThread.prototype.run = function() { $rt_currentNativeThread = this; + var result; try { - this.runner(); + result = this.runner(); + } catch (e) { + result = e; } finally { $rt_currentNativeThread = null; } @@ -491,6 +496,8 @@ TeaVMThread.prototype.run = function() { callback(function() { self.resume(); }); + } else if (this.status === 0) { + this.completeCallback(result); } } function $rt_suspending() { @@ -504,8 +511,8 @@ function $rt_resuming() { function $rt_suspend(callback) { return $rt_nativeThread().suspend(callback); } -function $rt_startThread(runner) { - new TeaVMThread(runner).start(); +function $rt_startThread(runner, callback) { + new TeaVMThread(runner).start(callback); } var $rt_currentNativeThread = null; function $rt_nativeThread() { diff --git a/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js index bde8a9555..51c8b0d83 100644 --- a/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js +++ b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js @@ -368,26 +368,52 @@ TreeNode.prototype.select = function() { var JUnitClient = {}; JUnitClient.run = function() { - var handler = window.addEventListener("message", function() { - window.removeEventListener("message", handler); - var message = {}; - try { - var instance = new TestClass(); - initInstance(instance); - runTest(instance, function(restore) { - try { - var result = restore(); - message.status = "ok"; - } catch (e) { - JUnitClient.makeErrorMessage(message, e); - } - window.parent.postMessage(JSON.stringify(message), "*"); - }); - } catch (e) { - JUnitClient.makeErrorMessage(message, e); - window.parent.postMessage(JSON.stringify(message), "*"); + var handler = window.addEventListener("message", $rt_threadStarter(function() { + var thread = $rt_nativeThread(); + var instance; + var ptr = 0; + var message; + if (thread.isResuming()) { + ptr = thread.pop(); + instance = thread.pop(); } - }); + loop: while (true) { switch (ptr) { + case 0: + instance = new TestClass(); + ptr = 1; + case 1: + try { + initInstance(instance); + } catch (e) { + message = {}; + JUnitClient.makeErrorMessage(message, e); + break loop; + } + if (thread.isSuspending()) { + thread.push(instance); + thread.push(ptr); + return; + } + ptr = 2; + case 2: + try { + runTest(instance); + } catch (e) { + message = {}; + JUnitClient.makeErrorMessage(message, e); + break loop; + } + if (thread.isSuspending()) { + thread.push(instance); + thread.push(ptr); + return; + } + message = {}; + message.status = "ok"; + break loop; + }} + window.parent.postMessage(JSON.stringify(message), "*"); + })); } JUnitClient.makeErrorMessage = function(message, e) { message.status = "exception"; diff --git a/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java index 6db988184..5bc565cd2 100644 --- a/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java @@ -67,4 +67,15 @@ public class ObjectTest { assertTrue(new Object[2].toString().startsWith("[Ljava.lang.Object;@")); assertTrue(new byte[3].toString().startsWith("[B@")); } + + @Test + public void waitWorks() throws InterruptedException { + long start = System.currentTimeMillis(); + final Object lock = new Object(); + synchronized (lock) { + lock.wait(100); + } + long end = System.currentTimeMillis(); + assertTrue(end - start > 100); + } }