Skip to content

Commit 2212d07

Browse files
committed
ES6 generators
1 parent 62ab481 commit 2212d07

File tree

4 files changed

+491
-1
lines changed

4 files changed

+491
-1
lines changed

Jint.Tests.Test262/Test262Harness.settings.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"Array.fromAsync",
99
"async-iteration",
1010
"Atomics",
11-
"generators",
1211
"import-assertions",
1312
"iterator-helpers",
1413
"regexp-duplicate-named-groups",
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
namespace Jint.Tests.Runtime;
2+
3+
public class GeneratorTests
4+
{
5+
[Fact]
6+
public void LoopYield()
7+
{
8+
const string Script = """
9+
const foo = function*() {
10+
yield 'a';
11+
yield 'b';
12+
yield 'c';
13+
};
14+
15+
let str = '';
16+
for (const val of foo()) {
17+
str += val;
18+
}
19+
return str;
20+
""";
21+
22+
var engine = new Engine();
23+
Assert.Equal("abc", engine.Evaluate(Script));
24+
}
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+
36+
let str = '';
37+
for (const val of foo()) {
38+
str += val;
39+
}
40+
return str;
41+
""";
42+
43+
var engine = new Engine();
44+
Assert.Equal("a", engine.Evaluate(Script));
45+
}
46+
47+
[Fact]
48+
public void LoneReturnInYield()
49+
{
50+
const string Script = """
51+
const foo = function*() {
52+
return;
53+
};
54+
55+
let str = '';
56+
for (const val of foo()) {
57+
str += val;
58+
}
59+
return str;
60+
""";
61+
62+
var engine = new Engine();
63+
Assert.Equal("", engine.Evaluate(Script));
64+
}
65+
66+
[Fact]
67+
public void LoneReturnValueInYield()
68+
{
69+
const string Script = """
70+
const foo = function*() {
71+
return 'a';
72+
};
73+
74+
let str = '';
75+
for (const val of foo()) {
76+
str += val;
77+
}
78+
return str;
79+
""";
80+
81+
var engine = new Engine();
82+
Assert.Equal("", engine.Evaluate(Script));
83+
}
84+
85+
[Fact]
86+
public void YieldUndefined()
87+
{
88+
const string Script = """
89+
const foo = function*() {
90+
yield undefined;
91+
};
92+
93+
let str = '';
94+
for (const val of foo()) {
95+
str += val;
96+
}
97+
return str;
98+
""";
99+
100+
var engine = new Engine();
101+
Assert.Equal("undefined", engine.Evaluate(Script));
102+
}
103+
104+
[Fact]
105+
public void ReturnUndefined()
106+
{
107+
const string Script = """
108+
const foo = function*() {
109+
return undefined;
110+
};
111+
112+
let str = '';
113+
for (const val of foo()) {
114+
str += val;
115+
}
116+
return str;
117+
""";
118+
119+
var engine = new Engine();
120+
Assert.Equal("", engine.Evaluate(Script));
121+
}
122+
123+
[Fact]
124+
public void Basic()
125+
{
126+
var engine = new Engine();
127+
engine.Execute("function * generator() { yield 5; yield 6; };");
128+
engine.Execute("var iterator = generator(); var item = iterator.next();");
129+
Assert.Equal(5, engine.Evaluate("item.value"));
130+
Assert.False(engine.Evaluate("item.done").AsBoolean());
131+
engine.Execute("item = iterator.next();");
132+
Assert.Equal(6, engine.Evaluate("item.value"));
133+
Assert.False(engine.Evaluate("item.done").AsBoolean());
134+
engine.Execute("item = iterator.next();");
135+
Assert.True(engine.Evaluate("item.value === void undefined").AsBoolean());
136+
Assert.True(engine.Evaluate("item.done").AsBoolean());
137+
}
138+
139+
[Fact]
140+
public void FunctionExpressions()
141+
{
142+
var engine = new Engine();
143+
engine.Execute("var generator = function * () { yield 5; yield 6; };");
144+
engine.Execute("var iterator = generator(); var item = iterator.next();");
145+
Assert.Equal(5, engine.Evaluate("item.value"));
146+
Assert.False(engine.Evaluate("item.done").AsBoolean());
147+
engine.Execute("item = iterator.next();");
148+
Assert.Equal(6, engine.Evaluate("item.value"));
149+
Assert.False(engine.Evaluate("item.done").AsBoolean());
150+
engine.Execute("item = iterator.next();");
151+
Assert.True(engine.Evaluate("item.value === void undefined").AsBoolean());
152+
Assert.True(engine.Evaluate("item.done").AsBoolean());
153+
}
154+
155+
[Fact]
156+
public void CorrectThisBinding()
157+
{
158+
var engine = new Engine();
159+
engine.Execute("var generator = function * () { yield 5; yield 6; };");
160+
engine.Execute("var iterator = { g: generator, x: 5, y: 6 }.g(); var item = iterator.next();");
161+
Assert.Equal(5, engine.Evaluate("item.value"));
162+
Assert.False(engine.Evaluate("item.done").AsBoolean());
163+
engine.Execute("item = iterator.next();");
164+
Assert.Equal(6, engine.Evaluate("item.value"));
165+
Assert.False(engine.Evaluate("item.done").AsBoolean());
166+
engine.Execute("item = iterator.next();");
167+
Assert.True(engine.Evaluate("item.value === void undefined").AsBoolean());
168+
Assert.True(engine.Evaluate("item.done").AsBoolean());
169+
}
170+
171+
[Fact(Skip = "TODO es6-generators")]
172+
public void Sending()
173+
{
174+
const string Script = """
175+
var sent;
176+
function * generator() {
177+
sent = [yield 5, yield 6];
178+
};
179+
var iterator = generator();
180+
iterator.next();
181+
iterator.next("foo");
182+
iterator.next("bar");
183+
""";
184+
185+
var engine = new Engine();
186+
engine.Execute(Script);
187+
188+
Assert.Equal("foo", engine.Evaluate("sent[0]"));
189+
Assert.Equal("bar", engine.Evaluate("sent[1]"));
190+
}
191+
192+
[Fact(Skip = "TODO es6-generators")]
193+
public void Sending2()
194+
{
195+
const string Script = """
196+
function* counter(value) {
197+
while (true) {
198+
const step = yield value++;
199+
200+
if (step) {
201+
value += step;
202+
}
203+
}
204+
}
205+
206+
const generatorFunc = counter(0);
207+
""";
208+
209+
var engine = new Engine();
210+
engine.Execute(Script);
211+
212+
Assert.Equal(0, engine.Evaluate("generatorFunc.next().value")); // 0
213+
Assert.Equal(1, engine.Evaluate("generatorFunc.next().value")); // 1
214+
Assert.Equal(2, engine.Evaluate("generatorFunc.next().value")); // 2
215+
Assert.Equal(3, engine.Evaluate("generatorFunc.next().value")); // 3
216+
Assert.Equal(14, engine.Evaluate("generatorFunc.next(10).value")); // 14
217+
Assert.Equal(15, engine.Evaluate("generatorFunc.next().value")); // 15
218+
Assert.Equal(26, engine.Evaluate("generatorFunc.next(10).value")); // 26
219+
}
220+
221+
[Fact(Skip = "TODO es6-generators")]
222+
public void Fibonacci()
223+
{
224+
const string Script = """
225+
function* fibonacci() {
226+
let current = 0;
227+
let next = 1;
228+
while (true) {
229+
const reset = yield current;
230+
[current, next] = [next, next + current];
231+
if (reset) {
232+
current = 0;
233+
next = 1;
234+
}
235+
}
236+
}
237+
238+
const sequence = fibonacci();
239+
""";
240+
241+
var engine = new Engine();
242+
engine.Execute(Script);
243+
244+
Assert.Equal(0, engine.Evaluate("sequence.next().value"));
245+
Assert.Equal(1, engine.Evaluate("sequence.next().value"));
246+
Assert.Equal(1, engine.Evaluate("sequence.next().value"));
247+
Assert.Equal(2, engine.Evaluate("sequence.next().value"));
248+
Assert.Equal(3, engine.Evaluate("sequence.next().value"));
249+
Assert.Equal(5, engine.Evaluate("sequence.next().value"));
250+
Assert.Equal(9, engine.Evaluate("sequence.next().value"));
251+
Assert.Equal(0, engine.Evaluate("sequence.next(true).value"));
252+
Assert.Equal(1, engine.Evaluate("sequence.next().value)"));
253+
Assert.Equal(1, engine.Evaluate("sequence.next().value)"));
254+
Assert.Equal(2, engine.Evaluate("sequence.next().value)"));
255+
}
256+
}

Jint/Runtime/Interpreter/Expressions/JintExpression.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ protected internal static JintExpression Build(Expression expression)
132132
? new JintCallExpression((CallExpression) ((ChainExpression) expression).Expression)
133133
: new JintMemberExpression((MemberExpression) ((ChainExpression) expression).Expression),
134134
Nodes.AwaitExpression => new JintAwaitExpression((AwaitExpression) expression),
135+
Nodes.YieldExpression => new JintYieldExpression((YieldExpression) expression),
135136
_ => null
136137
};
137138

0 commit comments

Comments
 (0)