UNPKG

11.9 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2014, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
7 * additional grant of patent rights can be found in the PATENTS file in
8 * the same directory.
9 */
10
11var assert = require("assert");
12
13describe("async functions and await expressions", function() {
14 Promise = require("promise");
15
16 describe("regeneratorRuntime", function() {
17 it("should be defined globally", function() {
18 var global = Function("return this")();
19 assert.ok("regeneratorRuntime" in global);
20 assert.strictEqual(global.regeneratorRuntime, regeneratorRuntime);
21 });
22
23 it("should have a .wrap method", function() {
24 assert.strictEqual(typeof regeneratorRuntime.wrap, "function");
25 });
26 });
27
28 describe("Promise", function() {
29 it("should be defined globally", function() {
30 var global = Function("return this")();
31 assert.ok("Promise" in global);
32 assert.strictEqual(global.Promise, Promise);
33 });
34
35 it("should be a function", function() {
36 assert.strictEqual(typeof Promise, "function");
37 });
38 });
39
40 describe("no-await async function", function() {
41 it("should return a Promise", function(done) {
42 var called = false;
43
44 async function noAwait(value) {
45 called = true;
46 return value;
47 }
48
49 var promise = noAwait("asdf");
50 assert.strictEqual(called, true);
51
52 promise.then(function(value) {
53 assert.strictEqual(called, true);
54 assert.strictEqual(value, "asdf");
55 done();
56 }).catch(done);
57 });
58 });
59
60 describe("one-await async function", function() {
61 it("should finish asynchronously", function(done) {
62 var flag1 = false;
63 var flag2 = false;
64
65 async function oneAwait(value) {
66 flag1 = true;
67 var result = await value;
68 flag2 = true;
69 return result;
70 }
71
72 var promise = oneAwait("asdf");
73 assert.strictEqual(flag1, true);
74 assert.strictEqual(flag2, false);
75
76 promise.then(function(value) {
77 assert.strictEqual(flag2, true);
78 assert.strictEqual(value, "asdf");
79 done();
80 }).catch(done);
81 });
82 });
83
84 describe("nested async function calls", function() {
85 it("should evaluate in the right order", function(done) {
86 var markers = [];
87
88 async function innerMost(marker) {
89 markers.push(marker);
90 return await marker;
91 }
92
93 async function inner(marker) {
94 markers.push(marker);
95
96 assert.strictEqual(
97 await innerMost(marker + 1),
98 marker + 1
99 );
100
101 markers.push(marker + 2);
102
103 assert.strictEqual(
104 await innerMost(marker + 3),
105 marker + 3
106 );
107
108 markers.push(marker + 4);
109 }
110
111 async function outer() {
112 markers.push(0);
113 await inner(1);
114 markers.push(6);
115 await inner(7);
116 markers.push(12);
117 }
118
119 outer().then(function() {
120 var expected = [];
121 for (var i = 0; i <= 12; ++i)
122 expected.push(i);
123 assert.deepEqual(markers, expected);
124 done();
125 }).catch(done);
126 });
127 });
128
129 describe("dependent promises", function() {
130 it("should be awaitable out of order", function(done) {
131 async function outer(value) {
132 var resolved = false;
133 var p1 = new Promise(function(resolve) {
134 setTimeout(function() {
135 resolve(value + 1);
136 resolved = true;
137 }, 0);
138 });
139
140 assert.strictEqual(resolved, false);
141
142 var v2 = await p1.then(function(value) {
143 return value + 1;
144 });
145
146 assert.strictEqual(resolved, true);
147
148 var v1 = await p1;
149
150 return [v1, v2];
151 }
152
153 outer(1).then(function(pair) {
154 assert.deepEqual(pair, [2, 3]);
155 done();
156 }).catch(done);
157 });
158 });
159
160 describe("rejected promises", function() {
161 it("should cause await expressions to throw", function(done) {
162 var error = new Error("rejected");
163
164 async function f(arg) {
165 try {
166 return await arg;
167 } catch (e) {
168 assert.strictEqual(e, error);
169 return "did throw";
170 }
171 }
172
173 Promise.all([
174 f(Promise.reject(error)),
175 f(Promise.resolve("did not throw"))
176 ]).then(function(results) {
177 assert.deepEqual(results, [
178 "did throw",
179 "did not throw"
180 ]);
181 done();
182 }).catch(done);
183 });
184
185 it("should be returned by exceptional async functions", function(done) {
186 var error = new Error("rejected");
187
188 async function e(arg) {
189 if (arg) {
190 throw arg;
191 }
192 return "did not throw";
193 }
194
195 async function f(arg) {
196 return await e(arg);
197 }
198
199 async function g(arg) {
200 return await f(arg);
201 }
202
203 async function h(arg) {
204 return await Promise.all([
205 g(arg),
206 Promise.resolve("dummy")
207 ]);
208 }
209
210 Promise.all([
211 h(error).then(function() {
212 done(new Error("should not have resolved"));
213 }, function(e) {
214 assert.strictEqual(e, error);
215 return "ok1";
216 }),
217 h(null).then(function(result) {
218 assert.deepEqual(result, [
219 "did not throw",
220 "dummy"
221 ]);
222 return "ok2";
223 })
224 ]).then(function(results) {
225 assert.deepEqual(results, ["ok1", "ok2"]);
226 done();
227 }).catch(done);
228 });
229
230 it("should propagate failure when returned", function() {
231 var rejection = new Error("rejection");
232
233 async function f() {
234 return new Promise(function(resolve, reject) {
235 reject(rejection);
236 });
237 }
238
239 return f().then(function(result) {
240 assert.ok(false, "should have been rejected");
241 }, function(error) {
242 assert.strictEqual(error, rejection);
243 });
244 });
245 });
246
247 describe("async function expressions", function() {
248 it("should be allowed", function(done) {
249 (async function(arg) {
250 return await arg;
251 })(Promise.resolve(1234)).then(function(value) {
252 assert.strictEqual(value, 1234);
253 done();
254 }).catch(done);
255 });
256 });
257});
258
259describe("async generator functions", function() {
260 it("should return a working AsyncIterator", function() {
261 var markers = [];
262
263 async function *gen(arg) {
264 markers.push(0);
265 var sent = yield arg;
266 markers.push(1);
267 var result = await sent;
268 markers.push(2);
269 assert.strictEqual(await (yield "second"), "sent after second");
270 markers.push(3);
271 return result;
272 }
273
274 var iter = gen("initial argument");
275 assert.deepEqual(markers, []);
276
277 var firstPromise = iter.next();
278 assert.deepEqual(markers, [0]);
279
280 return firstPromise.then(function(firstResult) {
281 assert.deepEqual(firstResult, {
282 value: "initial argument",
283 done: false
284 });
285
286 assert.deepEqual(markers, [0]);
287
288 return iter.next(new Promise(function(resolve) {
289 setTimeout(resolve, 100);
290 }).then(function() {
291 assert.deepEqual(markers, [0, 1]);
292 return "will become final result";
293 }));
294
295 }).then(function(secondResult) {
296 assert.deepEqual(secondResult, {
297 value: "second",
298 done: false
299 });
300
301 assert.deepEqual(markers, [0, 1, 2]);
302
303 return iter.next("sent after second");
304
305 }).then(function(finalResult) {
306 assert.deepEqual(markers, [0, 1, 2, 3]);
307 assert.deepEqual(finalResult, {
308 value: "will become final result",
309 done: true
310 });
311 });
312 });
313
314 it("should keep results in order", function() {
315 async function *range(limit) {
316 var before = [];
317 var after = [];
318 for (var i = 0; i < limit; ++i) {
319 before.push(i);
320 yield i;
321 after.push(i);
322 }
323 assert.deepEqual(before, after);
324 return before;
325 }
326
327 var limit = 10;
328 var iter = range(limit);
329 var promises = [];
330 var results = [];
331
332 for (var i = 0; i < limit; ++i) {
333 var promise = iter.next();
334 promises.push(promise);
335
336 promise.then(function(result) {
337 assert.strictEqual(result.done, false);
338 results.push(result);
339 });
340 }
341
342 assert.deepEqual(results, []);
343
344 return Promise.all(promises).then(function(promiseResults) {
345 assert.deepEqual(results, promiseResults);
346
347 return iter.next();
348
349 }).then(function(finalResult) {
350 assert.deepEqual(results.map(function(result) {
351 return result.value;
352 }), finalResult.value);
353
354 assert.strictEqual(finalResult.done, true);
355 });
356 });
357
358 it("should be able to handle many awaits", function() {
359 var awaitCount = 0;
360
361 function countAwait(i) {
362 return Promise.resolve(i).then(function() {
363 ++awaitCount;
364 });
365 }
366
367 async function *gen(limit) {
368 await countAwait(0);
369 yield 1;
370 await countAwait(2);
371 await countAwait(3);
372 yield 4;
373 await countAwait(5);
374 await countAwait(6);
375 await countAwait(7);
376 yield 8;
377 for (var i = 0; i < limit; ++i) {
378 await countAwait(i);
379 }
380 return "done";
381 }
382
383 var iter = gen(100);
384
385 return iter.next().then(function(result) {
386 assert.strictEqual(awaitCount, 1);
387
388 assert.deepEqual(result, {
389 value: 1,
390 done: false
391 });
392
393 return iter.next();
394
395 }).then(function(result) {
396 assert.strictEqual(awaitCount, 3);
397
398 assert.deepEqual(result, {
399 value: 4,
400 done: false
401 });
402
403 return iter.next();
404
405 }).then(function(result) {
406 assert.strictEqual(awaitCount, 6);
407
408 assert.deepEqual(result, {
409 value: 8,
410 done: false
411 });
412
413 return iter.next();
414
415 }).then(function(result) {
416 assert.strictEqual(awaitCount, 6 + 100);
417
418 assert.deepEqual(result, {
419 value: "done",
420 done: true
421 });
422
423 return iter.next();
424
425 }).then(function(result) {
426 assert.deepEqual(result, {
427 value: void 0,
428 done: true
429 });
430 });
431 });
432
433 it("should not propagate exceptions between iterations", function() {
434 async function *gen() {
435 yield 1;
436 yield 2;
437 }
438
439 var iter = gen();
440
441 return iter.next().then(function(result) {
442 assert.deepEqual(result, {
443 value: 1,
444 done: false
445 });
446
447 return iter.throw(new Error("thrown from first yield"));
448
449 }).then(function() {
450 throw new Error("should have thrown");
451
452 }, function(error) {
453 assert.strictEqual(error.message, "thrown from first yield");
454 return iter.next();
455
456 }).then(function(result) {
457 assert.deepEqual(result, {
458 value: void 0,
459 done: true
460 });
461 });
462 });
463
464 it("should allow yielding a rejected Promise", function() {
465 var yielded = new Error("yielded rejection");
466 var returned = new Error("returned rejection");
467
468 async function *gen() {
469 assert.strictEqual(yield Promise.reject(yielded), "first sent");
470 assert.strictEqual(yield "middle", "second sent");
471 return Promise.reject(returned);
472 }
473
474 var iter = gen();
475
476 return iter.next().then(function(result) {
477 assert.ok(false, "should have yielded a rejected Promise");
478 }, function(error) {
479 assert.strictEqual(error, yielded);
480 return iter.next("first sent");
481 }).then(function(result) {
482 assert.deepEqual(result, {
483 value: "middle",
484 done: false
485 });
486 return iter.next("second sent");
487 }).then(function(result) {
488 assert.ok(false, "should have returned a rejected Promise");
489 }, function(error) {
490 assert.strictEqual(error, returned);
491 });
492 });
493});