GeneratorTests.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. namespace Jint.Tests.Runtime;
  2. public class GeneratorTests
  3. {
  4. private readonly Engine _engine;
  5. public GeneratorTests()
  6. {
  7. _engine = new Engine(options => options.ExperimentalFeatures = ExperimentalFeature.Generators);
  8. }
  9. [Fact]
  10. public void LoopYield()
  11. {
  12. const string Script = """
  13. const foo = function*() {
  14. yield 'a';
  15. yield 'b';
  16. yield 'c';
  17. };
  18. let str = '';
  19. for (const val of foo()) {
  20. str += val;
  21. }
  22. return str;
  23. """;
  24. Assert.Equal("abc", _engine.Evaluate(Script));
  25. }
  26. [Fact]
  27. public void ReturnDuringYield()
  28. {
  29. const string Script = """
  30. const foo = function*() {
  31. yield 'a';
  32. return;
  33. yield 'c';
  34. };
  35. let str = '';
  36. for (const val of foo()) {
  37. str += val;
  38. }
  39. return str;
  40. """;
  41. Assert.Equal("a", _engine.Evaluate(Script));
  42. }
  43. [Fact]
  44. public void LoneReturnInYield()
  45. {
  46. const string Script = """
  47. const foo = function*() {
  48. return;
  49. };
  50. let str = '';
  51. for (const val of foo()) {
  52. str += val;
  53. }
  54. return str;
  55. """;
  56. Assert.Equal("", _engine.Evaluate(Script));
  57. }
  58. [Fact]
  59. public void LoneReturnValueInYield()
  60. {
  61. const string Script = """
  62. const foo = function*() {
  63. return 'a';
  64. };
  65. let str = '';
  66. for (const val of foo()) {
  67. str += val;
  68. }
  69. return str;
  70. """;
  71. Assert.Equal("", _engine.Evaluate(Script));
  72. }
  73. [Fact]
  74. public void YieldUndefined()
  75. {
  76. const string Script = """
  77. const foo = function*() {
  78. yield undefined;
  79. };
  80. let str = '';
  81. for (const val of foo()) {
  82. str += val;
  83. }
  84. return str;
  85. """;
  86. Assert.Equal("undefined", _engine.Evaluate(Script));
  87. }
  88. [Fact]
  89. public void ReturnUndefined()
  90. {
  91. const string Script = """
  92. const foo = function*() {
  93. return undefined;
  94. };
  95. let str = '';
  96. for (const val of foo()) {
  97. str += val;
  98. }
  99. return str;
  100. """;
  101. Assert.Equal("", _engine.Evaluate(Script));
  102. }
  103. [Fact]
  104. public void Basic()
  105. {
  106. _engine.Execute("function * generator() { yield 5; yield 6; };");
  107. _engine.Execute("var iterator = generator(); var item = iterator.next();");
  108. Assert.Equal(5, _engine.Evaluate("item.value"));
  109. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  110. _engine.Execute("item = iterator.next();");
  111. Assert.Equal(6, _engine.Evaluate("item.value"));
  112. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  113. _engine.Execute("item = iterator.next();");
  114. Assert.True(_engine.Evaluate("item.value === void undefined").AsBoolean());
  115. Assert.True(_engine.Evaluate("item.done").AsBoolean());
  116. }
  117. [Fact]
  118. public void FunctionExpressions()
  119. {
  120. _engine.Execute("var generator = function * () { yield 5; yield 6; };");
  121. _engine.Execute("var iterator = generator(); var item = iterator.next();");
  122. Assert.Equal(5, _engine.Evaluate("item.value"));
  123. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  124. _engine.Execute("item = iterator.next();");
  125. Assert.Equal(6, _engine.Evaluate("item.value"));
  126. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  127. _engine.Execute("item = iterator.next();");
  128. Assert.True(_engine.Evaluate("item.value === void undefined").AsBoolean());
  129. Assert.True(_engine.Evaluate("item.done").AsBoolean());
  130. }
  131. [Fact]
  132. public void CorrectThisBinding()
  133. {
  134. _engine.Execute("var generator = function * () { yield 5; yield 6; };");
  135. _engine.Execute("var iterator = { g: generator, x: 5, y: 6 }.g(); var item = iterator.next();");
  136. Assert.Equal(5, _engine.Evaluate("item.value"));
  137. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  138. _engine.Execute("item = iterator.next();");
  139. Assert.Equal(6, _engine.Evaluate("item.value"));
  140. Assert.False(_engine.Evaluate("item.done").AsBoolean());
  141. _engine.Execute("item = iterator.next();");
  142. Assert.True(_engine.Evaluate("item.value === void undefined").AsBoolean());
  143. Assert.True(_engine.Evaluate("item.done").AsBoolean());
  144. }
  145. [Fact(Skip = "TODO es6-generators")]
  146. public void Sending()
  147. {
  148. const string Script = """
  149. var sent;
  150. function * generator() {
  151. sent = [yield 5, yield 6];
  152. };
  153. var iterator = generator();
  154. iterator.next();
  155. iterator.next("foo");
  156. iterator.next("bar");
  157. """;
  158. _engine.Execute(Script);
  159. Assert.Equal("foo", _engine.Evaluate("sent[0]"));
  160. Assert.Equal("bar", _engine.Evaluate("sent[1]"));
  161. }
  162. [Fact(Skip = "TODO es6-generators")]
  163. public void Sending2()
  164. {
  165. const string Script = """
  166. function* counter(value) {
  167. while (true) {
  168. const step = yield value++;
  169. if (step) {
  170. value += step;
  171. }
  172. }
  173. }
  174. const generatorFunc = counter(0);
  175. """;
  176. _engine.Execute(Script);
  177. Assert.Equal(0, _engine.Evaluate("generatorFunc.next().value")); // 0
  178. Assert.Equal(1, _engine.Evaluate("generatorFunc.next().value")); // 1
  179. Assert.Equal(2, _engine.Evaluate("generatorFunc.next().value")); // 2
  180. Assert.Equal(3, _engine.Evaluate("generatorFunc.next().value")); // 3
  181. Assert.Equal(14, _engine.Evaluate("generatorFunc.next(10).value")); // 14
  182. Assert.Equal(15, _engine.Evaluate("generatorFunc.next().value")); // 15
  183. Assert.Equal(26, _engine.Evaluate("generatorFunc.next(10).value")); // 26
  184. }
  185. [Fact(Skip = "TODO es6-generators")]
  186. public void Fibonacci()
  187. {
  188. const string Script = """
  189. function* fibonacci() {
  190. let current = 0;
  191. let next = 1;
  192. while (true) {
  193. const reset = yield current;
  194. [current, next] = [next, next + current];
  195. if (reset) {
  196. current = 0;
  197. next = 1;
  198. }
  199. }
  200. }
  201. const sequence = fibonacci();
  202. """;
  203. _engine.Execute(Script);
  204. Assert.Equal(0, _engine.Evaluate("sequence.next().value"));
  205. Assert.Equal(1, _engine.Evaluate("sequence.next().value"));
  206. Assert.Equal(1, _engine.Evaluate("sequence.next().value"));
  207. Assert.Equal(2, _engine.Evaluate("sequence.next().value"));
  208. Assert.Equal(3, _engine.Evaluate("sequence.next().value"));
  209. Assert.Equal(5, _engine.Evaluate("sequence.next().value"));
  210. Assert.Equal(9, _engine.Evaluate("sequence.next().value"));
  211. Assert.Equal(0, _engine.Evaluate("sequence.next(true).value"));
  212. Assert.Equal(1, _engine.Evaluate("sequence.next().value)"));
  213. Assert.Equal(1, _engine.Evaluate("sequence.next().value)"));
  214. Assert.Equal(2, _engine.Evaluate("sequence.next().value)"));
  215. }
  216. }