AsyncTests.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. using Jint.Tests.Runtime.TestClasses;
  2. namespace Jint.Tests.Runtime;
  3. public class AsyncTests
  4. {
  5. [Fact]
  6. public void AwaitPropagationAgainstPrimitiveValue()
  7. {
  8. var engine = new Engine();
  9. var result = engine.Evaluate("(async ()=>await '1')()");
  10. result = result.UnwrapIfPromise();
  11. Assert.Equal("1", result);
  12. }
  13. [Fact]
  14. public void ShouldTaskConvertedToPromiseInJS()
  15. {
  16. Engine engine = new();
  17. engine.SetValue("callable", Callable);
  18. var result = engine.Evaluate("callable().then(x=>x*2)");
  19. result = result.UnwrapIfPromise();
  20. Assert.Equal(2, result);
  21. static async Task<int> Callable()
  22. {
  23. await Task.Delay(10);
  24. Assert.True(true);
  25. return 1;
  26. }
  27. }
  28. [Fact]
  29. public void ShouldReturnedTaskConvertedToPromiseInJS()
  30. {
  31. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  32. engine.SetValue("asyncTestClass", new AsyncTestClass());
  33. var result = engine.Evaluate("asyncTestClass.ReturnDelayedTaskAsync().then(x=>x)");
  34. result = result.UnwrapIfPromise();
  35. Assert.Equal(AsyncTestClass.TestString, result);
  36. }
  37. [Fact]
  38. public void ShouldReturnedCompletedTaskConvertedToPromiseInJS()
  39. {
  40. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  41. engine.SetValue("asyncTestClass", new AsyncTestClass());
  42. var result = engine.Evaluate("asyncTestClass.ReturnCompletedTask().then(x=>x)");
  43. result = result.UnwrapIfPromise();
  44. Assert.Equal(AsyncTestClass.TestString, result);
  45. }
  46. [Fact]
  47. public void ShouldTaskCatchWhenCancelled()
  48. {
  49. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  50. CancellationTokenSource cancel = new();
  51. cancel.Cancel();
  52. engine.SetValue("token", cancel.Token);
  53. engine.SetValue("callable", Callable);
  54. engine.SetValue("assert", new Action<bool>(Assert.True));
  55. var result = engine.Evaluate("callable(token).then(_ => assert(false)).catch(_ => assert(true))");
  56. result = result.UnwrapIfPromise();
  57. static async Task Callable(CancellationToken token)
  58. {
  59. await Task.FromCanceled(token);
  60. }
  61. }
  62. [Fact]
  63. public void ShouldReturnedTaskCatchWhenCancelled()
  64. {
  65. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  66. CancellationTokenSource cancel = new();
  67. cancel.Cancel();
  68. engine.SetValue("token", cancel.Token);
  69. engine.SetValue("asyncTestClass", new AsyncTestClass());
  70. engine.SetValue("assert", new Action<bool>(Assert.True));
  71. var result = engine.Evaluate("asyncTestClass.ReturnCancelledTask(token).then(_ => assert(false)).catch(_ => assert(true))");
  72. result = result.UnwrapIfPromise();
  73. }
  74. [Fact]
  75. public void ShouldTaskCatchWhenThrowError()
  76. {
  77. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  78. engine.SetValue("callable", Callable);
  79. engine.SetValue("assert", new Action<bool>(Assert.True));
  80. var result = engine.Evaluate("callable().then(_ => assert(false)).catch(_ => assert(true))");
  81. static async Task Callable()
  82. {
  83. await Task.Delay(10);
  84. throw new Exception();
  85. }
  86. }
  87. [Fact]
  88. public void ShouldReturnedTaskCatchWhenThrowError()
  89. {
  90. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  91. engine.SetValue("asyncTestClass", new AsyncTestClass());
  92. engine.SetValue("assert", new Action<bool>(Assert.True));
  93. var result = engine.Evaluate("asyncTestClass.ThrowAfterDelayAsync().then(_ => assert(false)).catch(_ => assert(true))");
  94. result = result.UnwrapIfPromise();
  95. }
  96. [Fact]
  97. public void ShouldTaskAwaitCurrentStack()
  98. {
  99. //https://github.com/sebastienros/jint/issues/514#issuecomment-1507127509
  100. Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
  101. AsyncTestClass asyncTestClass = new();
  102. engine.SetValue("myAsyncMethod", new Func<Task>(async () =>
  103. {
  104. await Task.Delay(1000);
  105. asyncTestClass.StringToAppend += "1";
  106. }));
  107. engine.SetValue("mySyncMethod2", new Action(() =>
  108. {
  109. asyncTestClass.StringToAppend += "2";
  110. }));
  111. engine.SetValue("asyncTestClass", asyncTestClass);
  112. engine.Execute("async function hello() {await myAsyncMethod();mySyncMethod2();await asyncTestClass.AddToStringDelayedAsync(\"3\")} hello();");
  113. Assert.Equal("123", asyncTestClass.StringToAppend);
  114. }
  115. #if NETFRAMEWORK == false
  116. [Fact]
  117. public void ShouldValueTaskConvertedToPromiseInJS()
  118. {
  119. Engine engine = new();
  120. engine.SetValue("callable", Callable);
  121. var result = engine.Evaluate("callable().then(x=>x*2)");
  122. result = result.UnwrapIfPromise();
  123. Assert.Equal(2, result);
  124. static async ValueTask<int> Callable()
  125. {
  126. await Task.Delay(10);
  127. Assert.True(true);
  128. return 1;
  129. }
  130. }
  131. [Fact]
  132. public void ShouldValueTaskCatchWhenCancelled()
  133. {
  134. Engine engine = new();
  135. CancellationTokenSource cancel = new();
  136. cancel.Cancel();
  137. engine.SetValue("token", cancel.Token);
  138. engine.SetValue("callable", Callable);
  139. engine.SetValue("assert", new Action<bool>(Assert.True));
  140. var result = engine.Evaluate("callable(token).then(_ => assert(false)).catch(_ => assert(true))");
  141. result = result.UnwrapIfPromise();
  142. static async ValueTask Callable(CancellationToken token)
  143. {
  144. await ValueTask.FromCanceled(token);
  145. }
  146. }
  147. [Fact]
  148. public void ShouldValueTaskCatchWhenThrowError()
  149. {
  150. Engine engine = new();
  151. engine.SetValue("callable", Callable);
  152. engine.SetValue("assert", new Action<bool>(Assert.True));
  153. var result = engine.Evaluate("callable().then(_ => assert(false)).catch(_ => assert(true))");
  154. static async ValueTask Callable()
  155. {
  156. await Task.Delay(10);
  157. throw new Exception();
  158. }
  159. }
  160. [Fact]
  161. public void ShouldValueTaskAwaitCurrentStack()
  162. {
  163. //https://github.com/sebastienros/jint/issues/514#issuecomment-1507127509
  164. Engine engine = new();
  165. string log = "";
  166. engine.SetValue("myAsyncMethod", new Func<ValueTask>(async () =>
  167. {
  168. await Task.Delay(1000);
  169. log += "1";
  170. }));
  171. engine.SetValue("myAsyncMethod2", new Action(() =>
  172. {
  173. log += "2";
  174. }));
  175. engine.Execute("async function hello() {await myAsyncMethod();myAsyncMethod2();} hello();");
  176. Assert.Equal("12", log);
  177. }
  178. #endif
  179. [Fact(Skip = "TODO es6-await https://github.com/sebastienros/jint/issues/1385")]
  180. public void ShouldHaveCorrectOrder()
  181. {
  182. var engine = new Engine();
  183. engine.Evaluate("var log = [];");
  184. const string Script = """
  185. async function foo(name) {
  186. log.push(name + " start");
  187. await log.push(name + " middle");
  188. log.push(name + " end");
  189. }
  190. foo("First");
  191. foo("Second");
  192. """;
  193. engine.Execute(Script);
  194. var log = engine.GetValue("log").AsArray();
  195. string[] expected = [
  196. "First start",
  197. "First middle",
  198. "Second start",
  199. "Second middle",
  200. "First end",
  201. "Second end",
  202. ];
  203. Assert.Equal(expected, log.Select(x => x.AsString()).ToArray());
  204. }
  205. [Fact]
  206. public void ShouldPromiseBeResolved()
  207. {
  208. var log = new List<string>();
  209. Engine engine = new();
  210. engine.SetValue("log", (string str) =>
  211. {
  212. log.Add(str);
  213. });
  214. const string Script = """
  215. async function main() {
  216. return new Promise(function (resolve) {
  217. log('Promise!')
  218. resolve(null)
  219. }).then(function () {
  220. log('Resolved!')
  221. });
  222. }
  223. """;
  224. var result = engine.Execute(Script);
  225. var val = result.GetValue("main");
  226. val.Call().UnwrapIfPromise();
  227. Assert.Equal(2, log.Count);
  228. Assert.Equal("Promise!", log[0]);
  229. Assert.Equal("Resolved!", log[1]);
  230. }
  231. [Fact]
  232. public void ShouldPromiseBeResolved2()
  233. {
  234. Engine engine = new();
  235. engine.SetValue("setTimeout",
  236. (Action action, int ms) =>
  237. {
  238. Task.Delay(ms).ContinueWith(_ => action());
  239. });
  240. const string Script = """
  241. var delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
  242. async function main() {
  243. await delay(100);
  244. return 1;
  245. }
  246. """;
  247. var result = engine.Execute(Script);
  248. var val = result.GetValue("main").Call();
  249. Assert.Equal(1, val.UnwrapIfPromise().AsInteger());
  250. }
  251. }