asyncawait-functionality.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // ES6 Async Await tests -- verifies functionality of async/await
  6. function echo(str) {
  7. WScript.Echo(str);
  8. }
  9. var tests = [
  10. {
  11. name: "Async keyword with a lambda expressions",
  12. body: function (index) {
  13. var x = 12;
  14. var y = 14;
  15. var lambdaParenNoArg = async() => x < y;
  16. var lambdaArgs = async(a, b, c) => a + b + c;
  17. lambdaParenNoArg().then(result => {
  18. echo(`Test #${index} - Success lambda expression with no argument called with result = '${result}'`);
  19. }, err => {
  20. echo(`Test #${index} - Error lambda expression with no argument called with err = ${err}`);
  21. });
  22. lambdaArgs(10, 20, 30).then(result => {
  23. echo(`Test #${index} - Success lambda expression with several arguments called with result = '${result}'`);
  24. }, err => {
  25. echo(`Test #${index} - Error lambda expression with several arguments called with err = ${err}`);
  26. });
  27. }
  28. },
  29. {
  30. name: "Async keyword with a lambda expressions and local variable captured and shadowed",
  31. body: function (index) {
  32. var x = 12;
  33. var lambdaSingleArgNoParen = async x => x;
  34. var lambdaSingleArg = async(x) => x;
  35. lambdaSingleArgNoParen(x).then(result => {
  36. echo(`Test #${index} - Success lambda expression with single argument and no paren called with result = '${result}'`);
  37. }, err => {
  38. echo(`Test #${index} - Error lambda expression with single argument and no paren called with err = ${err}`);
  39. });
  40. lambdaSingleArg(x).then(result => {
  41. echo(`Test #${index} - Success lambda expression with a single argument a called with result = '${result}'`);
  42. }, err => {
  43. echo(`Test #${index} - Error lambda expression with a single argument called with err = ${err}`);
  44. });
  45. }
  46. },
  47. {
  48. name: "Async function in a statement",
  49. body: function (index) {
  50. {
  51. var namedNonAsyncMethod = function async(x, y) { return x + y; }
  52. var unnamedAsyncMethod = async function (x, y) { return x + y; }
  53. async function async(x, y) { return x - y; }
  54. var result = namedNonAsyncMethod(10, 20);
  55. echo(`Test #${index} - Success function #1 called with result = '${result}'`);
  56. unnamedAsyncMethod(10, 20).then(result => {
  57. echo(`Test #${index} - Success function #2 called with result = '${result}'`);
  58. }, err => {
  59. echo(`Test #${index} - Error function #2 called with err = ${err}`);
  60. });
  61. async(10, 20).then(result => {
  62. echo(`Test #${index} - Success function #3 called with result = '${result}'`);
  63. }, err => {
  64. echo(`Test #${index} - Error function #3 called with err = ${err}`);
  65. });
  66. }
  67. {
  68. async function async() { return 12; }
  69. async().then(result => {
  70. echo(`Test #${index} - Success function #4 called with result = '${result}'`);
  71. }, err => {
  72. echo(`Test #${index} - Error function #4 called with err = ${err}`);
  73. });
  74. }
  75. {
  76. function async() { return 12; }
  77. var result = namedNonAsyncMethod(10, 20);
  78. echo(`Test #${index} - Success function #5 called with result = '${result}'`);
  79. }
  80. }
  81. },
  82. {
  83. name: "Async function in an object",
  84. body: function (index) {
  85. var object = {
  86. async async() { return 12; }
  87. };
  88. var object2 = {
  89. async() { return 12; }
  90. };
  91. var object3 = {
  92. async "a"() { return 12; },
  93. async 0() { return 12; },
  94. async 3.14() { return 12; },
  95. async else() { return 12; },
  96. };
  97. object.async().then(result => {
  98. echo(`Test #${index} - Success function in a object #1 called with result = '${result}'`);
  99. }, err => {
  100. echo(`Test #${index} - Error function in a object #1 called with err = ${err}`);
  101. });
  102. var result = object2.async();
  103. echo(`Test #${index} - Success function in a object #2 called with result = '${result}'`);
  104. object3.a().then(result => {
  105. echo(`Test #${index} - Success function in a object #3 called with result = '${result}'`);
  106. }, err => {
  107. echo(`Test #${index} - Error function in a object #3 called with err = ${err}`);
  108. });
  109. object3['0']().then(result => {
  110. echo(`Test #${index} - Success function in a object #4 called with result = '${result}'`);
  111. }, err => {
  112. echo(`Test #${index} - Error function in a object #4 called with err = ${err}`);
  113. });
  114. object3['3.14']().then(result => {
  115. echo(`Test #${index} - Success function in a object #5 called with result = '${result}'`);
  116. }, err => {
  117. echo(`Test #${index} - Error function in a object #5 called with err = ${err}`);
  118. });
  119. object3.else().then(result => {
  120. echo(`Test #${index} - Success function in a object #6 called with result = '${result}'`);
  121. }, err => {
  122. echo(`Test #${index} - Error function in a object #6 called with err = ${err}`);
  123. });
  124. }
  125. },
  126. {
  127. name: "Async classes",
  128. body: function (index) {
  129. class MyClass {
  130. async asyncMethod(a) { return a; }
  131. async async(a) { return a; }
  132. async "a"() { return 12; }
  133. async 0() { return 12; }
  134. async 3.14() { return 12; }
  135. async else() { return 12; }
  136. static async staticAsyncMethod(a) { return a; }
  137. }
  138. class MySecondClass {
  139. async(a) { return a; }
  140. }
  141. class MyThirdClass {
  142. static async(a) { return a; }
  143. }
  144. var x = "foo";
  145. class MyFourthClass {
  146. async [x](a) { return a; }
  147. }
  148. var myClassInstance = new MyClass();
  149. var mySecondClassInstance = new MySecondClass();
  150. var myFourthClassInstance = new MyFourthClass();
  151. myClassInstance.asyncMethod(10).then(result => {
  152. echo(`Test #${index} - Success async in a class #1 called with result = '${result}'`);
  153. }, err => {
  154. echo(`Test #${index} - Error async in a class #1 called with err = ${err}`);
  155. });
  156. myClassInstance.async(10).then(result => {
  157. echo(`Test #${index} - Success async in a class #2 called with result = '${result}'`);
  158. }, err => {
  159. echo(`Test #${index} - Error async in a class #2 called with err = ${err}`);
  160. });
  161. myClassInstance.a().then(result => {
  162. echo(`Test #${index} - Success async in a class #3 called with result = '${result}'`);
  163. }, err => {
  164. echo(`Test #${index} - Error async in a class #3 called with err = ${err}`);
  165. });
  166. myClassInstance['0']().then(result => {
  167. echo(`Test #${index} - Success async in a class #4 called with result = '${result}'`);
  168. }, err => {
  169. echo(`Test #${index} - Error async in a class #4 called with err = ${err}`);
  170. });
  171. myClassInstance['3.14']().then(result => {
  172. echo(`Test #${index} - Success async in a class #5 called with result = '${result}'`);
  173. }, err => {
  174. echo(`Test #${index} - Error async in a class #5 called with err = ${err}`);
  175. });
  176. myClassInstance.else().then(result => {
  177. echo(`Test #${index} - Success async in a class #6 called with result = '${result}'`);
  178. }, err => {
  179. echo(`Test #${index} - Error async in a class #6 called with err = ${err}`);
  180. });
  181. MyClass.staticAsyncMethod(10).then(result => {
  182. echo(`Test #${index} - Success async in a class #7 called with result = '${result}'`);
  183. }, err => {
  184. echo(`Test #${index} - Error async in a class #7 called with err = ${err}`);
  185. });
  186. var result = mySecondClassInstance.async(10);
  187. echo(`Test #${index} - Success async in a class #8 called with result = '${result}'`);
  188. var result = MyThirdClass.async(10);
  189. echo(`Test #${index} - Success async in a class #9 called with result = '${result}'`);
  190. myFourthClassInstance.foo(10).then(result => {
  191. echo(`Test #${index} - Success async in a class #10 called with result = '${result}'`);
  192. }, err => {
  193. echo(`Test #${index} - Error async in a class #10 called with err = ${err}`);
  194. });
  195. }
  196. },
  197. {
  198. name: "Await in an async function",
  199. body: function (index) {
  200. async function asyncMethod(val, factor) {
  201. val = val * factor;
  202. if (val > 0)
  203. val = await asyncMethod(val, -1);
  204. return val;
  205. }
  206. function await(x) {
  207. return x;
  208. }
  209. async function secondAsyncMethod(x) {
  210. return await(x);
  211. }
  212. function rejectedPromiseMethod() {
  213. return new Promise(function (resolve, reject) {
  214. reject(Error('My Error'));
  215. });
  216. }
  217. async function rejectAwaitMethod() {
  218. return await rejectedPromiseMethod();
  219. }
  220. async function asyncThrowingMethod() {
  221. throw 32;
  222. }
  223. async function throwAwaitMethod() {
  224. return await asyncThrowingMethod();
  225. }
  226. asyncMethod(2, 2).then(result => {
  227. echo(`Test #${index} - Success await in an async function #1 called with result = '${result}'`);
  228. }, err => {
  229. echo(`Test #${index} - Error await in an async function #1 called with err = ${err}`);
  230. });
  231. secondAsyncMethod(2).then(result => {
  232. echo(`Test #${index} - Success await in an async function #2 called with result = '${result}'`);
  233. }, err => {
  234. echo(`Test #${index} - Error await in an async function #2 called with err = ${err}`);
  235. });
  236. rejectAwaitMethod(2).then(result => {
  237. echo(`Test #${index} - Failed await in an async function doesn't catch a rejected Promise. Result = '${result}'`);
  238. }, err => {
  239. echo(`Test #${index} - Success await in an async function catch a rejected Promise in 'err'. Error = '${err}'`);
  240. });
  241. throwAwaitMethod(2).then(result => {
  242. echo(`Test #${index} - Failed await in an async function doesn't catch an error. Result = '${result}'`);
  243. }, err => {
  244. echo(`Test #${index} - Success await in an async function catch an error in 'err'. Error = '${err}'`);
  245. });
  246. }
  247. },
  248. {
  249. name: "Await keyword with a lambda expressions",
  250. body: function (index) {
  251. {
  252. async function asyncMethod(x, y, z) {
  253. var lambdaExp = async(a, b, c) => a * b * c;
  254. var lambdaResult = await lambdaExp(x, y, z);
  255. return lambdaResult;
  256. }
  257. asyncMethod(5, 5, 5).then(result => {
  258. echo(`Test #${index} - Success await keyword with a lambda expressions #1 called with result = '${result}'`);
  259. }, err => {
  260. echo(`Test #${index} - Error await keyword with a lambda expressions #1 called with err = ${err}`);
  261. });
  262. };
  263. {
  264. async function await(lambda, x, y, z) {
  265. return await lambda(x, y, z);
  266. }
  267. await(async(a, b, c) => a + b + c, 10, 20, 30).then(result => {
  268. echo(`Test #${index} - Success await keyword with a lambda expressions #1 called with result = '${result}'`);
  269. }, err => {
  270. echo(`Test #${index} - Error await keyword with a lambda expressions #1 called with err = ${err}`);
  271. });
  272. };
  273. }
  274. },
  275. {
  276. name: "Async function with default arguments's value",
  277. body: function (index) {
  278. {
  279. function thrower() {
  280. throw "expected error"
  281. }
  282. async function asyncMethod(argument = thrower()) {
  283. return true;
  284. }
  285. async function secondAsyncMethod(argument = false) {
  286. return true;
  287. }
  288. asyncMethod(true).then(result => {
  289. echo(`Test #${index} - Success async function with default arguments's value overwritten #1 called with result = '${result}'`);
  290. }, err => {
  291. echo(`Test #${index} - Error async function with default arguments's value overwritten #1 called with err = ${err}`);
  292. });
  293. // TODO:[aneeshd] Need to fix the default parameter evaluation order for both async functions and generators
  294. asyncMethod().then(result => {
  295. echo(`Test #${index} - Failed async function with default arguments's value has not been rejected as expected #2 called with result = '${result}'`);
  296. }, err => {
  297. echo(`Test #${index} - Success async function with default arguments's value has been rejected as expected by 'err' #2 called with err = '${err}'`);
  298. });
  299. secondAsyncMethod().then(result => {
  300. echo(`Test #${index} - Success async function with default arguments's value #3 called with result = '${result}'`);
  301. }, err => {
  302. echo(`Test #${index} - Error async function with default arguments's value #3 called with err = ${err}`);
  303. });
  304. };
  305. }
  306. },
  307. {
  308. name: "Promise in an Async function",
  309. body: function (index) {
  310. {
  311. async function asyncMethodResolved() {
  312. let p = new Promise(function (resolve, reject) {
  313. resolve("resolved");
  314. });
  315. return p.then(function (result) {
  316. return result;
  317. });
  318. }
  319. async function asyncMethodResolvedWithAwait() {
  320. let p = new Promise(function (resolve, reject) {
  321. resolve("resolved");
  322. });
  323. return await p;
  324. }
  325. async function asyncMethodRejected() {
  326. let p = new Promise(function (resolve, reject) {
  327. reject("rejected");
  328. });
  329. return p.then(function (result) {
  330. return result;
  331. });
  332. }
  333. asyncMethodResolved().then(result => {
  334. echo(`Test #${index} - Success resolved promise in an async function #1 called with result = '${result}'`);
  335. }, err => {
  336. echo(`Test #${index} - Error resolved promise in an async function #1 called with err = ${err}`);
  337. });
  338. asyncMethodResolvedWithAwait().then(result => {
  339. echo(`Test #${index} - Success resolved promise in an async function #2 called with result = '${result}'`);
  340. }, err => {
  341. echo(`Test #${index} - Error resolved promise in an async function #2 called with err = ${err}`);
  342. });
  343. asyncMethodRejected().then(result => {
  344. echo(`Test #${index} - Failed promise in an async function has not been rejected as expected #3 called with result = '${result}'`);
  345. }, err => {
  346. echo(`Test #${index} - Success promise in an async function has been rejected as expected by 'err' #3 called with err = '${err}'`);
  347. });
  348. };
  349. }
  350. },
  351. {
  352. name: "%AsyncFunction% constructor creates async functions analogous to Function constructor",
  353. body: function (index) {
  354. var AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
  355. var af = new AsyncFunction('return await Promise.resolve(0);');
  356. af().then(result => {
  357. echo(`Test #${index} - Success %AsyncFunction% created async function #1 called with result = '${result}'`);
  358. }, err => {
  359. echo(`Test #${index} - Error %AsyncFunction% created async function #1 called with err = ${err}`);
  360. });
  361. af = new AsyncFunction('a', 'b', 'c', 'a = await a; b = await b; c = await c; return a + b + c;');
  362. af(Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)).then(result => {
  363. echo(`Test #${index} - Success %AsyncFunction% created async function #2 called with result = '${result}'`);
  364. }, err => {
  365. echo(`Test #${index} - Error %AsyncFunction% created async function #2 called with err = ${err}`);
  366. });
  367. }
  368. },
  369. {
  370. name: "local variables with same names as formal parameters have proper redeclaration semantics (non-error cases, var and function)",
  371. body: function (index) {
  372. async function af1(x) { var y = x; var x = 'b'; return y + x; }
  373. af1('a').then(result => {
  374. if (result === 'ab') {
  375. echo(`Test #${index} - Success inner var x overwrote formal parameter x only after the declaration statement`);
  376. } else {
  377. echo(`Test #${index} - Failure x appears to have an unexpected value x = '${result}'`);
  378. }
  379. }, err => {
  380. echo(`Test #${index} - Error var redeclaration with err = ${err}`);
  381. });
  382. async function af2(x) { var xx = x(); function x() { return 'afx'; } return xx; }
  383. af2(function () { return ''; }).then(result => {
  384. if (result === 'afx') {
  385. echo(`Test #${index} - Success inner function x() overwrote formal parameter x`);
  386. } else {
  387. echo(`Test #${index} - Failure x appears not assigned with inner function x(), x = '${result}'`);
  388. }
  389. }, err => {
  390. echo(`Test #${index} - Error err = ${err}`);
  391. });
  392. }
  393. },
  394. {
  395. name: "this value in async functions behaves like it does in normal functions",
  396. body: function (index) {
  397. async function af() {
  398. return this;
  399. }
  400. af.call(5).then(result => {
  401. if (result == 5) {
  402. echo(`Test #${index} - Success this value set to 5`);
  403. } else {
  404. echo(`Test #${index} - Failure this value is not 5, this = '${result}'`);
  405. }
  406. }, err => {
  407. echo(`Test #${index} - Error err = ${err}`);
  408. });
  409. var o = {
  410. af: af,
  411. b: "abc"
  412. };
  413. o.af().then(result => {
  414. if (result.af === af && result.b === "abc") {
  415. echo(`Test #${index} - Success this value set to { af: af, b: "abc" }`);
  416. } else {
  417. echo(`Test #${index} - Failure this value set to something else, this = '${result}'`);
  418. }
  419. }, err => {
  420. echo(`Test #${index} - Error err = ${err}`);
  421. });
  422. }
  423. },
  424. {
  425. name: "arguments value in async functions behaves like it does in normal functions",
  426. body: function (index) {
  427. async function af() {
  428. return arguments[0] + arguments[1];
  429. }
  430. af('a', 'b').then(result => {
  431. if (result === 'ab') {
  432. echo(`Test #${index} - Success result is 'ab' from arguments 'a' + 'b'`);
  433. } else {
  434. echo(`Test #${index} - Failure result is not 'ab', result = '${result}'`);
  435. }
  436. }, err => {
  437. echo(`Test #${index} - Error err = ${err}`);
  438. });
  439. }
  440. },
  441. {
  442. name: "super value in async methods behaves like it does in normal methods",
  443. body: function (index) {
  444. class B {
  445. af() {
  446. return "base";
  447. }
  448. }
  449. class C extends B {
  450. async af() {
  451. return super.af() + " derived";
  452. }
  453. }
  454. var c = new C();
  455. c.af().then(result => {
  456. if (result === 'base derived') {
  457. echo(`Test #${index} - Success result is 'base derived' from derived method call`);
  458. } else {
  459. echo(`Test #${index} - Failure result is not 'base derived', result = '${result}'`);
  460. }
  461. }, err => {
  462. echo(`Test #${index} - Error err = ${err}`);
  463. });
  464. }
  465. },
  466. {
  467. name:"Async function with formal captured in a lambda",
  468. body: function (index) {
  469. async function af(d = 1) {
  470. return () => d;
  471. }
  472. af().then(result => {
  473. if (result() === 1) {
  474. print(`Test #${index} - Success lambda returns 1 when no arguments passed`);
  475. } else {
  476. print(`Test #${index} - Failure result is not 1, result = '${result()}'`);
  477. }
  478. }, err => {
  479. print(`Test #${index} - Error err = ${err}`);
  480. });
  481. }
  482. },
  483. {
  484. name:"Async function with formal captured in a nested function",
  485. body: function (index) {
  486. async function af(d = 1) {
  487. return function () { return d; };
  488. }
  489. af().then(result => {
  490. if (result() === 1) {
  491. print(`Test #${index} - Success nested function returns 1 when no arguments passed`);
  492. } else {
  493. print(`Test #${index} - Failure result is not 1, result = '${result()}'`);
  494. }
  495. }, err => {
  496. print(`Test #${index} - Error err = ${err}`);
  497. });
  498. }
  499. },
  500. {
  501. name:"Async function with formal captured in eval",
  502. body: function (index) {
  503. async function af(d = 1) {
  504. return eval("d");
  505. }
  506. af().then(result => {
  507. if (result === 1) {
  508. print(`Test #${index} - Success eval returns 1 when no arguments passed`);
  509. } else {
  510. print(`Test #${index} - Failure result is not 1, result = '${result}'`);
  511. }
  512. }, err => {
  513. print(`Test #${index} - Error err = ${err}`);
  514. });
  515. }
  516. },
  517. {
  518. name: "Async function with formal capturing in param scope",
  519. body: function (index) {
  520. async function af1(a, b = () => a, c = b) {
  521. function b() {
  522. return a;
  523. }
  524. var a = 2;
  525. return [b, c];
  526. }
  527. af1(1).then(result => {
  528. if (result[0]() === 2) {
  529. echo(`Test #${index} - Success inner function declaration captures the body variable`);
  530. } else {
  531. echo(`Test #${index} - Failure a appears to have an unexpected value a = '${result}'`);
  532. }
  533. if (result[1]() === 1) {
  534. echo(`Test #${index} - Success function defined in the param scope captures the param scope variable`);
  535. } else {
  536. echo(`Test #${index} - Failure a appears to have an unexpected value in the param scope function a = '${result}'`);
  537. }
  538. }, err => {
  539. echo(`Test #${index} - Error in split scope with err = ${err}`);
  540. });
  541. }
  542. },
  543. {
  544. name: "Async function with formal capturing in param scope with eval in the body",
  545. body: function (index) {
  546. async function af1(a, b = () => a, c = b) {
  547. function b() {
  548. return a;
  549. }
  550. var a = 2;
  551. return eval("[b, c]");
  552. }
  553. af1(1).then(result => {
  554. if (result[0]() === 2) {
  555. echo(`Test #${index} - Success inner function declaration captures the body variable with eval in the body`);
  556. } else {
  557. echo(`Test #${index} - Failure a appears to have an unexpected value a = '${result}'`);
  558. }
  559. if (result[1]() === 1) {
  560. echo(`Test #${index} - Success function defined in the param scope captures the param scope variable with eval in the body`);
  561. } else {
  562. echo(`Test #${index} - Failure a appears to have an unexpected value in the param scope function a = '${result}'`);
  563. }
  564. }, err => {
  565. echo(`Test #${index} - Error in split scope with eval in the body with err = ${err}`);
  566. });
  567. }
  568. },
  569. {
  570. name: "Async function with duplicate variable declaration in the body with eval",
  571. body: function (index) {
  572. async function af1(a, b) {
  573. var a = 10;
  574. return eval("a + b");
  575. }
  576. af1(1, 2).then(result => {
  577. if (result === 12) {
  578. echo(`Test #${index} - Success inner variable declaration shadows the formal`);
  579. } else {
  580. echo(`Test #${index} - Failure sum appears to have an unexpected value sum = '${result}'`);
  581. }
  582. }, err => {
  583. echo(`Test #${index} - Error in variable redeclaration with eval with err = ${err}`);
  584. });
  585. }
  586. },
  587. {
  588. name: "Async function with duplicate variable declaration in the body with child having eval",
  589. body: function (index) {
  590. async function af1(a, b) {
  591. var a = 10;
  592. return function () { return eval("a + b"); };
  593. }
  594. af1(1, 2).then(result => {
  595. if (result() === 12) {
  596. echo(`Test #${index} - Success inner variable declaration shadows the formal with eval in child function`);
  597. } else {
  598. echo(`Test #${index} - Failure sum appears to have an unexpected value sum = '${result}'`);
  599. }
  600. }, err => {
  601. echo(`Test #${index} - Error in variable redeclaration with eval with err = ${err}`);
  602. });
  603. }
  604. },
  605. {
  606. name: "Async function with more than one await",
  607. body: function (index) {
  608. async function af1() {
  609. return 1;
  610. }
  611. async function af2() {
  612. return 2;
  613. }
  614. async function af3() {
  615. return await af1() + await af2();
  616. }
  617. af3().then(result => {
  618. if (result === 3) {
  619. echo(`Test #${index} - Success functions completes both await calls`);
  620. } else {
  621. echo(`Test #${index} - Failed function failed to complete both await calls and returned ${result}`);
  622. }
  623. }, err => {
  624. echo(`Test #${index} - Error in multiple awaits in a function err = ${err}`);
  625. });
  626. }
  627. },
  628. {
  629. name: "Async function with more than one await with branching",
  630. body: function (index) {
  631. async function af1() {
  632. return 1;
  633. }
  634. async function af2() {
  635. return 2;
  636. }
  637. async function af3(a) {
  638. return a ? await af1() : await af2();
  639. }
  640. af3(1).then(result => {
  641. if (result === 1) {
  642. echo(`Test #${index} - Success functions completes the first await call`);
  643. } else {
  644. echo(`Test #${index} - Failed function failed to complete the first await call and returned ${result}`);
  645. }
  646. }, err => {
  647. echo(`Test #${index} - Error in multiple awaits with branching in a function err = ${err}`);
  648. });
  649. af3().then(result => {
  650. if (result === 2) {
  651. echo(`Test #${index} - Success functions completes the second await call`);
  652. } else {
  653. echo(`Test #${index} - Failed function failed to complete the second await call and returned ${result}`);
  654. }
  655. }, err => {
  656. echo(`Test #${index} - Error in multiple awaits with branching in a function err = ${err}`);
  657. });
  658. }
  659. },
  660. {
  661. name: "Async function with an exception in an await expression",
  662. body: function (index) {
  663. var obj = { x : 1 };
  664. async function af1() {
  665. throw obj;
  666. }
  667. async function af2() {
  668. echo(`Failed : This function was not expected to be executed`);
  669. }
  670. async function af3() {
  671. return await af1() + await af2();
  672. }
  673. af3().then(result => {
  674. echo(`Test #${index} - Error an expected exception does not seem to be thrown`);
  675. }, err => {
  676. if (err === obj) {
  677. echo(`Test #${index} - Success caught the expected exception`);
  678. } else {
  679. echo(`Test #${index} - Error an unexpected exception was thrown = ${err}`);
  680. }
  681. });
  682. }
  683. },
  684. {
  685. name: "Async functions throws on an await",
  686. body: function (index) {
  687. var obj = { x : 1 };
  688. async function af1() {
  689. throw obj;
  690. }
  691. async function af2() {
  692. echo(`Test #${index} Failed This function was not expected to be executed`);
  693. }
  694. async function af3() {
  695. return await af1() + await af2();
  696. }
  697. af3().then(result => {
  698. print(`Test #${index} Failed an expected exception does not seem to be thrown`);
  699. }, err => {
  700. if (err === obj) {
  701. print(`Test #${index} - Success caught the expected exception`);
  702. } else {
  703. print(`Test #${index} - Failed an unexpected exception was thrown = ${err}`);
  704. }
  705. });
  706. }
  707. },
  708. {
  709. name: "Awaiting a function with multiple awaits",
  710. body: function (index) {
  711. async function af1(a, b) {
  712. return await af2();
  713. async function af2() {
  714. a = await a * a;
  715. b = await b * b;
  716. return a + b;
  717. }
  718. }
  719. af1(1, 2).then(result => {
  720. if (result === 5) {
  721. echo(`Test #${index} - Success Multiple awaits in the inner function completed`);
  722. } else {
  723. echo(`Test #${index} - Failed function failed to complete the multiple awaits in the inner function ${result}`);
  724. }
  725. }, err => {
  726. echo(`Test #${index} - Error in multiple awaits in an inner function err = ${err}`);
  727. });
  728. }
  729. },
  730. {
  731. name: "Async function with nested try-catch in the body",
  732. body: function (index) {
  733. async function af1() {
  734. throw 42;
  735. }
  736. async function af2() {
  737. try {
  738. try {
  739. await af1();
  740. } catch (e) {
  741. echo(`Test #${index} - Success Caught the expected exception inside the inner catch in async body`);
  742. throw e;
  743. }
  744. } catch (e) {
  745. echo(`Test #${index} - Success Caught the expected exception inside catch in async body`);
  746. throw e;
  747. }
  748. echo(`Test #${index} - Failed Didn't throw an expected exception`);
  749. }
  750. af2().then(result => {
  751. echo(`Test #${index} - Failed an the expected was not thrown`);
  752. }, err => {
  753. if (err.x === obj.x) {
  754. echo(`Test #${index} - Success Caught the expected exception in the promise`);
  755. } else {
  756. echo(`Test #${index} - Failed Caught an unexpected exception in the promise ${error}`);
  757. }
  758. });
  759. }
  760. },
  761. {
  762. name: "Async function with try-catch and try-finally in the body",
  763. body: function (index) {
  764. async function af1() {
  765. throw 42;
  766. }
  767. async function af2() {
  768. try {
  769. try {
  770. await af1();
  771. } catch (e) {
  772. echo(`Test #${index} - Success Caught the expected exception inside the inner catch in async body`);
  773. throw e;
  774. }
  775. } finally {
  776. echo(`Test #${index} - Success finally block is executed in async body`);
  777. }
  778. echo(`Test #${index} - Failed Didn't throw an expected exception`);
  779. }
  780. af2().then(result => {
  781. echo(`Test #${index} - Failed an the expected was not thrown`);
  782. }, err => {
  783. if (err.x === obj.x) {
  784. echo(`Test #${index} - Success Caught the expected exception in the promise`);
  785. } else {
  786. echo(`Test #${index} - Failed Caught an unexpected exception in the promise ${error}`);
  787. }
  788. });
  789. }
  790. },
  791. {
  792. name: "Async function and with",
  793. body: function (index) {
  794. var obj = {
  795. async af() {
  796. this.b = await this.a + 10;
  797. return this;
  798. },
  799. a : 1,
  800. b : 0
  801. };
  802. async function af(x) {
  803. var x = 0;
  804. with (obj) {
  805. x = await af();
  806. }
  807. return x;
  808. }
  809. af().then(result => {
  810. if (result.a === 1 && result.b === 11) {
  811. echo(`Test #${index} - Success functions call inside with returns the right this object`);
  812. } else {
  813. echo(`Test #${index} - Failed function failed to execute with inside an async function got ${result}`);
  814. }
  815. }, err => {
  816. echo(`Test #${index} - Error in with construct inside an async method err = ${err}`);
  817. });
  818. }
  819. },
  820. {
  821. name: "Async and arguments.callee",
  822. body: function (index) {
  823. async function asyncMethod() {
  824. return arguments.callee;
  825. }
  826. asyncMethod().then(result => {
  827. if (result === asyncMethod) {
  828. echo(`Test #${index} - Success async function and arguments.callee`);
  829. } else {
  830. echo(`Test #${index} - Failed async function and arguments.callee called with result = '${result}'`);
  831. }
  832. }, err => {
  833. echo(`Test #${index} - Error async function and arguments.callee called with err = ${err}`);
  834. });
  835. }
  836. },
  837. {
  838. name: "Async and arguments.caller",
  839. body: function (index) {
  840. var func = function () {
  841. return func.caller;
  842. }
  843. async function asyncMethod(flag, value) {
  844. if (!flag) {
  845. return await func();
  846. }
  847. return value * value;
  848. }
  849. asyncMethod().then(
  850. result => {
  851. if (result === asyncMethod) {
  852. echo(`Test #${index} - Success async function returned through caller property is the same as the original async function`);
  853. } else {
  854. echo(`Test #${index} - Failed async function returned through the caller property is not the same as the original async function = ${result}`);
  855. }
  856. result(true, 10).then(
  857. r => {
  858. if (r === 100) {
  859. echo(`Test #${index} - Success async function returned through caller property behaves the same way as the original async function`);
  860. } else {
  861. echo(`Test #${index} - Failed async function returned through caller property behaves different from the original async function with value = ${r}`);
  862. }
  863. },
  864. e => {
  865. echo(`Test #${index} - Failed while trying to execute the async function returned through caller property with err = ${e}`);
  866. }
  867. );
  868. },
  869. error => {
  870. echo(`Test #${index} - Failed while trying to retrieve the async function through caller property with err = ${error}`);
  871. }
  872. )
  873. }
  874. },
  875. {
  876. name: "Async and split scope",
  877. body: function () {
  878. async function asyncMethod1(b) {
  879. return b() + 100;
  880. }
  881. async function asynMethod2(a = 10, b = () => a) {
  882. if (a === 10) {
  883. echo(`Test #${index} - Success initial value of the formal is the same as the default param value`);
  884. } else {
  885. echo(`Test #${index} - Failed initial value of the formal is not the same as the default param value, expected 10, result = ${a}`);
  886. }
  887. a = await asyncMethod1(b);
  888. if (a === 110) {
  889. echo(`Test #${index} - Success updated value of the formal is the same as the value returned from the second async function`);
  890. } else {
  891. echo(`Test #${index} - Failed updated value of the formal is not the same as the value returned from the second async function, expected 110, result = ${a}`);
  892. }
  893. return b;
  894. }
  895. asynMethod2().then(
  896. result => {
  897. if (result() === 110) {
  898. echo(`Test #${index} - Success value returned through await is assigned to the formal`);
  899. } else {
  900. echo(`Test #${index} - Failed value returned through the await is different from the expected 110, result = ${result()}`);
  901. }
  902. },
  903. error => {
  904. echo(`Test #${index} - Failed error while trying to return through the await in a split scope function, expected 100, error = ${error}`);
  905. }
  906. );
  907. async function asyncMethod3(b) {
  908. return b() + 100;
  909. }
  910. async function asynMethod4(a = 10, b = () => a) {
  911. if (a === 10) {
  912. echo(`Test #${index} - Success initial value of the body symbol is the same as the default param value`);
  913. } else {
  914. echo(`Test #${index} - Failed initial value of the body symbol is not the same as the default param value, expected 10, result = ${a}`);
  915. }
  916. var a = await asyncMethod3(b);
  917. if (a === 110) {
  918. echo(`Test #${index} - Success updated value of the body symbol is the same as the value returned from the second async function`);
  919. } else {
  920. echo(`Test #${index} - Failed updated value of the body symbol is not the same as the value returned from the second async function, expected 110, result = ${a}`);
  921. }
  922. return b;
  923. }
  924. asynMethod4().then(
  925. result => {
  926. if (result() === 10) {
  927. echo(`Test #${index} - Success value returned through await is not assigned to the formal`);
  928. } else {
  929. echo(`Test #${index} - Failed value of the formal is different from the expected 10, result = ${result()}`);
  930. }
  931. },
  932. error => {
  933. echo(`Test #${index} - Failed error while trying to return through the await in a split scope function with duplicate symbol in the body, expected 100, error = ${error}`);
  934. }
  935. );
  936. }
  937. }
  938. ];
  939. var index = 1;
  940. function runTest(test) {
  941. echo('Executing test #' + index + ' - ' + test.name);
  942. try {
  943. test.body(index);
  944. } catch(e) {
  945. echo('Caught exception: ' + e);
  946. }
  947. index++;
  948. }
  949. tests.forEach(runTest);
  950. echo('\nCompletion Results:');