ES6PromiseAsync.js 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. // ES6 Promise async tests -- verifies functionality of promise async operations
  7. function echo(str) {
  8. WScript.Echo(str);
  9. }
  10. function getAsyncFulfilledPromise(t, v, fail) {
  11. fail = fail || false;
  12. var p = new Promise(
  13. function(resolve,reject) {
  14. if (fail) {
  15. WScript.SetTimeout(function() { reject(v) }, 0);
  16. } else {
  17. WScript.SetTimeout(function() { resolve(v) }, 0);
  18. }
  19. }
  20. );
  21. p.then(
  22. function(result) {
  23. echo(t + v + ' success: ' + result);
  24. },
  25. function(err) {
  26. echo(t + v + ' failure: ' + err);
  27. }
  28. );
  29. return p;
  30. }
  31. function getAsyncResolvePromise(t, v) {
  32. return getAsyncFulfilledPromise(t, v, false);
  33. }
  34. function getAsyncRejectPromise(t, v) {
  35. return getAsyncFulfilledPromise(t, v, true);
  36. }
  37. // Copy promise and attempt to call resolve handler twice.
  38. // Since we can only call the Promise.all resolve handlers once, we can tamper with the result value for this promise.
  39. function tamper(p, result, useresult) {
  40. return Object.assign(p, {
  41. then(onFulfilled, onRejected) {
  42. if (useresult) {
  43. onFulfilled(result);
  44. } else {
  45. onFulfilled();
  46. }
  47. return Promise.prototype.then.call(this, onFulfilled, onRejected);
  48. }
  49. });
  50. }
  51. var tests = [
  52. {
  53. name: "Promise basic behavior",
  54. body: function (index) {
  55. var promise = new Promise(
  56. function(resolve,reject) {
  57. echo('Test #' + index + ' - Executor function called synchronously');
  58. resolve('basic:success');
  59. }
  60. );
  61. promise.then(
  62. function(result) {
  63. echo('Test #' + index + ' - Success handler called with result = ' + result);
  64. },
  65. function(err) {
  66. echo('Test #' + index + ' - Error handler called with err = ' + err);
  67. }
  68. );
  69. }
  70. },
  71. {
  72. name: "Promise basic error behavior",
  73. body: function (index) {
  74. var promise = new Promise(
  75. function(resolve,reject) {
  76. echo('Test #' + index + ' - Executor function called synchronously');
  77. reject('basic:error');
  78. }
  79. );
  80. promise.then(
  81. function(result) {
  82. echo('Test #' + index + ' - Success handler called with result = ' + result);
  83. },
  84. function(err) {
  85. echo('Test #' + index + ' - Error handler called with err = ' + err);
  86. }
  87. );
  88. }
  89. },
  90. {
  91. name: "Promise with multiple then handlers",
  92. body: function (index) {
  93. var promise = new Promise(
  94. function(resolve,reject) {
  95. resolve('multithen:success');
  96. }
  97. );
  98. promise.then(
  99. function(result) {
  100. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  101. },
  102. function(err) {
  103. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  104. }
  105. );
  106. promise.then(
  107. function(result) {
  108. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  109. },
  110. function(err) {
  111. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  112. }
  113. );
  114. promise.then(
  115. function(result) {
  116. echo('Test #' + index + ' - Success handler #3 called with result = ' + result);
  117. },
  118. function(err) {
  119. echo('Test #' + index + ' - Error handler #3 called with err = ' + err);
  120. }
  121. );
  122. }
  123. },
  124. {
  125. name: "Promise with chained then handlers",
  126. body: function (index) {
  127. var promise = new Promise(
  128. function(resolve,reject) {
  129. resolve('chain:success1');
  130. }
  131. );
  132. promise.then(
  133. function(result) {
  134. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  135. return new Promise(
  136. function(resolve,reject) {
  137. resolve('chain:success2');
  138. }
  139. );
  140. },
  141. function(err) {
  142. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  143. }
  144. ).then(
  145. function(result) {
  146. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  147. },
  148. function(err) {
  149. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  150. }
  151. );
  152. }
  153. },
  154. {
  155. name: "Promise with a throwing executor function",
  156. body: function (index) {
  157. var promise = new Promise(
  158. function(resolve,reject) {
  159. throw 'basic:throw';
  160. }
  161. );
  162. promise.then(
  163. function(result) {
  164. echo('Test #' + index + ' - Success handler called with result = ' + result);
  165. },
  166. function(err) {
  167. echo('Test #' + index + ' - Error handler called with err = ' + err);
  168. }
  169. );
  170. }
  171. },
  172. {
  173. name: "Promise with a potential thenable that throws when getting the 'then' property",
  174. body: function (index) {
  175. var promise = new Promise(
  176. function(resolve,reject) {
  177. resolve('thenable.get:unused');
  178. }
  179. );
  180. promise.then(
  181. function(result) {
  182. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  183. return { get then() { throw 'thenable.get:error!'; } };
  184. },
  185. function(err) {
  186. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  187. }
  188. ).then(
  189. function(result) {
  190. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  191. },
  192. function(err) {
  193. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  194. }
  195. );
  196. }
  197. },
  198. {
  199. name: "Promise with a potential thenable that throws when calling the 'then' function",
  200. body: function (index) {
  201. var promise = new Promise(
  202. function(resolve,reject) {
  203. resolve('thenable.call:unused');
  204. }
  205. );
  206. promise.then(
  207. function(result) {
  208. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  209. return { then: function() { throw 'thenable.call:error!'; } };
  210. },
  211. function(err) {
  212. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  213. }
  214. ).then(
  215. function(result) {
  216. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  217. },
  218. function(err) {
  219. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  220. }
  221. );
  222. }
  223. },
  224. {
  225. name: "Promise with a success handler that throws when called",
  226. body: function (index) {
  227. var promise = new Promise(
  228. function(resolve,reject) {
  229. resolve('success.throw:unused');
  230. }
  231. );
  232. promise.then(
  233. function(result) {
  234. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  235. throw 'success.throw:error';
  236. },
  237. function(err) {
  238. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  239. }
  240. ).then(
  241. function(result) {
  242. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  243. },
  244. function(err) {
  245. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  246. }
  247. );
  248. }
  249. },
  250. {
  251. name: "Promise with an error handler that throws when called",
  252. body: function (index) {
  253. var promise = new Promise(
  254. function(resolve,reject) {
  255. reject('error.throw:unused');
  256. }
  257. );
  258. promise.then(
  259. function(result) {
  260. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  261. },
  262. function(err) {
  263. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  264. throw 'error.throw:error';
  265. }
  266. ).then(
  267. function(result) {
  268. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  269. },
  270. function(err) {
  271. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  272. }
  273. );
  274. }
  275. },
  276. {
  277. name: "Promise with an executor function that creates a self-resolution error",
  278. body: function (index) {
  279. var promise = new Promise(
  280. function(resolve,reject) {
  281. WScript.SetTimeout(
  282. function() {
  283. resolve(promise);
  284. },
  285. 0
  286. );
  287. }
  288. );
  289. promise.then(
  290. function(result) {
  291. echo('Test #' + index + ' - Success handler called with result = ' + result);
  292. },
  293. function(err) {
  294. echo('Test #' + index + ' - Error handler called with err = ' + err);
  295. }
  296. );
  297. }
  298. },
  299. {
  300. name: "Promise basic catch behavior",
  301. body: function (index) {
  302. var promise = new Promise(
  303. function(resolve,reject) {
  304. reject('error');
  305. }
  306. );
  307. promise.catch(
  308. function(err) {
  309. echo('Test #' + index + ' - Catch handler called with err = ' + err);
  310. }
  311. );
  312. }
  313. },
  314. {
  315. name: "Promise chained catch behavior",
  316. body: function (index) {
  317. var promise = new Promise(
  318. function(resolve,reject) {
  319. reject('error1');
  320. }
  321. );
  322. promise.catch(
  323. function(err) {
  324. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  325. throw 'error2';
  326. }
  327. ).catch(
  328. function(err) {
  329. echo('Test #' + index + ' - Catch handler #2 called with err = ' + err);
  330. }
  331. );
  332. }
  333. },
  334. {
  335. name: "Promise then and catch interleaved",
  336. body: function (index) {
  337. var promise = new Promise(
  338. function(resolve,reject) {
  339. reject('error1');
  340. }
  341. );
  342. promise.catch(
  343. function(err) {
  344. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  345. return 'ok';
  346. }
  347. ).then(
  348. function(result) {
  349. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  350. throw 'error2';
  351. },
  352. function(err) {
  353. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  354. }
  355. ).catch(
  356. function(err) {
  357. echo('Test #' + index + ' - Catch handler #2 called with err = ' + err);
  358. }
  359. );
  360. }
  361. },
  362. {
  363. name: "Promise identity function is used when no success handler is provided",
  364. body: function (index) {
  365. var promise = new Promise(
  366. function(resolve,reject) {
  367. resolve('success');
  368. }
  369. );
  370. promise.then(
  371. undefined,
  372. function(err) {
  373. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  374. }
  375. ).then(
  376. function(result) {
  377. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  378. },
  379. function(err) {
  380. echo('Test #' + index + ' - Error handler #2 called with err = ' + err);
  381. }
  382. );
  383. }
  384. },
  385. {
  386. name: "Promise thrower function is used when no error handler is provided",
  387. body: function (index) {
  388. var promise = new Promise(
  389. function(resolve,reject) {
  390. reject('failure');
  391. }
  392. );
  393. promise.then(
  394. function(result) {
  395. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  396. },
  397. undefined
  398. ).then(
  399. function(result) {
  400. echo('Test #' + index + ' - Success handler #2 called with result = ' + result);
  401. },
  402. undefined
  403. ).catch(
  404. function(err) {
  405. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  406. }
  407. );
  408. }
  409. },
  410. {
  411. name: "Promise.resolve creates a fulfilled resolved promise",
  412. body: function (index) {
  413. var promise = Promise.resolve('resolved promise result');
  414. promise.then(
  415. function(result) {
  416. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  417. }
  418. );
  419. }
  420. },
  421. {
  422. name: "Promise.resolve called with a promise returns the same promise",
  423. body: function (index) {
  424. var promise = Promise.resolve(42);
  425. var wrappedPromise = Promise.resolve(promise);
  426. if (promise !== wrappedPromise) {
  427. echo('Test #' + index + ' - Promise.resolve returns a new promise object!');
  428. }
  429. }
  430. },
  431. {
  432. name: "Promise.reject creates a fulfilled rejected promise",
  433. body: function (index) {
  434. var promise = Promise.reject('rejected promise result');
  435. promise.catch(
  436. function(err) {
  437. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  438. }
  439. );
  440. }
  441. },
  442. {
  443. name: "Promise.reject called with a promise returns a promise for that promise",
  444. body: function (index) {
  445. var promise = Promise.reject(42);
  446. var wrappedPromise = Promise.reject(promise);
  447. if (promise === wrappedPromise) {
  448. echo('Test #' + index + ' - Promise.reject does not return a new promise object!');
  449. }
  450. }
  451. },
  452. {
  453. name: "Promise.race with an object containing a non-function iterator property",
  454. body: function (index) {
  455. var objectWithNonObjectIterator = {
  456. [Symbol.iterator]: 123
  457. };
  458. var p = Promise.race(objectWithNonObjectIterator);
  459. p.catch(
  460. function(err) {
  461. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  462. }
  463. );
  464. }
  465. },
  466. {
  467. name: "Promise.race with this argument missing the resolve function",
  468. body: function (index) {
  469. var _resolve = Promise.resolve;
  470. Promise.resolve = undefined;
  471. var p = Promise.race([Promise.reject(42)]);
  472. p.catch(
  473. function(err) {
  474. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  475. }
  476. );
  477. Promise.resolve = _resolve;
  478. }
  479. },
  480. {
  481. name: "Promise.race with this argument resolve function returning a non-object",
  482. body: function (index) {
  483. var _resolve = Promise.resolve;
  484. Promise.resolve = function() { return undefined; };
  485. var p = Promise.race([Promise.reject(42)]);
  486. p.catch(
  487. function(err) {
  488. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  489. }
  490. );
  491. Promise.resolve = _resolve;
  492. }
  493. },
  494. {
  495. name: "Promise.race with this argument resolve function returning an object with no then function",
  496. body: function (index) {
  497. var _resolve = Promise.resolve;
  498. Promise.resolve = function() { return {}; };
  499. var p = Promise.race([Promise.reject(42)]);
  500. p.catch(
  501. function(err) {
  502. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  503. }
  504. );
  505. Promise.resolve = _resolve;
  506. }
  507. },
  508. {
  509. name: "Promise.race with an object containing an iterator that throws",
  510. body: function (index) {
  511. var objectWithIterator = {
  512. [Symbol.iterator]: function() {
  513. return {
  514. next: function () {
  515. throw new TypeError('failure inside iterator');
  516. }
  517. };
  518. }
  519. };
  520. var p = Promise.race(objectWithIterator);
  521. p.catch(
  522. function(err) {
  523. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  524. }
  525. );
  526. }
  527. },
  528. {
  529. name: "Promise.race still returns a rejected promise if anything throws while iterating, even if resolved promises are encountered",
  530. body: function (index) {
  531. var objectWithIterator = {
  532. [Symbol.iterator]: function() {
  533. return {
  534. i: 0,
  535. next: function () {
  536. if (this.i > 2)
  537. {
  538. throw new TypeError('failure inside iterator');
  539. }
  540. this.i++;
  541. return {
  542. done: this.i == 5,
  543. value: Promise.resolve('resolved promise completion #' + this.i)
  544. };
  545. }
  546. };
  547. }
  548. };
  549. var p = Promise.race(objectWithIterator);
  550. p.then(
  551. function(result) {
  552. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  553. },
  554. function(err) {
  555. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  556. }
  557. );
  558. }
  559. },
  560. {
  561. name: "Promise.race fulfills with the same value as the first encountered resolved promise",
  562. body: function (index) {
  563. var promises = [
  564. new Promise(function() {}),
  565. Promise.resolve('first promise'),
  566. Promise.resolve('second promise'),
  567. Promise.reject('third promise')
  568. ];
  569. var p = Promise.race(promises);
  570. p.then(
  571. function(result) {
  572. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  573. },
  574. function(err) {
  575. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  576. }
  577. );
  578. }
  579. },
  580. {
  581. name: "Promise.race fulfills with the same value as the first encountered resolved promise (promises complete async)",
  582. body: function (index) {
  583. var promises = [
  584. new Promise(function() {}),
  585. getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
  586. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  587. getAsyncRejectPromise('Test #' + index + ' - ', 'p3')
  588. ];
  589. var p = Promise.race(promises);
  590. p.then(
  591. function(result) {
  592. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  593. },
  594. function(err) {
  595. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  596. }
  597. );
  598. }
  599. },
  600. {
  601. name: "Promise.race fulfills with the same value as the first encountered rejected promise (promises complete async)",
  602. body: function (index) {
  603. var promises = [
  604. new Promise(function() {}),
  605. getAsyncRejectPromise('Test #' + index + ' - ', 'p1'),
  606. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  607. getAsyncResolvePromise('Test #' + index + ' - ', 'p3')
  608. ];
  609. var p = Promise.race(promises);
  610. p.then(
  611. function(result) {
  612. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  613. },
  614. function(err) {
  615. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  616. }
  617. );
  618. }
  619. },
  620. {
  621. name: "Promise.race passes each element in it's argument to Promise.resolve",
  622. body: function (index) {
  623. var promises = [
  624. 'first promise value',
  625. 42,
  626. new TypeError('some error')
  627. ];
  628. var p = Promise.race(promises);
  629. p.then(
  630. function(result) {
  631. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  632. },
  633. function(err) {
  634. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  635. }
  636. );
  637. }
  638. },
  639. {
  640. name: "Promise.all with an object containing a non-function iterator property",
  641. body: function (index) {
  642. var objectWithNonObjectIterator = {
  643. [Symbol.iterator]: 123
  644. };
  645. var p = Promise.all(objectWithNonObjectIterator);
  646. p.catch(
  647. function(err) {
  648. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  649. }
  650. );
  651. }
  652. },
  653. {
  654. name: "Promise.all with this argument missing the resolve function",
  655. body: function (index) {
  656. var _resolve = Promise.resolve;
  657. Promise.resolve = undefined;
  658. var p = Promise.all([Promise.reject(42)]);
  659. p.catch(
  660. function(err) {
  661. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  662. }
  663. );
  664. Promise.resolve = _resolve;
  665. }
  666. },
  667. {
  668. name: "Promise.all with this argument resolve function returning a non-object",
  669. body: function (index) {
  670. var _resolve = Promise.resolve;
  671. Promise.resolve = function() { return undefined; };
  672. var p = Promise.all([Promise.reject(42)]);
  673. p.catch(
  674. function(err) {
  675. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  676. }
  677. );
  678. Promise.resolve = _resolve;
  679. }
  680. },
  681. {
  682. name: "Promise.all with this argument resolve function returning an object with no then function",
  683. body: function (index) {
  684. var _resolve = Promise.resolve;
  685. Promise.resolve = function() { return {}; };
  686. var p = Promise.all([Promise.reject(42)]);
  687. p.catch(
  688. function(err) {
  689. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  690. }
  691. );
  692. Promise.resolve = _resolve;
  693. }
  694. },
  695. {
  696. name: "Promise.all with an object containing an iterator that throws",
  697. body: function (index) {
  698. var objectWithIterator = {
  699. [Symbol.iterator]: function() {
  700. return {
  701. next: function () {
  702. throw new TypeError('failure inside iterator');
  703. }
  704. };
  705. }
  706. };
  707. var p = Promise.all(objectWithIterator);
  708. p.catch(
  709. function(err) {
  710. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  711. }
  712. );
  713. }
  714. },
  715. {
  716. name: "Promise.all still returns a rejected promise if anything throws while iterating, even if resolved promises are encountered",
  717. body: function (index) {
  718. var objectWithIterator = {
  719. [Symbol.iterator]: function() {
  720. return {
  721. i: 0,
  722. next: function () {
  723. if (this.i > 2)
  724. {
  725. throw new TypeError('failure inside iterator');
  726. }
  727. this.i++;
  728. return {
  729. done: this.i == 5,
  730. value: Promise.resolve('resolved promise completion #' + this.i)
  731. };
  732. }
  733. };
  734. }
  735. };
  736. var p = Promise.all(objectWithIterator);
  737. p.then(
  738. function(result) {
  739. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  740. },
  741. function(err) {
  742. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  743. }
  744. );
  745. }
  746. },
  747. {
  748. name: "Promise.all fulfills with the same value as the first encountered rejected promise",
  749. body: function (index) {
  750. var promises = [
  751. new Promise(function() {}),
  752. Promise.resolve('first promise'),
  753. Promise.resolve('second promise'),
  754. Promise.reject('third promise')
  755. ];
  756. var p = Promise.all(promises);
  757. p.then(
  758. function(result) {
  759. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  760. },
  761. function(err) {
  762. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  763. }
  764. );
  765. }
  766. },
  767. {
  768. name: "Promise.all fulfills with the same value as the first encountered rejected promise (async promises)",
  769. body: function (index) {
  770. var promises = [
  771. new Promise(function() {}),
  772. getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
  773. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  774. getAsyncRejectPromise('Test #' + index + ' - ', 'p3')
  775. ];
  776. var p = Promise.all(promises);
  777. p.then(
  778. function(result) {
  779. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  780. },
  781. function(err) {
  782. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  783. }
  784. );
  785. }
  786. },
  787. {
  788. name: "Promise.all fulfills when all promises in iterable fulfill",
  789. body: function (index) {
  790. var promises = [
  791. getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
  792. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  793. getAsyncResolvePromise('Test #' + index + ' - ', 'p3')
  794. ];
  795. var p = Promise.all(promises);
  796. p.then(
  797. function(result) {
  798. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  799. },
  800. function(err) {
  801. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  802. }
  803. );
  804. }
  805. },
  806. {
  807. name: "Promise.all passes each element in the arguments to Promise.resolve",
  808. body: function (index) {
  809. var promises = [
  810. 'success value 1',
  811. 42,
  812. new TypeError('an error')
  813. ];
  814. var p = Promise.all(promises);
  815. p.then(
  816. function(result) {
  817. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  818. },
  819. function(err) {
  820. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  821. }
  822. );
  823. }
  824. },
  825. {
  826. name: "Promise.all called with empty iterator, calls Promise.resolve synchronously and passes abrupt completion to reject handler",
  827. body: function (index) {
  828. function FakePromise(fn) {
  829. function resolve() { echo(`Test #${index} - resolve called`); throw new Error('oops'); }
  830. function reject(e) { echo(`Test #${index} - reject called: ${e.message}`) }
  831. fn(resolve, reject);
  832. this.then = function(onResolve, onReject) {};
  833. }
  834. FakePromise.resolve = function() {};
  835. Promise.all.call(FakePromise, []);
  836. }
  837. },
  838. {
  839. name: "Promise.resolve called with a thenable calls then on the thenable",
  840. body: function (index) {
  841. var thenable = {
  842. then: function(resolve, reject) {
  843. echo('Test #' + index + ' - Promise.resolve calls thenable.then');
  844. Promise.resolve('nested Promise.resolve call').then(
  845. function(result) {
  846. echo('Test #' + index + ' - Promise.resolve call nested within thenable.then = ' + result);
  847. }
  848. );
  849. }
  850. };
  851. var promise = Promise.resolve(thenable);
  852. }
  853. },
  854. {
  855. name: "Calling promise resolve function with thenable should call thenable.then",
  856. body: function (index) {
  857. var p = new Promise(function(res) {
  858. res({ then: function(resolve, reject) {
  859. echo('Test #' + index + ' - thenable.then resolve = ' + (typeof resolve) + ' reject = ' + (typeof reject));
  860. }});
  861. });
  862. }
  863. },
  864. {
  865. name: "Promise.all doesn't call then for rejected promises",
  866. body: function(index) {
  867. Promise.all([Promise.reject('expected1')]).then(
  868. result => echo(`Test #${index} - Success handler #1 called with result = ${result}`)
  869. ).catch(
  870. err => echo(`Test #${index} - Catch handler #1 called with err = ${err}`)
  871. );
  872. Promise.all([Promise.reject('expected2'), Promise.resolve('unexpected1')]).then(
  873. result => echo(`Test #${index} - Success handler #2 called with result = ${result}`)
  874. ).catch(
  875. err => echo(`Test #${index} - Catch handler #2 called with err = ${err}`)
  876. );
  877. Promise.all([Promise.resolve('unexpected2'), Promise.reject('expected3')]).then(
  878. result => echo(`Test #${index} - Success handler #3 called with result = ${result}`)
  879. ).catch(
  880. err => echo(`Test #${index} - Catch handler #3 called with err = ${err}`)
  881. );
  882. }
  883. },
  884. {
  885. name: "Promise.all with iterator that returns no items",
  886. body: function(index) {
  887. var promises = [];
  888. var p = Promise.all(promises);
  889. p.then(v => {
  890. echo(`Test #${index} - Success handler #1 called with result = '${v}' (length = ${v.length}) (isArray = ${Array.isArray(v)})`);
  891. }).catch(err => {
  892. echo(`Test #${index} - Catch handler called with err = ${err}`);
  893. });
  894. }
  895. },
  896. {
  897. name: "Simple tampering of Promise.all promise changes resolved result value",
  898. body: function(index) {
  899. var promises = [tamper(Promise.resolve('success'), 'tampered', true)];
  900. Promise.all(promises).then(result => {
  901. echo(`Test #${index} - Success handler called with result = '${result}' (length = ${result.length}) (isArray = ${Array.isArray(result)})`);
  902. }).catch(err => {
  903. echo(`Test #${index} - Catch handler called with err = ${err}`);
  904. });
  905. }
  906. },
  907. {
  908. name: "Promise.all - can't prevent remaining elements counter from reaching zero",
  909. body: function (index) {
  910. var promises = [tamper(Promise.resolve('success'))];
  911. Promise.all(promises).then(result => {
  912. echo(`Test #${index} - Success handler called with result = '${result}' (length = ${result.length}) (isArray = ${Array.isArray(result)})`);
  913. }).catch(err => {
  914. echo(`Test #${index} - Catch handler called with err = ${err}`);
  915. });
  916. }
  917. },
  918. {
  919. name: "Promise from Promise.all never resolved before arguments",
  920. body: function (index) {
  921. var promises = [
  922. Promise.resolve(0),
  923. tamper(Promise.resolve(1)),
  924. Promise.resolve(2).then(result => {
  925. echo(`Test #${index} - Success handler #1a called with result = '${result}' (isArray = ${Array.isArray(result)}) (fulfillCalled = ${fulfillCalled})`);
  926. return 3;
  927. }).then(result => {
  928. echo(`Test #${index} - Success handler #1b called with result = '${result}' (isArray = ${Array.isArray(result)}) (fulfillCalled = ${fulfillCalled})`);
  929. return 4;
  930. }).catch(err => {
  931. echo(`Test #${index} - Catch handler #1 called with err = ${err}`);
  932. })
  933. ];
  934. let fulfillCalled = false;
  935. Promise.all(promises).then(result => {
  936. fulfillCalled = true;
  937. echo(`Test #${index} - Success handler #2 called with result = '${result}' (length = ${result.length}) (isArray = ${Array.isArray(result)}) (fulfillCalled = ${fulfillCalled})`);
  938. }).catch((err) => {
  939. echo(`Test #${index} - Catch handler #2 called with err = ${err}`);
  940. });
  941. }
  942. },
  943. {
  944. name: "Promise from Promise.all never resolved if rejected promise in arguments",
  945. body: function (index) {
  946. var promises = [
  947. Promise.resolve(0),
  948. tamper(Promise.resolve(1)),
  949. Promise.reject(2)
  950. ];
  951. Promise.all(promises).then(result => {
  952. echo(`Test #${index} - Success handler #1 called with result = '${result}' (length = ${result.length}) (isArray = ${Array.isArray(result)})`);
  953. }, err => {
  954. echo(`Test #${index} - Error handler #1 called with err = ${err}`);
  955. }).catch(err => {
  956. echo(`Test #${index} - Catch handler #1 called with err = ${err}`);
  957. });
  958. }
  959. },
  960. {
  961. name: "Promise executor resolves with the first call resolve function",
  962. body: function (index) {
  963. var p = new Promise(function(resolve,reject) {
  964. resolve('success');
  965. resolve('failure');
  966. });
  967. p.then(
  968. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  969. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  970. );
  971. }
  972. },
  973. {
  974. name: "Promise executor rejects with the first call reject function",
  975. body: function (index) {
  976. var p = new Promise(function(resolve,reject) {
  977. reject('success');
  978. reject('failure');
  979. });
  980. p.then(
  981. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  982. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  983. );
  984. }
  985. },
  986. {
  987. name: "Promise executor resolves/rejects with the first call to either function",
  988. body: function (index) {
  989. var p = new Promise(function(resolve,reject) {
  990. resolve('success');
  991. reject('failure');
  992. });
  993. p.then(
  994. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  995. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  996. );
  997. }
  998. },
  999. {
  1000. name: "Promise executor rejects/resolves with the first call to either function",
  1001. body: function (index) {
  1002. var p = new Promise(function(resolve,reject) {
  1003. reject('success');
  1004. resolve('failure');
  1005. });
  1006. p.then(
  1007. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  1008. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  1009. );
  1010. }
  1011. },
  1012. {
  1013. name: "Promise executor rejects/resolves/rejects with the first call to either function",
  1014. body: function (index) {
  1015. var p = new Promise(function(resolve,reject) {
  1016. reject('success');
  1017. resolve('failure');
  1018. reject('failure');
  1019. });
  1020. p.then(
  1021. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  1022. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  1023. );
  1024. }
  1025. },
  1026. {
  1027. name: "Promise executor resolves/rejects/resolves with the first call to either function",
  1028. body: function (index) {
  1029. var p = new Promise(function(resolve,reject) {
  1030. resolve('success');
  1031. reject('failure');
  1032. resolve('failure');
  1033. });
  1034. p.then(
  1035. (res) => { echo(`Test #${index} - Success handler #1 called with res = '${res}'`); },
  1036. (err) => { echo(`Test #${index} - Error handler #1 called with err = '${err}'`); }
  1037. );
  1038. }
  1039. },
  1040. {
  1041. name: "Promise.prototype.finally - called for resolved promise",
  1042. body: function (index) {
  1043. var p = Promise.resolve("failure");
  1044. p.finally((arg) => { if(arg == "failure") { echo(`Test #${index} - Failed finally handler called with incorrect parameter = '${arg}'`); }
  1045. else {echo(`Test #${index} - Success finally handler called for resolved promise without value`); } } );
  1046. }
  1047. },
  1048. {
  1049. name: "Promise.prototype.finally - called for rejected promise",
  1050. body: function (index) {
  1051. var p = Promise.reject("failure");
  1052. p.finally((arg) => { if(arg == "failure") { echo(`Test #${index} - Failed finally handler called with incorrect parameter = '${arg}'`); }
  1053. else { echo(`Test #${index} - Success finally handler called for rejected promise without value`); } } );
  1054. }
  1055. },
  1056. {
  1057. name: "Promise.prototype.finally passes through result for Reject",
  1058. body: function (index) {
  1059. var p = Promise.reject("Result");
  1060. var final = p.finally((arg) => { return "failure" } );
  1061. final.then((e) => { echo(`Test #${index} - Failed - wrong status passed through finally`); },
  1062. (e) => { if(e == "Result") { echo(`Test #${index} - Success - Rejected status and value passed through finally`); }
  1063. else { echo(`Test #${index} - Failed - wrong value passed through finally`); }});
  1064. }
  1065. },
  1066. {
  1067. name: "Promise.prototype.finally passes through result for Resolve",
  1068. body: function (index) {
  1069. var p = Promise.resolve("Result");
  1070. var final = p.finally((arg) => { return "failure" } );
  1071. final.then((e) => { if(e == "Result") { echo(`Test #${index} - Success - Resolved status and value passed through finally`); }
  1072. else { echo(`Test #${index} - Failed - wrong value passed through finally`); }},
  1073. (e) => { echo(`Test #${index} - Failed - wrong status passed through finally`); });
  1074. }
  1075. },
  1076. {
  1077. name: "Promise.prototype.finally passes through result for Reject with not callable argument",
  1078. body: function (index) {
  1079. var p = Promise.reject("Result");
  1080. var final = p.finally("not callable");
  1081. final.then((e) => { echo(`Test #${index} - Failed - wrong status passed through finally`); },
  1082. (e) => { if(e == "Result") { echo(`Test #${index} - Success - Rejected status and value passed through finally with not callable argument`); }
  1083. else { echo(`Test #${index} - Failed - wrong value passed through finally`); }});
  1084. }
  1085. },
  1086. {
  1087. name: "Promise.prototype.finally passes through result for Resolve with not callable argument",
  1088. body: function (index) {
  1089. var p = Promise.resolve("Result");
  1090. var final = p.finally("not callable");
  1091. final.then((e) => { if(e == "Result") { echo(`Test #${index} - Success - Resolved status and value passed through finally with not callable argument`); }
  1092. else { echo(`Test #${index} - Failed - wrong value passed through finally`); }},
  1093. (e) => { echo(`Test #${index} - Failed - wrong status passed through finally`); });
  1094. }
  1095. },
  1096. {
  1097. name: "Promise.prototype.finally throws own rejection after a resolved promise",
  1098. body: function (index) {
  1099. var p = Promise.resolve("Result");
  1100. var final = p.finally(()=>{throw "own rejection";});
  1101. final.then((e) => { (e) => echo(`Test #${index} - Failed - wrong status passed through finally`); },
  1102. (e) => { if(e == "own rejection") { echo(`Test #${index} - Success - own rejection passed through finally`); }
  1103. else {echo(`Test #${index} - Failed - wrong result ${e} passed through finally`); } } );
  1104. }
  1105. },
  1106. {
  1107. name: "Promise.prototype.finally throws own rejection after a rejected promise",
  1108. body: function (index) {
  1109. var p = Promise.reject("Result");
  1110. var final = p.finally(()=>{throw "own rejection";});
  1111. final.then((e) => { (e) => echo(`Test #${index} - Failed - wrong status passed through finally`); },
  1112. (e) => { if(e == "own rejection") { echo(`Test #${index} - Success - own rejection passed through finally`); }
  1113. else {echo(`Test #${index} - Failed - wrong result ${e} passed through finally`); } } );
  1114. }
  1115. },
  1116. {
  1117. name: "Ensure Multiple then handlers on a single promise are executed in correct order",
  1118. body: function (index) {
  1119. let val = -7
  1120. let resolveFunc;
  1121. const p = new Promise((resolve, reject) => {
  1122. resolveFunc = resolve;
  1123. });
  1124. p.then(() => {
  1125. val = val * 3;
  1126. });
  1127. p.then(() => {
  1128. val = val + 21
  1129. });
  1130. p.then(() => {
  1131. echo('Test #' + index + ' - val is ' + val + '(Expect 0)');
  1132. });
  1133. resolveFunc();
  1134. }
  1135. },
  1136. {
  1137. name: "Promise.allSettled settles when all promises in iterable settle",
  1138. body: function (index) {
  1139. var iterable = [getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
  1140. Promise.resolve('p2'),
  1141. Promise.reject('p3'),
  1142. getAsyncRejectPromise('Test #' + index + ' - ', 'p4'),];
  1143. Promise.allSettled(iterable).then(
  1144. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1145. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1146. }
  1147. },
  1148. {
  1149. name: "Promise.allSettled settles even if all promises reject",
  1150. body: function (index) {
  1151. var iterable = [getAsyncRejectPromise('Test #' + index + ' - ', 'p1'),
  1152. Promise.reject('p2'),
  1153. Promise.reject('p3')];
  1154. Promise.allSettled(iterable).then(
  1155. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1156. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1157. }
  1158. },
  1159. {
  1160. name: "Promise.allSettled settles immediately with an empty iterator",
  1161. body: function (index) {
  1162. var iterable = [];
  1163. Promise.allSettled(iterable).then(
  1164. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1165. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1166. }
  1167. },
  1168. {
  1169. name: "Promise.allSettled doesn't settle if some promises don't settle",
  1170. body: function (index) {
  1171. var iterable = [Promise.resolve('p1'), new Promise(()=>{})];
  1172. Promise.allSettled(iterable).then(
  1173. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1174. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1175. }
  1176. },
  1177. {
  1178. name: "Promise.allSettled rejects immediately with an iterator that throws",
  1179. body: function (index) {
  1180. var objectWithIterator = {
  1181. [Symbol.iterator]: function() {
  1182. return {
  1183. i: 0,
  1184. next: function () {
  1185. if (this.i > 2)
  1186. {
  1187. throw new TypeError('failure inside iterator');
  1188. }
  1189. this.i++;
  1190. return {
  1191. done: this.i == 5,
  1192. value: getAsyncResolvePromise('Test #' + index + ' - ', 'p' + this.i)
  1193. };
  1194. }
  1195. };
  1196. }
  1197. };
  1198. Promise.allSettled(objectWithIterator).then(
  1199. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1200. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1201. }
  1202. },
  1203. {
  1204. name: "Promise.allSettled resolve and reject functions cannot be called multiple times",
  1205. body: function(index) {
  1206. let oldThen = Promise.prototype.then;
  1207. try {
  1208. var resolveFunc;
  1209. var rejectFunc;
  1210. Promise.prototype.then = function(resolve, reject) {
  1211. console.log(`Test #${index} - Temp then handler called from Promise.allSettled`);
  1212. // Stash resolve functions
  1213. resolveFunc = resolve;
  1214. rejectFunc = reject;
  1215. // Reset Promise#then
  1216. Promise.prototype.then = oldThen;
  1217. // Call builtin Promise#then
  1218. Promise.prototype.then.call(this, resolve, reject);
  1219. }
  1220. Promise.allSettled([getAsyncResolvePromise('Test #' + index + ' - ', 'p1')]).then(
  1221. v => {
  1222. console.log(`Test #${index} - Success: ${JSON.stringify(v)}`);
  1223. // Call the stashed resolve function a second time.
  1224. // It is a wrapper (defined in getAsyncResolvePromise) and will log something
  1225. // but it does not trigger allSettled to fire.
  1226. resolveFunc('p2');
  1227. rejectFunc('e2');
  1228. },
  1229. e => console.log(`Test #${index} - Error: ${e}`)
  1230. );
  1231. } finally {
  1232. // Reset Promise#then in case of failure
  1233. Promise.prototype.then = oldThen;
  1234. }
  1235. }
  1236. },
  1237. {
  1238. name: "Promise.allSettled passes all elements of iterable to Promise.resolve",
  1239. body: function (index) {
  1240. var iterable = ['p1', 'p2'];
  1241. Promise.allSettled(iterable).then(
  1242. v => echo(`Test #${index} - Success - ${JSON.stringify(v)}`),
  1243. e => echo(`Test #${index} - Failed - ${JSON.stringify(e)}`));
  1244. }
  1245. },
  1246. {
  1247. name: "Promise.allSettled called with empty iterator, calls Promise.resolve synchronously and passes abrupt completion to reject handler",
  1248. body: function (index) {
  1249. function FakePromise(fn) {
  1250. function resolve() { echo(`Test #${index} - resolve called`); throw new Error('oops'); }
  1251. function reject(e) { echo(`Test #${index} - reject called: ${e.message}`) }
  1252. fn(resolve, reject);
  1253. this.then = function(onResolve, onReject) {};
  1254. }
  1255. FakePromise.resolve = function() {};
  1256. Promise.allSettled.call(FakePromise, []);
  1257. }
  1258. },
  1259. {
  1260. name: "Promise.allSettled gets the constructor's resolve function only once",
  1261. body: function(index) {
  1262. function FakePromise(fn) {
  1263. fn(function() {}, function() {});
  1264. this.then = function(onResolve, onReject) {};
  1265. }
  1266. Object.defineProperty(FakePromise, 'resolve', {
  1267. get: function() {
  1268. echo(`Test #${index} - get constructor resolve`);
  1269. return function(x) {
  1270. echo(`Test #${index} - constructor resolve called`);
  1271. return Promise.resolve(x);
  1272. };
  1273. }
  1274. });
  1275. Promise.allSettled.call(FakePromise, [1, 2]);
  1276. }
  1277. },
  1278. {
  1279. name: "Promise.all gets the constructor's resolve function only once",
  1280. body: function(index) {
  1281. function FakePromise(fn) {
  1282. fn(function() {}, function() {});
  1283. this.then = function(onResolve, onReject) {};
  1284. }
  1285. Object.defineProperty(FakePromise, 'resolve', {
  1286. get: function() {
  1287. echo(`Test #${index} - get constructor resolve`);
  1288. return function(x) {
  1289. echo(`Test #${index} - constructor resolve called`);
  1290. return Promise.resolve(x);
  1291. };
  1292. }
  1293. });
  1294. Promise.all.call(FakePromise, [1, 2]);
  1295. }
  1296. },
  1297. {
  1298. name: "Promise.race gets the constructor's resolve function only once",
  1299. body: function(index) {
  1300. function FakePromise(fn) {
  1301. fn(function() {}, function() {});
  1302. this.then = function(onResolve, onReject) {};
  1303. }
  1304. Object.defineProperty(FakePromise, 'resolve', {
  1305. get: function() {
  1306. echo(`Test #${index} - get constructor resolve`);
  1307. return function(x) {
  1308. echo(`Test #${index} - constructor resolve called`);
  1309. return Promise.resolve(x);
  1310. };
  1311. }
  1312. });
  1313. Promise.race.call(FakePromise, [1, 2]);
  1314. }
  1315. },
  1316. {
  1317. name: "Promise.any gets the constructor's resolve function only once",
  1318. body: function(index) {
  1319. function FakePromise(fn) {
  1320. fn(function() {}, function() {});
  1321. this.then = function(onResolve, onReject) {};
  1322. }
  1323. FakePromise.reject = Promise.reject;
  1324. Object.defineProperty(FakePromise, 'resolve', {
  1325. get: function() {
  1326. echo(`Test #${index} - get constructor resolve`);
  1327. return function(x) {
  1328. echo(`Test #${index} - constructor resolve called`);
  1329. return Promise.resolve(x);
  1330. };
  1331. }
  1332. });
  1333. Promise.any.call(FakePromise, [
  1334. FakePromise.reject(1),
  1335. FakePromise.reject(2)
  1336. ]);
  1337. }
  1338. },
  1339. {
  1340. name: "Promise.any with an object containing a non-function iterator property",
  1341. body: function (index) {
  1342. var objectWithNonObjectIterator = {
  1343. [Symbol.iterator]: 123
  1344. };
  1345. var p = Promise.any(objectWithNonObjectIterator);
  1346. p.catch(
  1347. function(err) {
  1348. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  1349. echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
  1350. }
  1351. );
  1352. }
  1353. },
  1354. {
  1355. name: "Promise.any with this argument missing the resolve function",
  1356. body: function (index) {
  1357. var _resolve = Promise.resolve;
  1358. Promise.resolve = undefined;
  1359. var p = Promise.any([Promise.reject(42)]);
  1360. p.catch(
  1361. function(err) {
  1362. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  1363. echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
  1364. }
  1365. );
  1366. Promise.resolve = _resolve;
  1367. }
  1368. },
  1369. {
  1370. name: "Promise.any with this argument resolve function returning a non-object",
  1371. body: function (index) {
  1372. var _resolve = Promise.resolve;
  1373. Promise.resolve = function() { return undefined; };
  1374. var p = Promise.any([Promise.reject(42)]);
  1375. p.catch(
  1376. function(err) {
  1377. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  1378. echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
  1379. }
  1380. );
  1381. Promise.resolve = _resolve;
  1382. }
  1383. },
  1384. {
  1385. name: "Promise.any with this argument resolve function returning an object with no then function",
  1386. body: function (index) {
  1387. var _resolve = Promise.resolve;
  1388. Promise.resolve = function() { return {}; };
  1389. var p = Promise.any([Promise.reject(42)]);
  1390. p.catch(
  1391. function(err) {
  1392. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  1393. echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
  1394. }
  1395. );
  1396. Promise.resolve = _resolve;
  1397. }
  1398. },
  1399. {
  1400. name: "Promise.any with an object containing an iterator that throws",
  1401. body: function (index) {
  1402. var objectWithIterator = {
  1403. [Symbol.iterator]: function() {
  1404. return {
  1405. next: function () {
  1406. throw new TypeError('failure inside iterator');
  1407. }
  1408. };
  1409. }
  1410. };
  1411. var p = Promise.any(objectWithIterator);
  1412. p.catch(
  1413. function(err) {
  1414. echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
  1415. echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
  1416. }
  1417. );
  1418. }
  1419. },
  1420. {
  1421. name: "Promise.any still returns a rejected promise if anything throws while iterating, even if resolved promises are encountered",
  1422. body: function (index) {
  1423. var objectWithIterator = {
  1424. [Symbol.iterator]: function() {
  1425. return {
  1426. i: 0,
  1427. next: function () {
  1428. if (this.i > 2)
  1429. {
  1430. throw new TypeError('failure inside iterator');
  1431. }
  1432. this.i++;
  1433. return {
  1434. done: this.i == 5,
  1435. value: Promise.resolve('resolved promise completion #' + this.i)
  1436. };
  1437. }
  1438. };
  1439. }
  1440. };
  1441. var p = Promise.any(objectWithIterator);
  1442. p.then(
  1443. function(result) {
  1444. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1445. },
  1446. function(err) {
  1447. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1448. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1449. }
  1450. );
  1451. }
  1452. },
  1453. {
  1454. name: "Promise.any fulfills with the same value as the first encountered resolved promise",
  1455. body: function (index) {
  1456. var promises = [
  1457. new Promise(function() {}),
  1458. Promise.resolve('first promise'),
  1459. Promise.resolve('second promise'),
  1460. Promise.reject('third promise')
  1461. ];
  1462. var p = Promise.any(promises);
  1463. p.then(
  1464. function(result) {
  1465. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1466. },
  1467. function(err) {
  1468. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1469. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1470. }
  1471. );
  1472. }
  1473. },
  1474. {
  1475. name: "Promise.any fulfills with the same value as the first encountered resolved promise (promises complete async)",
  1476. body: function (index) {
  1477. var promises = [
  1478. new Promise(function() {}),
  1479. getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
  1480. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  1481. getAsyncRejectPromise('Test #' + index + ' - ', 'p3')
  1482. ];
  1483. var p = Promise.any(promises);
  1484. p.then(
  1485. function(result) {
  1486. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1487. },
  1488. function(err) {
  1489. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1490. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1491. }
  1492. );
  1493. }
  1494. },
  1495. {
  1496. name: "Promise.any fulfills with the same value as the first encountered rejected promise (promises complete async)",
  1497. body: function (index) {
  1498. var promises = [
  1499. new Promise(function() {}),
  1500. getAsyncRejectPromise('Test #' + index + ' - ', 'p1'),
  1501. getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
  1502. getAsyncResolvePromise('Test #' + index + ' - ', 'p3')
  1503. ];
  1504. var p = Promise.any(promises);
  1505. p.then(
  1506. function(result) {
  1507. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1508. },
  1509. function(err) {
  1510. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1511. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1512. }
  1513. );
  1514. }
  1515. },
  1516. {
  1517. name: "Promise.any should wait until one resolve",
  1518. body: function (index) {
  1519. const list = [
  1520. Promise.reject(1),
  1521. getAsyncRejectPromise('Test #' + index + ' - ', 2),
  1522. getAsyncResolvePromise('Test #' + index + ' - ', 3),
  1523. getAsyncRejectPromise('Test #' + index + ' - ', 4),
  1524. Promise.reject(5),
  1525. ]
  1526. Promise.any(list).then(
  1527. function(result) {
  1528. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1529. },
  1530. function(err){
  1531. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1532. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + JSON.stringify(err.message));
  1533. echo('Test #' + index + ' - Error handler #1 called with err.name = ' + err.name);
  1534. echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
  1535. }
  1536. );
  1537. }
  1538. },
  1539. {
  1540. name: "Promise.any should wait until all reject",
  1541. body: function (index) {
  1542. const list = [
  1543. Promise.reject(1),
  1544. getAsyncRejectPromise('Test #' + index + ' - ', 2),
  1545. getAsyncRejectPromise('Test #' + index + ' - ', 3),
  1546. getAsyncRejectPromise('Test #' + index + ' - ', 4),
  1547. Promise.reject(5),
  1548. ]
  1549. Promise.any(list).then(
  1550. function(result) {
  1551. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1552. },
  1553. function(err){
  1554. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1555. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + JSON.stringify(err.message));
  1556. echo('Test #' + index + ' - Error handler #1 called with err.name = ' + err.name);
  1557. echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
  1558. }
  1559. );
  1560. }
  1561. },
  1562. {
  1563. name: "Promise.any should not call return",
  1564. body: function (index) {
  1565. function it() {
  1566. return {
  1567. [Symbol.iterator]() {
  1568. echo(`Test #${index} - get iterator called`);
  1569. return this;
  1570. },
  1571. i: 2,
  1572. next() {
  1573. if (this.i > 0) {
  1574. let i = this.i--;
  1575. echo(`Test #${index} - iterator next called: ${i}`);
  1576. return { value: i, done: false }
  1577. } else {
  1578. echo(`Test #${index} - iterator next throw`);
  1579. throw new Error("BANG");
  1580. }
  1581. },
  1582. return() {
  1583. echo(`Test #${index} - iterator return called`);
  1584. }
  1585. }
  1586. }
  1587. Promise.any(it()).then(
  1588. function (result) {
  1589. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1590. },
  1591. function (err) {
  1592. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1593. }
  1594. );
  1595. }
  1596. },
  1597. {
  1598. name: "Promise.any should call return once",
  1599. body: function (index) {
  1600. function it() {
  1601. return {
  1602. [Symbol.iterator]() {
  1603. echo(`Test #${index} - get iterator called`);
  1604. return this;
  1605. },
  1606. i: 2,
  1607. next() {
  1608. if (this.i > 0) {
  1609. let i = this.i--;
  1610. echo(`Test #${index} - iterator next called: ${i}`);
  1611. return { value: i, done: false }
  1612. } else {
  1613. echo(`Test #${index} - iterator next throw`);
  1614. throw new Error("BANG");
  1615. }
  1616. },
  1617. return() {
  1618. echo(`Test #${index} - iterator return called`);
  1619. }
  1620. }
  1621. }
  1622. Promise.resolve = function () { throw new Error(); }
  1623. Promise.any(it()).then(
  1624. function (result) {
  1625. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1626. },
  1627. function (err) {
  1628. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1629. }
  1630. );
  1631. }
  1632. },
  1633. {
  1634. name: "Promise.any should throw TypeError if resolve not a function",
  1635. body: function (index) {
  1636. class foo extends Promise {
  1637. static get resolve() {
  1638. echo('Test #' + index + ' - resolve getter called');
  1639. return 5;
  1640. }
  1641. }
  1642. Promise.any.call(foo, [2, 3]).then(
  1643. function(result) {
  1644. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1645. },
  1646. function(err) {
  1647. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1648. }
  1649. );
  1650. }
  1651. },
  1652. {
  1653. name: "Promise.any passes each element in it's argument to Promise.resolve",
  1654. body: function (index) {
  1655. var promises = [
  1656. 'first promise value',
  1657. 42,
  1658. new TypeError('some error')
  1659. ];
  1660. var p = Promise.any(promises);
  1661. p.then(
  1662. function(result) {
  1663. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1664. },
  1665. function(err) {
  1666. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1667. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1668. }
  1669. );
  1670. }
  1671. },
  1672. {
  1673. name: "Promise.any should failure with empty list",
  1674. body: function (index) {
  1675. Promise.any([]).then(
  1676. function(result) {
  1677. echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
  1678. },
  1679. function(err){
  1680. echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
  1681. echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
  1682. echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
  1683. }
  1684. )
  1685. }
  1686. },
  1687. {
  1688. name: "Promise.any should reject with aggregate error and errors",
  1689. body: function (index) {
  1690. function applyTest(list, idx) {
  1691. Promise.any(list).then(
  1692. function(result) {
  1693. echo('Test #' + index + ' - Success handler #' + idx + ' called with result = ' + result);
  1694. },
  1695. function(err){
  1696. echo('Test #' + index + ' - Error handler #' + idx + ' called with err = ' + err);
  1697. echo('Test #' + index + ' - Error handler #' + idx + ' called with err.message = ' + JSON.stringify(err.message));
  1698. echo('Test #' + index + ' - Error handler #' + idx + ' called with err.name = ' + err.name);
  1699. echo('Test #' + index + ' - Error handler #' + idx + ' called with err.errors = ' + JSON.stringify(err.errors));
  1700. }
  1701. );
  1702. }
  1703. applyTest([], 1)
  1704. applyTest([Promise.reject(1)], 2)
  1705. applyTest([Promise.reject(1), Promise.reject(2), Promise.reject(3)], 3)
  1706. }
  1707. }
  1708. ];
  1709. var index = 1;
  1710. function runTest(test) {
  1711. echo('Executing test #' + index + ' - ' + test.name);
  1712. try {
  1713. test.body(index);
  1714. } catch(e) {
  1715. echo('Caught exception: ' + e);
  1716. }
  1717. index++;
  1718. }
  1719. tests.forEach(runTest);
  1720. echo('\nCompletion Results:');