| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import "package:expect/expect.dart"; | 5 import "package:expect/expect.dart"; |
| 6 import "package:compiler/src/js/js.dart"; | 6 import "package:compiler/src/js/js.dart"; |
| 7 import "package:compiler/src/js/rewrite_async.dart"; | 7 import "package:compiler/src/js/rewrite_async.dart"; |
| 8 import "package:compiler/src/js_backend/js_backend.dart" show StringBackedName; | 8 import "package:compiler/src/js_backend/js_backend.dart" show StringBackedName; |
| 9 | 9 |
| 10 import "backend_dart/dart_printer_test.dart" show PrintDiagnosticListener; | 10 import "backend_dart/dart_printer_test.dart" show PrintDiagnosticListener; |
| 11 | 11 |
| 12 void testTransform(String source, String expected) { | 12 void testTransform(String source, String expected, AsyncRewriterBase rewriter) { |
| 13 Fun fun = js(source); | 13 Fun fun = js(source); |
| 14 Fun rewritten = new AsyncRewriter( | 14 Fun rewritten = rewriter.rewrite(fun); |
| 15 null, // The diagnostic helper should not be used in these tests. | |
| 16 null, | |
| 17 asyncHelper: new VariableUse("thenHelper"), | |
| 18 newCompleter: new VariableUse("Completer"), | |
| 19 safeVariableName: (String name) => "__$name", | |
| 20 bodyName: new StringBackedName("body")).rewrite(fun); | |
| 21 | 15 |
| 22 JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(); | 16 JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(); |
| 23 SimpleJavaScriptPrintingContext context = | 17 SimpleJavaScriptPrintingContext context = |
| 24 new SimpleJavaScriptPrintingContext(); | 18 new SimpleJavaScriptPrintingContext(); |
| 25 Printer printer = new Printer(options, context); | 19 Printer printer = new Printer(options, context); |
| 26 printer.visit(rewritten); | 20 printer.visit(rewritten); |
| 27 Expect.stringEquals(expected, context.getText()); | 21 Expect.stringEquals(expected, context.getText()); |
| 28 } | 22 } |
| 29 | 23 |
| 24 void testAsyncTransform(String source, String expected) { |
| 25 testTransform(source, expected, new AsyncRewriter( |
| 26 null, // The diagnostic helper should not be used in these tests. |
| 27 null, |
| 28 asyncHelper: new VariableUse("thenHelper"), |
| 29 newCompleter: new VariableUse("Completer"), |
| 30 safeVariableName: (String name) => "__$name", |
| 31 bodyName: new StringBackedName("body"))); |
| 32 } |
| 33 |
| 34 void testSyncStarTransform(String source, String expected) { |
| 35 testTransform(source, expected, new SyncStarRewriter( |
| 36 null, |
| 37 null, |
| 38 endOfIteration: new VariableUse("endOfIteration"), |
| 39 newIterable: new VariableUse("newIterable"), |
| 40 yieldStarExpression: new VariableUse("yieldStar"), |
| 41 uncaughtErrorExpression: new VariableUse("uncaughtError"), |
| 42 safeVariableName: (String name) => "__$name", |
| 43 bodyName: new StringBackedName("body"))); |
| 44 } |
| 45 |
| 30 main() { | 46 main() { |
| 31 testTransform(""" | 47 testAsyncTransform(""" |
| 32 function(a) async { | 48 function(a) async { |
| 33 print(this.x); // Ensure `this` is translated in the helper function. | 49 print(this.x); // Ensure `this` is translated in the helper function. |
| 34 await foo(); | 50 await foo(); |
| 35 }""", """ | 51 }""", """ |
| 36 function(a) { | 52 function(a) { |
| 37 var __goto = 0, __completer = new Completer(), __handler = 1, __currentError,
__self = this; | 53 var __goto = 0, __completer = new Completer(), __handler = 1, __currentError,
__self = this; |
| 38 function body(__errorCode, __result) { | 54 function body(__errorCode, __result) { |
| 39 if (__errorCode === 1) { | 55 if (__errorCode === 1) { |
| 40 __currentError = __result; | 56 __currentError = __result; |
| 41 __goto = __handler; | 57 __goto = __handler; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 52 // implicit return | 68 // implicit return |
| 53 return thenHelper(null, 0, __completer, null); | 69 return thenHelper(null, 0, __completer, null); |
| 54 case 1: | 70 case 1: |
| 55 // rethrow | 71 // rethrow |
| 56 return thenHelper(__currentError, 1, __completer); | 72 return thenHelper(__currentError, 1, __completer); |
| 57 } | 73 } |
| 58 } | 74 } |
| 59 return thenHelper(null, body, __completer, null); | 75 return thenHelper(null, body, __completer, null); |
| 60 }"""); | 76 }"""); |
| 61 | 77 |
| 62 testTransform(""" | 78 testAsyncTransform(""" |
| 63 function(b) async { | 79 function(b) async { |
| 64 try { | 80 try { |
| 65 __outer: while (true) { // Overlapping label name. | 81 __outer: while (true) { // Overlapping label name. |
| 66 try { | 82 try { |
| 67 inner: while (true) { | 83 inner: while (true) { |
| 68 break __outer; // Break from untranslated loop to translated target. | 84 break __outer; // Break from untranslated loop to translated target. |
| 69 break; // break to untranslated target. | 85 break; // break to untranslated target. |
| 70 } | 86 } |
| 71 while (true) { | 87 while (true) { |
| 72 return; // Return via finallies. | 88 return; // Return via finallies. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 // return | 192 // return |
| 177 return thenHelper(__returnValue, 0, __completer, null); | 193 return thenHelper(__returnValue, 0, __completer, null); |
| 178 case 2: | 194 case 2: |
| 179 // rethrow | 195 // rethrow |
| 180 return thenHelper(__currentError, 1, __completer); | 196 return thenHelper(__currentError, 1, __completer); |
| 181 } | 197 } |
| 182 } | 198 } |
| 183 return thenHelper(null, body, __completer, null); | 199 return thenHelper(null, body, __completer, null); |
| 184 }"""); | 200 }"""); |
| 185 | 201 |
| 186 testTransform(""" | 202 testAsyncTransform(""" |
| 187 function(c) async { | 203 function(c) async { |
| 188 var a, b, c, d, e, f; | 204 var a, b, c, d, e, f; |
| 189 a = b++; // post- and preincrements. | 205 a = b++; // post- and preincrements. |
| 190 b = --b; | 206 b = --b; |
| 191 c = (await foo()).a++; | 207 c = (await foo()).a++; |
| 192 d = ++(await foo()).a; | 208 d = ++(await foo()).a; |
| 193 e = foo1()[await foo2()]--; | 209 e = foo1()[await foo2()]--; |
| 194 f = --foo1()[await foo2()]; | 210 f = --foo1()[await foo2()]; |
| 195 }""", """ | 211 }""", """ |
| 196 function(c) { | 212 function(c) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 // implicit return | 247 // implicit return |
| 232 return thenHelper(null, 0, __completer, null); | 248 return thenHelper(null, 0, __completer, null); |
| 233 case 1: | 249 case 1: |
| 234 // rethrow | 250 // rethrow |
| 235 return thenHelper(__currentError, 1, __completer); | 251 return thenHelper(__currentError, 1, __completer); |
| 236 } | 252 } |
| 237 } | 253 } |
| 238 return thenHelper(null, body, __completer, null); | 254 return thenHelper(null, body, __completer, null); |
| 239 }"""); | 255 }"""); |
| 240 | 256 |
| 241 testTransform(""" | 257 testAsyncTransform(""" |
| 242 function(d2) async { | 258 function(d2) async { |
| 243 var a, b, c, d, e, f, g, h; // empty initializer | 259 var a, b, c, d, e, f, g, h; // empty initializer |
| 244 a = foo1() || await foo2(); // short circuiting operators | 260 a = foo1() || await foo2(); // short circuiting operators |
| 245 b = await foo1() || foo2(); | 261 b = await foo1() || foo2(); |
| 246 c = await foo1() || foo3(await foo2()); | 262 c = await foo1() || foo3(await foo2()); |
| 247 d = foo1() || foo2(); | 263 d = foo1() || foo2(); |
| 248 e = foo1() && await foo2(); | 264 e = foo1() && await foo2(); |
| 249 f = await foo1() && foo2(); | 265 f = await foo1() && foo2(); |
| 250 g = await foo1() && await foo2(); | 266 g = await foo1() && await foo2(); |
| 251 h = foo1() && foo2(); | 267 h = foo1() && foo2(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 // implicit return | 380 // implicit return |
| 365 return thenHelper(null, 0, __completer, null); | 381 return thenHelper(null, 0, __completer, null); |
| 366 case 1: | 382 case 1: |
| 367 // rethrow | 383 // rethrow |
| 368 return thenHelper(__currentError, 1, __completer); | 384 return thenHelper(__currentError, 1, __completer); |
| 369 } | 385 } |
| 370 } | 386 } |
| 371 return thenHelper(null, body, __completer, null); | 387 return thenHelper(null, body, __completer, null); |
| 372 }"""); | 388 }"""); |
| 373 | 389 |
| 374 testTransform(""" | 390 testAsyncTransform(""" |
| 375 function(x, y) async { | 391 function(x, y) async { |
| 376 while (true) { | 392 while (true) { |
| 377 switch(y) { // Switch with no awaits in case key expressions | 393 switch(y) { // Switch with no awaits in case key expressions |
| 378 case 0: | 394 case 0: |
| 379 case 1: | 395 case 1: |
| 380 await foo(); | 396 await foo(); |
| 381 continue; // Continue the loop, not the switch | 397 continue; // Continue the loop, not the switch |
| 382 case 1: // Duplicate case | 398 case 1: // Duplicate case |
| 383 await foo(); | 399 await foo(); |
| 384 break; // Break the switch | 400 break; // Break the switch |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // implicit return | 474 // implicit return |
| 459 return thenHelper(null, 0, __completer, null); | 475 return thenHelper(null, 0, __completer, null); |
| 460 case 1: | 476 case 1: |
| 461 // rethrow | 477 // rethrow |
| 462 return thenHelper(__currentError, 1, __completer); | 478 return thenHelper(__currentError, 1, __completer); |
| 463 } | 479 } |
| 464 } | 480 } |
| 465 return thenHelper(null, body, __completer, null); | 481 return thenHelper(null, body, __completer, null); |
| 466 }"""); | 482 }"""); |
| 467 | 483 |
| 468 testTransform(""" | 484 testAsyncTransform(""" |
| 469 function(f) async { | 485 function(f) async { |
| 470 do { | 486 do { |
| 471 var a = await foo(); | 487 var a = await foo(); |
| 472 if (a) // If with no awaits in body | 488 if (a) // If with no awaits in body |
| 473 break; | 489 break; |
| 474 else | 490 else |
| 475 continue; | 491 continue; |
| 476 } while (await foo()); | 492 } while (await foo()); |
| 477 } | 493 } |
| 478 """, """ | 494 """, """ |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 // implicit return | 535 // implicit return |
| 520 return thenHelper(null, 0, __completer, null); | 536 return thenHelper(null, 0, __completer, null); |
| 521 case 1: | 537 case 1: |
| 522 // rethrow | 538 // rethrow |
| 523 return thenHelper(__currentError, 1, __completer); | 539 return thenHelper(__currentError, 1, __completer); |
| 524 } | 540 } |
| 525 } | 541 } |
| 526 return thenHelper(null, body, __completer, null); | 542 return thenHelper(null, body, __completer, null); |
| 527 }"""); | 543 }"""); |
| 528 | 544 |
| 529 testTransform(""" | 545 testAsyncTransform(""" |
| 530 function(g) async { | 546 function(g) async { |
| 531 for (var i = 0; i < await foo1(); i += await foo2()) { | 547 for (var i = 0; i < await foo1(); i += await foo2()) { |
| 532 if (foo(i)) | 548 if (foo(i)) |
| 533 continue; | 549 continue; |
| 534 else | 550 else |
| 535 break; | 551 break; |
| 536 if (!foo(i)) { // If with no else and await in body. | 552 if (!foo(i)) { // If with no else and await in body. |
| 537 await foo(); | 553 await foo(); |
| 538 return; | 554 return; |
| 539 } | 555 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 // return | 625 // return |
| 610 return thenHelper(__returnValue, 0, __completer, null); | 626 return thenHelper(__returnValue, 0, __completer, null); |
| 611 case 2: | 627 case 2: |
| 612 // rethrow | 628 // rethrow |
| 613 return thenHelper(__currentError, 1, __completer); | 629 return thenHelper(__currentError, 1, __completer); |
| 614 } | 630 } |
| 615 } | 631 } |
| 616 return thenHelper(null, body, __completer, null); | 632 return thenHelper(null, body, __completer, null); |
| 617 }"""); | 633 }"""); |
| 618 | 634 |
| 619 testTransform(""" | 635 testAsyncTransform(""" |
| 620 function(a, h) async { | 636 function(a, h) async { |
| 621 var x = {"a": foo1(), "b": await foo2(), "c": foo3()}; | 637 var x = {"a": foo1(), "b": await foo2(), "c": foo3()}; |
| 622 x["a"] = 2; // Different assignments | 638 x["a"] = 2; // Different assignments |
| 623 (await foo()).a = 3; | 639 (await foo()).a = 3; |
| 624 x[await foo()] = 4; | 640 x[await foo()] = 4; |
| 625 x[(await foo1()).a = await foo2()] = 5; | 641 x[(await foo1()).a = await foo2()] = 5; |
| 626 (await foo1())[await foo2()] = await foo3(6); | 642 (await foo1())[await foo2()] = await foo3(6); |
| 627 } | 643 } |
| 628 """, """ | 644 """, """ |
| 629 function(a, h) { | 645 function(a, h) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 // implicit return | 700 // implicit return |
| 685 return thenHelper(null, 0, __completer, null); | 701 return thenHelper(null, 0, __completer, null); |
| 686 case 1: | 702 case 1: |
| 687 // rethrow | 703 // rethrow |
| 688 return thenHelper(__currentError, 1, __completer); | 704 return thenHelper(__currentError, 1, __completer); |
| 689 } | 705 } |
| 690 } | 706 } |
| 691 return thenHelper(null, body, __completer, null); | 707 return thenHelper(null, body, __completer, null); |
| 692 }"""); | 708 }"""); |
| 693 | 709 |
| 694 testTransform(""" | 710 testAsyncTransform(""" |
| 695 function(c, i) async { | 711 function(c, i) async { |
| 696 try { | 712 try { |
| 697 var x = c ? await foo() : foo(); // conditional | 713 var x = c ? await foo() : foo(); // conditional |
| 698 var y = {}; | 714 var y = {}; |
| 699 } catch (error) { | 715 } catch (error) { |
| 700 try { | 716 try { |
| 701 x = c ? await fooError(error) : fooError(error); | 717 x = c ? await fooError(error) : fooError(error); |
| 702 } catch (error) { // nested error handler with overlapping name | 718 } catch (error) { // nested error handler with overlapping name |
| 703 y.x = foo(error); | 719 y.x = foo(error); |
| 704 } finally { | 720 } finally { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 // implicit return | 817 // implicit return |
| 802 return thenHelper(null, 0, __completer, null); | 818 return thenHelper(null, 0, __completer, null); |
| 803 case 1: | 819 case 1: |
| 804 // rethrow | 820 // rethrow |
| 805 return thenHelper(__currentError, 1, __completer); | 821 return thenHelper(__currentError, 1, __completer); |
| 806 } | 822 } |
| 807 } | 823 } |
| 808 return thenHelper(null, body, __completer, null); | 824 return thenHelper(null, body, __completer, null); |
| 809 }"""); | 825 }"""); |
| 810 | 826 |
| 811 testTransform(""" | 827 testAsyncTransform(""" |
| 812 function(x, y, j) async { | 828 function(x, y, j) async { |
| 813 print(await(foo(x))); // calls | 829 print(await(foo(x))); // calls |
| 814 (await print)(foo(x)); | 830 (await print)(foo(x)); |
| 815 print(foo(await x)); | 831 print(foo(await x)); |
| 816 await (print(foo(await x))); | 832 await (print(foo(await x))); |
| 817 print(foo(x, await y, z)); | 833 print(foo(x, await y, z)); |
| 818 } | 834 } |
| 819 """, """ | 835 """, """ |
| 820 function(x, y, j) { | 836 function(x, y, j) { |
| 821 var __goto = 0, __completer = new Completer(), __handler = 1, __currentError,
__temp1, __temp2, __temp3; | 837 var __goto = 0, __completer = new Completer(), __handler = 1, __currentError,
__temp1, __temp2, __temp3; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 // implicit return | 883 // implicit return |
| 868 return thenHelper(null, 0, __completer, null); | 884 return thenHelper(null, 0, __completer, null); |
| 869 case 1: | 885 case 1: |
| 870 // rethrow | 886 // rethrow |
| 871 return thenHelper(__currentError, 1, __completer); | 887 return thenHelper(__currentError, 1, __completer); |
| 872 } | 888 } |
| 873 } | 889 } |
| 874 return thenHelper(null, body, __completer, null); | 890 return thenHelper(null, body, __completer, null); |
| 875 }"""); | 891 }"""); |
| 876 | 892 |
| 877 testTransform(""" | 893 testAsyncTransform(""" |
| 878 function(x, y, k) async { | 894 function(x, y, k) async { |
| 879 while (await(foo())) { | 895 while (await(foo())) { |
| 880 lab: { // labelled statement | 896 lab: { // labelled statement |
| 881 switch(y) { | 897 switch(y) { |
| 882 case 0: | 898 case 0: |
| 883 foo(); | 899 foo(); |
| 884 case 0: // Duplicate case | 900 case 0: // Duplicate case |
| 885 print(await foo1(x)); | 901 print(await foo1(x)); |
| 886 return y; | 902 return y; |
| 887 case await bar(): // await in case | 903 case await bar(): // await in case |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 case 1: | 1022 case 1: |
| 1007 // return | 1023 // return |
| 1008 return thenHelper(__returnValue, 0, __completer, null); | 1024 return thenHelper(__returnValue, 0, __completer, null); |
| 1009 case 2: | 1025 case 2: |
| 1010 // rethrow | 1026 // rethrow |
| 1011 return thenHelper(__currentError, 1, __completer); | 1027 return thenHelper(__currentError, 1, __completer); |
| 1012 } | 1028 } |
| 1013 } | 1029 } |
| 1014 return thenHelper(null, body, __completer, null); | 1030 return thenHelper(null, body, __completer, null); |
| 1015 }"""); | 1031 }"""); |
| 1016 testTransform(""" | 1032 |
| 1033 testAsyncTransform(""" |
| 1017 function(l) async { | 1034 function(l) async { |
| 1018 switch(await l) { | 1035 switch(await l) { |
| 1019 case 1: | 1036 case 1: |
| 1020 print(1); | 1037 print(1); |
| 1021 break; | 1038 break; |
| 1022 case 2: | 1039 case 2: |
| 1023 print(1); | 1040 print(1); |
| 1024 // Fallthrough | 1041 // Fallthrough |
| 1025 default: | 1042 default: |
| 1026 print(2); | 1043 print(2); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1055 // implicit return | 1072 // implicit return |
| 1056 return thenHelper(null, 0, __completer, null); | 1073 return thenHelper(null, 0, __completer, null); |
| 1057 case 1: | 1074 case 1: |
| 1058 // rethrow | 1075 // rethrow |
| 1059 return thenHelper(__currentError, 1, __completer); | 1076 return thenHelper(__currentError, 1, __completer); |
| 1060 } | 1077 } |
| 1061 } | 1078 } |
| 1062 return thenHelper(null, body, __completer, null); | 1079 return thenHelper(null, body, __completer, null); |
| 1063 }"""); | 1080 }"""); |
| 1064 | 1081 |
| 1065 testTransform(""" | 1082 testAsyncTransform(""" |
| 1066 function(m) async { | 1083 function(m) async { |
| 1067 var exception = 1; | 1084 var exception = 1; |
| 1068 try { | 1085 try { |
| 1069 await 42; | 1086 await 42; |
| 1070 throw 42; | 1087 throw 42; |
| 1071 } catch (exception) { | 1088 } catch (exception) { |
| 1072 exception = await 10; | 1089 exception = await 10; |
| 1073 exception += await 10; | 1090 exception += await 10; |
| 1074 exception++; | 1091 exception++; |
| 1075 exception--; | 1092 exception--; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 print(exception); | 1150 print(exception); |
| 1134 // implicit return | 1151 // implicit return |
| 1135 return thenHelper(null, 0, __completer, null); | 1152 return thenHelper(null, 0, __completer, null); |
| 1136 case 1: | 1153 case 1: |
| 1137 // rethrow | 1154 // rethrow |
| 1138 return thenHelper(__currentError, 1, __completer); | 1155 return thenHelper(__currentError, 1, __completer); |
| 1139 } | 1156 } |
| 1140 } | 1157 } |
| 1141 return thenHelper(null, body, __completer, null); | 1158 return thenHelper(null, body, __completer, null); |
| 1142 }"""); | 1159 }"""); |
| 1160 |
| 1161 testSyncStarTransform(""" |
| 1162 function(a) sync* { |
| 1163 // Ensure that return of a value is treated as first evaluating the value, and |
| 1164 // then returning. |
| 1165 return foo(); |
| 1166 }""", """ |
| 1167 function(__a) { |
| 1168 return new newIterable(function() { |
| 1169 var a = __a; |
| 1170 var __goto = 0, __handler = 2, __currentError; |
| 1171 return function body(__errorCode, __result) { |
| 1172 if (__errorCode === 1) { |
| 1173 __currentError = __result; |
| 1174 __goto = __handler; |
| 1175 } |
| 1176 while (true) |
| 1177 switch (__goto) { |
| 1178 case 0: |
| 1179 // Function start |
| 1180 foo(); |
| 1181 // goto return |
| 1182 __goto = 1; |
| 1183 break; |
| 1184 case 1: |
| 1185 // return |
| 1186 return endOfIteration(); |
| 1187 case 2: |
| 1188 // rethrow |
| 1189 return uncaughtError(__currentError); |
| 1190 } |
| 1191 }; |
| 1192 }); |
| 1193 }"""); |
| 1143 } | 1194 } |
| OLD | NEW |