async.es6.js 12 KB

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