Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: test/mjsunit/harmony/async-from-sync-iterator.js

Issue 2645313003: [async-iteration] implement Async-from-Sync Iterator (Closed)
Patch Set: [async-iteration] implement Async-from-Sync Iterator Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Flags: --harmony-async-iteration --allow-natives-syntax
6
7 let testFailed = false;
8 let testFailure;
9
10 class MyError extends Error {};
11
12 (async function() {
13 function* gen() {
14 yield "sync value";
15 try {
16 yield new Promise(function(resolve) {
17 resolve("async value");
18 });
19 } catch (error) {
20 throw error;
neis 2017/02/20 09:41:20 What's the point of catching and rethrowing here?
caitp 2017/02/20 17:09:34 it's a basic control flow test. The .throw call ge
neis 2017/02/21 12:48:08 I don't get your point, but feel free to keep it a
21 }
22 assertUnreachable("generator is closed");
neis 2017/02/20 09:41:20 I was at first confused by this. Could you just re
caitp 2017/02/20 17:09:35 I'm not entirely sure what you mean --- after the
neis 2017/02/21 12:48:08 What confused me is that this line is not unreacha
caitp 2017/02/21 14:36:52 It is unreachable, because the throw on line 20 re
23 }
24 let iter = %CreateAsyncFromSyncIterator(gen());
25
26 // [Async-from-Sync Iterator] wraps sync iterator values in a Promise
27 let promise = iter.next();
28 assertInstanceof(promise, Promise);
29 let iter_result = await promise;
30 assertEquals({ value: "sync value", done: false }, iter_result);
31
32 // [Async-from-Sync Iterator] will wait for resolution of Promise values
33 promise = iter.next();
34 assertInstanceof(promise, Promise);
35 iter_result = await promise;
36 assertEquals({ value: "async value", done: false }, iter_result);
37
38 // [Async-from-Sync Iterator].throw delegates to .throw() method of sync
39 // iterator.
40 promise = iter.throw(new MyError("Error#1"));
41 assertInstanceof(promise, Promise);
42 try {
43 await promise;
44 assertUnreachable("promise should be rejected");
45 } catch (e) {
46 assertInstanceof(e, MyError);
47 assertEquals("Error#1", e.message);
48 }
49
50 promise = iter.return("generator closed");
51 assertInstanceof(promise, Promise);
52 iter_result = await promise;
53 assertEquals({ value: "generator closed", done: true }, iter_result);
54
55 // .next(), .return() and .throw() delegate to sync iterator methods, without
56 // keeping track of the state of the generator.
57 promise = iter.next("unused");
58 assertInstanceof(promise, Promise);
59 iter_result = await promise;
60 assertEquals({ value: undefined, done: true }, iter_result);
61
62 promise = iter.throw(new MyError("Error#2"));
63 assertInstanceof(promise, Promise);
64 try {
65 await promise;
66 } catch (e) {
67 assertInstanceof(e, MyError);
68 assertEquals("Error#2", e.message);
69 }
70
71 promise = iter.return("return-after-completed");
72 assertInstanceof(promise, Promise);
73 iter_result = await promise;
74 assertEquals({ value: "return-after-completed", done: true }, iter_result);
neis 2017/02/20 09:41:20 You already tested .return above, didn't you?
caitp 2017/02/20 17:09:35 it's good to have an extra one thrown in as it hel
75
neis 2017/02/20 09:41:20 Can you somehow separate the tests using gen (abov
caitp 2017/02/20 17:09:35 Acknowledged.
76 function resolveLater(value) {
77 return new Promise(function(resolve) {
78 Promise.resolve().then(function() {
79 resolve(value);
80 });
81 });
82 }
83
84 function rejectLater(value) {
85 return new Promise(function(resolve, reject) {
86 Promise.resolve().then(function() {
87 reject(value);
88 });
89 });
90 }
91
92 const kNext = 1;
93 const kThrow = 2;
94 const kReturn = 4;
95 const kNextThrows = kNext | 8;
96 const kReturnThrows = kReturn | 16;
97 const kThrowNormal = kThrow | 32;
98 function sync(array, features, log = []) {
neis 2017/02/20 09:41:20 There shouldn't be a default value for log (see co
caitp 2017/02/20 17:09:35 Removed the default value, and added a %AbortJS()
99 let i = 0;
100 let methods = {
101 next(sent) {
102 let done = i >= array.length;
103 let value = array[i];
104 log.push({ method: "next", sent, value, done });
105 if ((features & kNextThrows) === kNextThrows) throw sent;
106 i++;
107 return { value, done };
108 },
109 throw(sent) {
110 let done = i >= array.length;
111 let value = undefined;
112 log.push({ method: "throw", sent, value, done });
neis 2017/02/20 09:41:20 I think you can drop value here and in return belo
caitp 2017/02/20 17:09:35 Done.
113 if ((features & kThrowNormal) === kThrowNormal)
114 return { value: sent, done };
115 throw sent;
116 },
117 return(sent) {
118 let done = true;
119 let value = undefined;
120 log.push({ method: "return", sent, value, done });
121 if ((features & kReturnThrows) === kReturnThrows) throw sent;
122 return { value, done };
neis 2017/02/20 09:41:20 Not sure why you use undefined as the value in ret
caitp 2017/02/20 17:09:35 It's pretty inconsequential to the test either way
123 }
124 };
125 return {
126 [Symbol.iterator]() { return this; },
127 next: (features & kNext) ? methods.next : undefined,
128 throw: (features & kThrow) ? methods.throw : undefined,
129 return: (features & kReturn) ? methods.return : undefined
130 };
131 }
132
133 let log = [];
134 iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], 0));
neis 2017/02/20 09:41:20 You forgot to pass the log.
caitp 2017/02/20 17:09:35 Good catch, thx
135
136 try {
137 await iter.next();
138 assertUnreachable("Iterator.next() method is not optional");
139 } catch (e) {
140 assertInstanceof(e, TypeError);
141 assertEquals([], log);
142 }
143
144 log = [];
145 iter = %CreateAsyncFromSyncIterator(sync(["sync-value"], kNext, log));
146 assertEquals({ value: "sync-value", done: false }, await iter.next("a"));
147 assertEquals([
148 {
149 method: "next",
150 sent: "a",
151 value: "sync-value",
152 done: false
153 }
154 ], log);
155
156 log = [];
157 let asyncValue = resolveLater("async-value");
158 iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
159 assertEquals({ value: "async-value", done: false }, await iter.next("b"));
160 assertEquals([
161 {
162 method: "next",
163 sent: "b",
164 value: asyncValue,
165 done: false
166 }
167 ], log);
168
169 // If [sync_iterator].next() produces a rejected Promise or an exception is
170 // thrown, Promise is rejected with thrown/rejected value.
171 log = [];
172 asyncValue = rejectLater("Boo!");
173 iter = %CreateAsyncFromSyncIterator(sync([asyncValue], kNext, log));
174 try {
175 await iter.next('c');
176 assertUnreachable('Expected `iter.next(\'c\') to throw, but did not throw');
neis 2017/02/20 09:41:20 It's the await that throws, not the iter.next call
caitp 2017/02/20 17:09:35 throw/reject are admittedly being used inferchange
177 } catch (e) {
178 assertEquals("Boo!", e);
179 assertEquals([
180 {
181 method: 'next',
182 sent: 'c',
183 value: asyncValue,
184 done: false
185 }
186 ], log);
187 }
188
189 // If [sync_iterator].return() does not exist, return a Promise resolved with
190 // the value `{ value: <<sent value>>, done: true }`.
191 log = [];
192 iter = %CreateAsyncFromSyncIterator(sync(['sync-return'], kNext, log));
193 assertEquals({
194 value: 'd',
195 done: true
196 }, await iter.return('d'));
197
198 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
199 // whether [sync_iterator] is completed or not.
200 assertEquals({
201 value: 'sync-return',
202 done: false
203 }, await iter.next('e'));
204
205 assertEquals([
206 {
207 method: 'next',
208 sent: 'e',
209 value: 'sync-return',
210 done: false
211 }
212 ], log);
213
214 // If [sync_iterator].return() does exist, return a Promise resolved with
215 // the iterator result of [sync_iterator].return().
216 log = [];
217 iter = %CreateAsyncFromSyncIterator(sync(['sync-return'],
218 kNext|kReturn, log));
219 assertEquals({
220 value: undefined,
221 done: true
222 }, await iter.return('f'));
223
224 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
225 // whether [sync_iterator] is completed or not.
226 assertEquals({
227 value: 'sync-return',
228 done: false
229 }, await iter.next('g'));
230
231 assertEquals([
232 {
233 method: 'return',
234 sent: 'f',
235 value: undefined,
236 done: true
237 },
238 {
239 method: 'next',
240 sent: 'g',
241 value: 'sync-return',
242 done: false
243 }
244 ], log);
245
246 // If [sync_iterator].return() produces a rejected Promise or an exception is
247 // thrown, Promise is rejected with thrown/rejected value.
248 log = [];
249 iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kReturnThrows,
250 log));
251 try {
252 await iter.return('Boo!!');
253 assertUnreachable('Expected `iter.return(\'Boo!!\') to throw, but did ' +
254 'not throw');
255 } catch (e) {
256 assertEquals("Boo!!", e);
257 }
neis 2017/02/20 09:41:20 Can you also test the case where the result of the
258
259 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
260 // whether [sync_iterator] is completed or not.
261 assertEquals({ value: 'sync-value', done: false }, await iter.next('h'));
262 assertEquals([
263 {
264 method: 'return',
265 sent: 'Boo!!',
266 value: undefined,
267 done: true
268 },
269 {
270 method: 'next',
271 sent: 'h',
272 value: 'sync-value',
273 done: false
274 }
275 ], log);
276
277 // If [sync_iterator].throw() does exist, return a Promise rejected with
278 // the sent value.
neis 2017/02/20 09:41:20 Do you mean "does not exist" here?
caitp 2017/02/20 17:09:35 "if [sync_iterator] does not have a .throw method"
279 log = [];
280 iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext, log));
281 try {
282 await iter.throw('Boo!!');
283 assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
284 'throw');
285 } catch (e) {
286 assertEquals('Boo!!', e);
287 }
288
289 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
290 // whether [sync_iterator] is completed or not.
291 assertEquals({ value: 'sync-value', done: false }, await iter.next('i'));
292 assertEquals([
293 {
294 method: 'next',
295 sent: 'i',
296 value: 'sync-value',
297 done: false
298 }
299 ], log);
300
301 log = [];
302 iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrow, log));
303 try {
304 await iter.throw('Boo!!');
305 assertUnreachable('Expected iter.throw(\'Boo!!\') to throw, but did not ' +
306 'throw');
307 } catch (e) {
308 assertEquals('Boo!!', e);
309 }
310
311 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
312 // whether [sync_iterator] is completed or not.
313 assertEquals({ value: 'sync-value', done: false }, await iter.next('j'));
314 assertEquals([
315 {
316 method: 'throw',
317 sent: 'Boo!!',
318 value: undefined,
319 done: false
320 },
321 {
322 method: 'next',
323 sent: 'j',
324 value: 'sync-value',
325 done: false
326 }
327 ], log);
328
329 // If [sync_iterator].throw() returns a resolved Promise or a Completion
330 // with [[Type]] "normal" or "return", return a resolved Promise
331 log = [];
neis 2017/02/20 09:41:20 A function call cannot return a "normal" completio
332 iter = %CreateAsyncFromSyncIterator(sync(['sync-value'], kNext|kThrowNormal,
333 log));
334 assertEquals({
335 value: 'Boo!!',
336 done: false
337 }, await iter.throw('Boo!!'));
338
339 // [Async-from-Sync Iterator] merely delegates, and does not keep track of
340 // whether [sync_iterator] is completed or not.
341 assertEquals({ value: 'sync-value', done: false }, await iter.next('k'));
342 assertEquals([
343 {
344 method: 'throw',
345 sent: 'Boo!!',
346 value: undefined,
347 done: false
348 },
349 {
350 method: 'next',
351 sent: 'k',
352 value: 'sync-value',
353 done: false
354 }
355 ], log);
356
357 // Let nextValue be IteratorValue(nextResult).
358 // IfAbruptRejectPromise(nextValue, promiseCapability).)
359 iter = %CreateAsyncFromSyncIterator({
360 next() { return { get value() { throw "BadValue!" }, done: false }; }
361 });
362 try {
363 await iter.next();
364 assertUnreachable('Expected `iter.next()` to throw, but did not throw');
365 } catch (e) {
366 assertEquals('BadValue!', e);
367 }
368
369 // Let nextDone be IteratorComplete(nextResult).
370 // IfAbruptRejectPromise(nextDone, promiseCapability).
371 iter = %CreateAsyncFromSyncIterator({
372 next() { return { value: undefined, get done() { throw "BadValue!" } }; }
373 });
374 try {
375 await iter.next();
376 assertUnreachable('Expected `iter.next()` to throw, but did not throw');
377 } catch (e) {
378 assertEquals('BadValue!', e);
379 }
380
381 // IfAbruptRejectPromise(returnResult, promiseCapability).
382 // Let returnValue be IteratorValue(returnResult).
383 iter = %CreateAsyncFromSyncIterator({
384 return() { return { get value() { throw "BadValue!" }, done: false }; }
385 });
386 try {
387 await iter.return();
388 assertUnreachable('Expected `iter.return()` to throw, but did not throw');
389 } catch (e) {
390 assertEquals('BadValue!', e);
391 }
392
393 // IfAbruptRejectPromise(returnValue, promiseCapability).
394 // Let returnDone be IteratorComplete(returnResult).
395 iter = %CreateAsyncFromSyncIterator({
396 return() { return { value: undefined, get done() { throw "BadValue!" } }; }
397 });
398 try {
399 await iter.return();
400 assertUnreachable('Expected `iter.return()` to throw, but did not throw');
401 } catch (e) {
402 assertEquals('BadValue!', e);
403 }
404
405 // IfAbruptRejectPromise(throwResult, promiseCapability).
406 // Let throwValue be IteratorValue(throwResult).
407 iter = %CreateAsyncFromSyncIterator({
408 throw() { return { get value() { throw "BadValue!" }, done: false }; }
409 });
410 try {
411 await iter.throw();
412 assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
413 } catch (e) {
414 assertEquals('BadValue!', e);
415 }
416
417 // IfAbruptRejectPromise(throwValue, promiseCapability).
418 // Let throwDone be IteratorComplete(throwResult).
419 iter = %CreateAsyncFromSyncIterator({
420 throw() { return { value: undefined, get done() { throw "BadValue!" } }; }
421 });
422 try {
423 await iter.throw();
424 assertUnreachable('Expected `iter.throw()` to throw, but did not throw');
425 } catch (e) {
426 assertEquals('BadValue!', e);
427 }
428 })().catch(function(error) {
429 testFailed = true;
430 testFailure = error;
431 });
432
433 %RunMicrotasks();
434
435 if (testFailed) {
436 throw testFailure;
437 }
neis 2017/02/20 09:41:20 Could you please add - a test where the sync itera
OLDNEW
« src/builtins/builtins-async-iterator.cc ('K') | « test/cctest/interpreter/test-bytecode-generator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698