| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library trydart.incremental_compilation_update_test; | |
| 6 | |
| 7 import 'dart:html' hide | |
| 8 Element; | |
| 9 | |
| 10 import 'dart:async' show | |
| 11 Future; | |
| 12 | |
| 13 import 'package:async_helper/async_helper.dart' show | |
| 14 asyncTest; | |
| 15 | |
| 16 import 'package:expect/expect.dart' show | |
| 17 Expect; | |
| 18 | |
| 19 import 'package:try/src/interaction_manager.dart' show | |
| 20 splitLines; | |
| 21 | |
| 22 import 'package:try/poi/scope_information_visitor.dart' show | |
| 23 ScopeInformationVisitor; | |
| 24 | |
| 25 import 'sandbox.dart' show | |
| 26 appendIFrame, | |
| 27 listener; | |
| 28 | |
| 29 import 'web_compiler_test_case.dart' show | |
| 30 WebCompilerTestCase, | |
| 31 WebInputProvider; | |
| 32 | |
| 33 import '../poi/compiler_test_case.dart' show | |
| 34 CompilerTestCase; | |
| 35 | |
| 36 import 'package:compiler/src/elements/elements.dart' show | |
| 37 Element, | |
| 38 LibraryElement; | |
| 39 | |
| 40 import 'package:compiler/src/compiler.dart' show | |
| 41 Compiler; | |
| 42 | |
| 43 import 'package:dart2js_incremental/dart2js_incremental.dart' show | |
| 44 IncrementalCompilationFailed; | |
| 45 | |
| 46 import 'program_result.dart'; | |
| 47 | |
| 48 const int TIMEOUT = 100; | |
| 49 | |
| 50 const List<EncodedResult> tests = const <EncodedResult>[ | |
| 51 // Basic hello-world test. | |
| 52 const EncodedResult( | |
| 53 const [ | |
| 54 "main() { print('Hello, ", | |
| 55 const ["", "Brave New "], | |
| 56 "World!'); }", | |
| 57 ], | |
| 58 const <ProgramExpectation>[ | |
| 59 const ProgramExpectation( | |
| 60 const <String>['Hello, World!']), | |
| 61 const ProgramExpectation( | |
| 62 const <String>['Hello, Brave New World!']), | |
| 63 ]), | |
| 64 | |
| 65 // Test that the test framework handles more than one update. | |
| 66 const EncodedResult( | |
| 67 const [ | |
| 68 "main() { print('", | |
| 69 const [ | |
| 70 "Hello darkness, my old friend", | |
| 71 "I\\'ve come to talk with you again", | |
| 72 "Because a vision softly creeping", | |
| 73 ], | |
| 74 "'); }", | |
| 75 ], | |
| 76 const <ProgramExpectation>[ | |
| 77 const ProgramExpectation( | |
| 78 const <String>['Hello darkness, my old friend']), | |
| 79 const ProgramExpectation( | |
| 80 const <String>['I\'ve come to talk with you again']), | |
| 81 const ProgramExpectation( | |
| 82 const <String>['Because a vision softly creeping']), | |
| 83 ]), | |
| 84 | |
| 85 // Test that that isolate support works. | |
| 86 const EncodedResult( | |
| 87 const [ | |
| 88 "main(arguments) { print(", | |
| 89 const [ | |
| 90 "'Hello, Isolated World!'", | |
| 91 "arguments" | |
| 92 ], | |
| 93 "); }", | |
| 94 ], | |
| 95 const <ProgramExpectation>[ | |
| 96 const ProgramExpectation( | |
| 97 const <String>['Hello, Isolated World!']), | |
| 98 const ProgramExpectation( | |
| 99 const <String>['[]']), | |
| 100 ]), | |
| 101 | |
| 102 const EncodedResult( | |
| 103 const [ | |
| 104 r""" | |
| 105 // Test that a stored closure changes behavior when updated. | |
| 106 | |
| 107 var closure; | |
| 108 | |
| 109 foo(a, [b = 'b']) { | |
| 110 """, | |
| 111 const [ | |
| 112 r""" | |
| 113 print('$a $b'); | |
| 114 """, | |
| 115 r""" | |
| 116 print('$b $a'); | |
| 117 """, | |
| 118 ], | |
| 119 r""" | |
| 120 } | |
| 121 | |
| 122 main() { | |
| 123 if (closure == null) { | |
| 124 print('[closure] is null.'); | |
| 125 closure = foo; | |
| 126 } | |
| 127 closure('a'); | |
| 128 closure('a', 'c'); | |
| 129 } | |
| 130 """], | |
| 131 const <ProgramExpectation>[ | |
| 132 const ProgramExpectation( | |
| 133 const <String>['[closure] is null.', 'a b', 'a c']), | |
| 134 const ProgramExpectation( | |
| 135 const <String>['b a', 'c a']), | |
| 136 ]), | |
| 137 | |
| 138 const EncodedResult( | |
| 139 const [ | |
| 140 """ | |
| 141 // Test modifying a static method works. | |
| 142 | |
| 143 class C { | |
| 144 static m() { | |
| 145 """, | |
| 146 const [ | |
| 147 r""" | |
| 148 print('v1'); | |
| 149 """, | |
| 150 r""" | |
| 151 print('v2'); | |
| 152 """, | |
| 153 ], | |
| 154 """ | |
| 155 } | |
| 156 } | |
| 157 main() { | |
| 158 C.m(); | |
| 159 } | |
| 160 """, | |
| 161 ], | |
| 162 const <ProgramExpectation>[ | |
| 163 const ProgramExpectation( | |
| 164 const <String>['v1']), | |
| 165 const ProgramExpectation( | |
| 166 const <String>['v2']), | |
| 167 ]), | |
| 168 | |
| 169 const EncodedResult( | |
| 170 const [ | |
| 171 """ | |
| 172 // Test modifying an instance method works. | |
| 173 | |
| 174 class C { | |
| 175 m() { | |
| 176 """, | |
| 177 const [ | |
| 178 r""" | |
| 179 print('v1'); | |
| 180 """, | |
| 181 r""" | |
| 182 print('v2'); | |
| 183 """, | |
| 184 ], | |
| 185 """ | |
| 186 } | |
| 187 } | |
| 188 var instance; | |
| 189 main() { | |
| 190 if (instance == null) { | |
| 191 print('instance is null'); | |
| 192 instance = new C(); | |
| 193 } | |
| 194 instance.m(); | |
| 195 } | |
| 196 """, | |
| 197 | |
| 198 ], | |
| 199 const <ProgramExpectation>[ | |
| 200 const ProgramExpectation( | |
| 201 const <String>['instance is null', 'v1']), | |
| 202 const ProgramExpectation( | |
| 203 const <String>['v2']), | |
| 204 ]), | |
| 205 | |
| 206 const EncodedResult( | |
| 207 const [ | |
| 208 """ | |
| 209 // Test that a stored instance tearoff changes behavior when updated. | |
| 210 | |
| 211 class C { | |
| 212 m() { | |
| 213 """, | |
| 214 const [ | |
| 215 r""" | |
| 216 print('v1'); | |
| 217 """, | |
| 218 r""" | |
| 219 print('v2'); | |
| 220 """, | |
| 221 ], | |
| 222 """ | |
| 223 } | |
| 224 } | |
| 225 var closure; | |
| 226 main() { | |
| 227 if (closure == null) { | |
| 228 print('closure is null'); | |
| 229 closure = new C().m; | |
| 230 } | |
| 231 closure(); | |
| 232 } | |
| 233 """, | |
| 234 | |
| 235 ], | |
| 236 const <ProgramExpectation>[ | |
| 237 const ProgramExpectation( | |
| 238 const <String>['closure is null', 'v1']), | |
| 239 const ProgramExpectation( | |
| 240 const <String>['v2']), | |
| 241 ]), | |
| 242 | |
| 243 const EncodedResult( | |
| 244 const [ | |
| 245 """ | |
| 246 // Test that deleting an instance method works. | |
| 247 | |
| 248 class C { | |
| 249 """, | |
| 250 const [ | |
| 251 """ | |
| 252 m() { | |
| 253 print('v1'); | |
| 254 } | |
| 255 """, | |
| 256 """ | |
| 257 """, | |
| 258 ], | |
| 259 """ | |
| 260 } | |
| 261 var instance; | |
| 262 main() { | |
| 263 if (instance == null) { | |
| 264 print('instance is null'); | |
| 265 instance = new C(); | |
| 266 } | |
| 267 try { | |
| 268 instance.m(); | |
| 269 } catch (e) { | |
| 270 print('threw'); | |
| 271 } | |
| 272 } | |
| 273 """, | |
| 274 ], | |
| 275 const <ProgramExpectation>[ | |
| 276 const ProgramExpectation( | |
| 277 const <String>['instance is null', 'v1']), | |
| 278 const ProgramExpectation( | |
| 279 const <String>['threw']), | |
| 280 ]), | |
| 281 | |
| 282 const EncodedResult( | |
| 283 const [ | |
| 284 """ | |
| 285 // Test that deleting an instance method works, even when accessed through | |
| 286 // super. | |
| 287 | |
| 288 class A { | |
| 289 m() { | |
| 290 print('v2'); | |
| 291 } | |
| 292 } | |
| 293 class B extends A { | |
| 294 """, | |
| 295 const [ | |
| 296 """ | |
| 297 m() { | |
| 298 print('v1'); | |
| 299 } | |
| 300 """, | |
| 301 """ | |
| 302 """, | |
| 303 ], | |
| 304 """ | |
| 305 } | |
| 306 class C extends B { | |
| 307 m() { | |
| 308 super.m(); | |
| 309 } | |
| 310 } | |
| 311 var instance; | |
| 312 main() { | |
| 313 if (instance == null) { | |
| 314 print('instance is null'); | |
| 315 instance = new C(); | |
| 316 } | |
| 317 instance.m(); | |
| 318 } | |
| 319 """, | |
| 320 | |
| 321 ], | |
| 322 const <ProgramExpectation>[ | |
| 323 const ProgramExpectation( | |
| 324 const <String>['instance is null', 'v1']), | |
| 325 const ProgramExpectation( | |
| 326 const <String>['v2']), | |
| 327 ]), | |
| 328 | |
| 329 const EncodedResult( | |
| 330 const [ | |
| 331 """ | |
| 332 // Test that deleting a top-level method works. | |
| 333 | |
| 334 """, | |
| 335 const [ | |
| 336 """ | |
| 337 toplevel() { | |
| 338 print('v1'); | |
| 339 } | |
| 340 """, | |
| 341 """ | |
| 342 """, | |
| 343 ], | |
| 344 """ | |
| 345 class C { | |
| 346 m() { | |
| 347 try { | |
| 348 toplevel(); | |
| 349 } catch (e) { | |
| 350 print('threw'); | |
| 351 } | |
| 352 } | |
| 353 } | |
| 354 var instance; | |
| 355 main() { | |
| 356 if (instance == null) { | |
| 357 print('instance is null'); | |
| 358 instance = new C(); | |
| 359 } | |
| 360 instance.m(); | |
| 361 } | |
| 362 """, | |
| 363 ], | |
| 364 const <ProgramExpectation>[ | |
| 365 const ProgramExpectation( | |
| 366 const <String>['instance is null', 'v1']), | |
| 367 const ProgramExpectation( | |
| 368 const <String>['threw']), | |
| 369 ]), | |
| 370 | |
| 371 const EncodedResult( | |
| 372 const [ | |
| 373 """ | |
| 374 // Test that deleting a static method works. | |
| 375 | |
| 376 class B { | |
| 377 """, | |
| 378 const [ | |
| 379 """ | |
| 380 static staticMethod() { | |
| 381 print('v1'); | |
| 382 } | |
| 383 """, | |
| 384 """ | |
| 385 """, | |
| 386 ], | |
| 387 """ | |
| 388 } | |
| 389 class C { | |
| 390 m() { | |
| 391 try { | |
| 392 B.staticMethod(); | |
| 393 } catch (e) { | |
| 394 print('threw'); | |
| 395 } | |
| 396 try { | |
| 397 // Ensure that noSuchMethod support is compiled. This test is not about | |
| 398 // adding new classes. | |
| 399 B.missingMethod(); | |
| 400 print('bad'); | |
| 401 } catch (e) { | |
| 402 } | |
| 403 } | |
| 404 } | |
| 405 var instance; | |
| 406 main() { | |
| 407 if (instance == null) { | |
| 408 print('instance is null'); | |
| 409 instance = new C(); | |
| 410 } | |
| 411 instance.m(); | |
| 412 } | |
| 413 """, | |
| 414 ], | |
| 415 const <ProgramExpectation>[ | |
| 416 const ProgramExpectation( | |
| 417 const <String>['instance is null', 'v1']), | |
| 418 const ProgramExpectation( | |
| 419 const <String>['threw']), | |
| 420 ]), | |
| 421 | |
| 422 const EncodedResult( | |
| 423 const [ | |
| 424 """ | |
| 425 // Test that a newly instantiated class is handled. | |
| 426 | |
| 427 class A { | |
| 428 m() { | |
| 429 print('Called A.m'); | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 class B { | |
| 434 m() { | |
| 435 print('Called B.m'); | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 var instance; | |
| 440 main() { | |
| 441 if (instance == null) { | |
| 442 print('instance is null'); | |
| 443 instance = new A(); | |
| 444 """, | |
| 445 const [ | |
| 446 """ | |
| 447 """, | |
| 448 """ | |
| 449 } else { | |
| 450 instance = new B(); | |
| 451 """, | |
| 452 ], | |
| 453 """ | |
| 454 } | |
| 455 instance.m(); | |
| 456 } | |
| 457 """, | |
| 458 | |
| 459 ], | |
| 460 const <ProgramExpectation>[ | |
| 461 const ProgramExpectation( | |
| 462 const <String>['instance is null', 'Called A.m']), | |
| 463 const ProgramExpectation( | |
| 464 const <String>['Called B.m']), | |
| 465 ]), | |
| 466 | |
| 467 const EncodedResult( | |
| 468 const [ | |
| 469 """ | |
| 470 // Test that source maps don't throw exceptions. | |
| 471 | |
| 472 main() { | |
| 473 print('a'); | |
| 474 """, | |
| 475 const [ | |
| 476 """ | |
| 477 """, | |
| 478 """ | |
| 479 print('b'); | |
| 480 print('c'); | |
| 481 """, | |
| 482 ], | |
| 483 """ | |
| 484 } | |
| 485 """, | |
| 486 ], | |
| 487 const <ProgramExpectation>[ | |
| 488 const ProgramExpectation( | |
| 489 const <String>['a']), | |
| 490 const ProgramExpectation( | |
| 491 const <String>['a', 'b', 'c']), | |
| 492 ]), | |
| 493 | |
| 494 const EncodedResult( | |
| 495 const [ | |
| 496 r""" | |
| 497 // Test that a newly instantiated class is handled. | |
| 498 | |
| 499 class A { | |
| 500 get name => 'A.m'; | |
| 501 | |
| 502 m() { | |
| 503 print('Called $name'); | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 class B extends A { | |
| 508 get name => 'B.m'; | |
| 509 } | |
| 510 | |
| 511 var instance; | |
| 512 main() { | |
| 513 if (instance == null) { | |
| 514 print('instance is null'); | |
| 515 instance = new A(); | |
| 516 """, | |
| 517 const [ | |
| 518 r""" | |
| 519 """, | |
| 520 r""" | |
| 521 } else { | |
| 522 instance = new B(); | |
| 523 """, | |
| 524 ], | |
| 525 r""" | |
| 526 } | |
| 527 instance.m(); | |
| 528 } | |
| 529 """, | |
| 530 ], | |
| 531 const <ProgramExpectation>[ | |
| 532 const ProgramExpectation( | |
| 533 const <String>['instance is null', 'Called A.m']), | |
| 534 const ProgramExpectation( | |
| 535 const <String>['Called B.m']), | |
| 536 ]), | |
| 537 | |
| 538 const EncodedResult( | |
| 539 const [ | |
| 540 r""" | |
| 541 // Test that fields of a newly instantiated class are handled. | |
| 542 | |
| 543 class A { | |
| 544 var x; | |
| 545 A(this.x); | |
| 546 } | |
| 547 var instance; | |
| 548 foo() { | |
| 549 if (instance != null) { | |
| 550 print(instance.x); | |
| 551 } else { | |
| 552 print('v1'); | |
| 553 } | |
| 554 } | |
| 555 main() { | |
| 556 """, | |
| 557 const [ | |
| 558 r""" | |
| 559 """, | |
| 560 r""" | |
| 561 instance = new A('v2'); | |
| 562 """, | |
| 563 ], | |
| 564 r""" | |
| 565 foo(); | |
| 566 } | |
| 567 """, | |
| 568 ], | |
| 569 const <ProgramExpectation>[ | |
| 570 const ProgramExpectation( | |
| 571 const <String>['v1']), | |
| 572 const ProgramExpectation( | |
| 573 const <String>['v2']), | |
| 574 ]), | |
| 575 | |
| 576 const EncodedResult( | |
| 577 const [ | |
| 578 r""" | |
| 579 // Test that top-level functions can be added. | |
| 580 | |
| 581 """, | |
| 582 const [ | |
| 583 "", | |
| 584 r""" | |
| 585 foo() { | |
| 586 print('v2'); | |
| 587 } | |
| 588 """, | |
| 589 ], | |
| 590 r""" | |
| 591 main() { | |
| 592 try { | |
| 593 foo(); | |
| 594 } catch(e) { | |
| 595 print('threw'); | |
| 596 } | |
| 597 } | |
| 598 """, | |
| 599 ], | |
| 600 const <ProgramExpectation>[ | |
| 601 const ProgramExpectation( | |
| 602 const <String>['threw']), | |
| 603 const ProgramExpectation( | |
| 604 const <String>['v2']), | |
| 605 ]), | |
| 606 | |
| 607 const EncodedResult( | |
| 608 const [ | |
| 609 r""" | |
| 610 // Test that static methods can be added. | |
| 611 | |
| 612 class C { | |
| 613 """, | |
| 614 const [ | |
| 615 "", | |
| 616 r""" | |
| 617 static foo() { | |
| 618 print('v2'); | |
| 619 } | |
| 620 """, | |
| 621 ], | |
| 622 r""" | |
| 623 } | |
| 624 | |
| 625 main() { | |
| 626 try { | |
| 627 C.foo(); | |
| 628 } catch(e) { | |
| 629 print('threw'); | |
| 630 } | |
| 631 } | |
| 632 """, | |
| 633 | |
| 634 ], | |
| 635 const <ProgramExpectation>[ | |
| 636 const ProgramExpectation( | |
| 637 const <String>['threw']), | |
| 638 const ProgramExpectation( | |
| 639 const <String>['v2']), | |
| 640 ]), | |
| 641 | |
| 642 const EncodedResult( | |
| 643 const [ | |
| 644 r""" | |
| 645 // Test that instance methods can be added. | |
| 646 | |
| 647 class C { | |
| 648 """, | |
| 649 const [ | |
| 650 "", | |
| 651 r""" | |
| 652 foo() { | |
| 653 print('v2'); | |
| 654 } | |
| 655 """, | |
| 656 ], | |
| 657 r""" | |
| 658 } | |
| 659 | |
| 660 var instance; | |
| 661 | |
| 662 main() { | |
| 663 if (instance == null) { | |
| 664 print('instance is null'); | |
| 665 instance = new C(); | |
| 666 } | |
| 667 | |
| 668 try { | |
| 669 instance.foo(); | |
| 670 } catch(e) { | |
| 671 print('threw'); | |
| 672 } | |
| 673 } | |
| 674 """, | |
| 675 ], | |
| 676 const <ProgramExpectation>[ | |
| 677 const ProgramExpectation( | |
| 678 const <String>['instance is null', 'threw']), | |
| 679 const ProgramExpectation( | |
| 680 const <String>['v2']), | |
| 681 ]), | |
| 682 | |
| 683 const EncodedResult( | |
| 684 const [ | |
| 685 r""" | |
| 686 // Test that top-level functions can have signature changed. | |
| 687 | |
| 688 """, | |
| 689 const [ | |
| 690 r""" | |
| 691 foo() { | |
| 692 print('v1'); | |
| 693 """, | |
| 694 r""" | |
| 695 void foo() { | |
| 696 print('v2'); | |
| 697 """, | |
| 698 ], | |
| 699 r""" | |
| 700 } | |
| 701 | |
| 702 main() { | |
| 703 foo(); | |
| 704 } | |
| 705 """, | |
| 706 ], | |
| 707 const <ProgramExpectation>[ | |
| 708 const ProgramExpectation( | |
| 709 const <String>['v1']), | |
| 710 const ProgramExpectation( | |
| 711 const <String>['v2']), | |
| 712 ]), | |
| 713 | |
| 714 const EncodedResult( | |
| 715 const [ | |
| 716 r""" | |
| 717 // Test that static methods can have signature changed. | |
| 718 | |
| 719 class C { | |
| 720 """, | |
| 721 const [ | |
| 722 r""" | |
| 723 static foo() { | |
| 724 print('v1'); | |
| 725 """, | |
| 726 r""" | |
| 727 static void foo() { | |
| 728 print('v2'); | |
| 729 """, | |
| 730 ], | |
| 731 r""" | |
| 732 } | |
| 733 } | |
| 734 | |
| 735 main() { | |
| 736 C.foo(); | |
| 737 } | |
| 738 """, | |
| 739 ], | |
| 740 const <ProgramExpectation>[ | |
| 741 const ProgramExpectation( | |
| 742 const <String>['v1']), | |
| 743 const ProgramExpectation( | |
| 744 const <String>['v2']), | |
| 745 ]), | |
| 746 | |
| 747 const EncodedResult( | |
| 748 const [ | |
| 749 r""" | |
| 750 // Test that instance methods can have signature changed. | |
| 751 | |
| 752 class C { | |
| 753 """, | |
| 754 const [ | |
| 755 r""" | |
| 756 foo() { | |
| 757 print('v1'); | |
| 758 """, | |
| 759 r""" | |
| 760 void foo() { | |
| 761 print('v2'); | |
| 762 """, | |
| 763 ], | |
| 764 r""" | |
| 765 } | |
| 766 } | |
| 767 | |
| 768 var instance; | |
| 769 | |
| 770 main() { | |
| 771 if (instance == null) { | |
| 772 print('instance is null'); | |
| 773 instance = new C(); | |
| 774 } | |
| 775 | |
| 776 instance.foo(); | |
| 777 } | |
| 778 """, | |
| 779 ], | |
| 780 const <ProgramExpectation>[ | |
| 781 const ProgramExpectation( | |
| 782 const <String>['instance is null', 'v1']), | |
| 783 const ProgramExpectation( | |
| 784 const <String>['v2']), | |
| 785 ]), | |
| 786 | |
| 787 const EncodedResult( | |
| 788 const [ | |
| 789 r""" | |
| 790 // Test that adding a class is supported. | |
| 791 | |
| 792 """, | |
| 793 const [ | |
| 794 "", | |
| 795 r""" | |
| 796 class C { | |
| 797 void foo() { | |
| 798 print('v2'); | |
| 799 } | |
| 800 } | |
| 801 """, | |
| 802 ], | |
| 803 r""" | |
| 804 main() { | |
| 805 """, | |
| 806 const [ | |
| 807 r""" | |
| 808 print('v1'); | |
| 809 """, | |
| 810 r""" | |
| 811 new C().foo(); | |
| 812 """, | |
| 813 ], | |
| 814 r""" | |
| 815 } | |
| 816 """, | |
| 817 ], | |
| 818 const <ProgramExpectation>[ | |
| 819 const ProgramExpectation( | |
| 820 const <String>['v1']), | |
| 821 const ProgramExpectation( | |
| 822 const <String>['v2']), | |
| 823 ]), | |
| 824 | |
| 825 const EncodedResult( | |
| 826 const [ | |
| 827 r""" | |
| 828 // Test that removing a class is supported, using constructor. | |
| 829 | |
| 830 """, | |
| 831 const [ | |
| 832 r""" | |
| 833 class C { | |
| 834 } | |
| 835 """, | |
| 836 "" | |
| 837 ], | |
| 838 r""" | |
| 839 main() { | |
| 840 try { | |
| 841 new C(); | |
| 842 print('v1'); | |
| 843 } catch (e) { | |
| 844 print('v2'); | |
| 845 } | |
| 846 } | |
| 847 """, | |
| 848 ], | |
| 849 const <ProgramExpectation>[ | |
| 850 const ProgramExpectation( | |
| 851 const <String>['v1']), | |
| 852 const ProgramExpectation( | |
| 853 const <String>['v2']), | |
| 854 ]), | |
| 855 | |
| 856 const EncodedResult( | |
| 857 const [ | |
| 858 r""" | |
| 859 // Test that removing a class is supported, using a static method. | |
| 860 | |
| 861 """, | |
| 862 const [ | |
| 863 r""" | |
| 864 class C { | |
| 865 static m() { | |
| 866 print('v1'); | |
| 867 } | |
| 868 } | |
| 869 """, | |
| 870 "", | |
| 871 ], | |
| 872 r""" | |
| 873 main() { | |
| 874 try { | |
| 875 C.m(); | |
| 876 } catch (e) { | |
| 877 print('v2'); | |
| 878 } | |
| 879 } | |
| 880 """, | |
| 881 ], | |
| 882 const <ProgramExpectation>[ | |
| 883 const ProgramExpectation( | |
| 884 const <String>['v1']), | |
| 885 const ProgramExpectation( | |
| 886 const <String>['v2']), | |
| 887 ]), | |
| 888 | |
| 889 const EncodedResult( | |
| 890 const [ | |
| 891 r""" | |
| 892 // Test that changing the supertype of a class. | |
| 893 | |
| 894 class A { | |
| 895 m() { | |
| 896 print('v2'); | |
| 897 } | |
| 898 } | |
| 899 class B extends A { | |
| 900 m() { | |
| 901 print('v1'); | |
| 902 } | |
| 903 } | |
| 904 """, | |
| 905 const [ | |
| 906 r""" | |
| 907 class C extends B { | |
| 908 """, | |
| 909 r""" | |
| 910 class C extends A { | |
| 911 """, | |
| 912 ], | |
| 913 r""" | |
| 914 m() { | |
| 915 super.m(); | |
| 916 } | |
| 917 } | |
| 918 | |
| 919 var instance; | |
| 920 | |
| 921 main() { | |
| 922 if (instance == null) { | |
| 923 print('instance is null'); | |
| 924 instance = new C(); | |
| 925 } | |
| 926 instance.m(); | |
| 927 } | |
| 928 """, | |
| 929 ], | |
| 930 const <ProgramExpectation>[ | |
| 931 const ProgramExpectation( | |
| 932 const <String>['instance is null', 'v1']), | |
| 933 const ProgramExpectation( | |
| 934 const <String>['v2']), | |
| 935 ]), | |
| 936 | |
| 937 const EncodedResult( | |
| 938 const [ | |
| 939 r""" | |
| 940 // Test adding a field to a class works. | |
| 941 | |
| 942 class A { | |
| 943 """, | |
| 944 const [ | |
| 945 "", | |
| 946 r""" | |
| 947 var x; | |
| 948 """, | |
| 949 ], | |
| 950 r""" | |
| 951 } | |
| 952 | |
| 953 var instance; | |
| 954 | |
| 955 main() { | |
| 956 if (instance == null) { | |
| 957 print('instance is null'); | |
| 958 instance = new A(); | |
| 959 } | |
| 960 try { | |
| 961 instance.x = 'v2'; | |
| 962 } catch(e) { | |
| 963 print('setter threw'); | |
| 964 } | |
| 965 try { | |
| 966 print(instance.x); | |
| 967 } catch (e) { | |
| 968 print('getter threw'); | |
| 969 } | |
| 970 } | |
| 971 """, | |
| 972 ], | |
| 973 const <ProgramExpectation>[ | |
| 974 const ProgramExpectation( | |
| 975 const <String>['instance is null', 'setter threw', 'getter threw
']), | |
| 976 const ProgramExpectation( | |
| 977 const <String>['v2']), | |
| 978 ]), | |
| 979 | |
| 980 const EncodedResult( | |
| 981 const [ | |
| 982 r""" | |
| 983 // Test removing a field from a class works. | |
| 984 | |
| 985 class A { | |
| 986 """, | |
| 987 const [ | |
| 988 r""" | |
| 989 var x; | |
| 990 """, | |
| 991 "", | |
| 992 ], | |
| 993 r""" | |
| 994 } | |
| 995 | |
| 996 var instance; | |
| 997 | |
| 998 main() { | |
| 999 if (instance == null) { | |
| 1000 print('instance is null'); | |
| 1001 instance = new A(); | |
| 1002 } | |
| 1003 try { | |
| 1004 instance.x = 'v1'; | |
| 1005 } catch(e) { | |
| 1006 print('setter threw'); | |
| 1007 } | |
| 1008 try { | |
| 1009 print(instance.x); | |
| 1010 } catch (e) { | |
| 1011 print('getter threw'); | |
| 1012 } | |
| 1013 } | |
| 1014 """, | |
| 1015 ], | |
| 1016 const <ProgramExpectation>[ | |
| 1017 const ProgramExpectation( | |
| 1018 const <String>['instance is null', 'v1']), | |
| 1019 const ProgramExpectation( | |
| 1020 const <String>['setter threw', 'getter threw']), | |
| 1021 ]), | |
| 1022 | |
| 1023 const EncodedResult( | |
| 1024 const [ | |
| 1025 r""" | |
| 1026 // Test that named arguments can be called. | |
| 1027 | |
| 1028 class C { | |
| 1029 foo({a, named: 'v1', x}) { | |
| 1030 print(named); | |
| 1031 } | |
| 1032 } | |
| 1033 | |
| 1034 var instance; | |
| 1035 | |
| 1036 main() { | |
| 1037 if (instance == null) { | |
| 1038 print('instance is null'); | |
| 1039 instance = new C(); | |
| 1040 } | |
| 1041 """, | |
| 1042 const [ | |
| 1043 r""" | |
| 1044 instance.foo(); | |
| 1045 """, | |
| 1046 r""" | |
| 1047 instance.foo(named: 'v2'); | |
| 1048 """, | |
| 1049 ], | |
| 1050 r""" | |
| 1051 } | |
| 1052 """, | |
| 1053 ], | |
| 1054 const <ProgramExpectation>[ | |
| 1055 const ProgramExpectation( | |
| 1056 const <String>['instance is null', 'v1']), | |
| 1057 const ProgramExpectation( | |
| 1058 const <String>['v2']), | |
| 1059 ]), | |
| 1060 | |
| 1061 const EncodedResult( | |
| 1062 const [ | |
| 1063 r""" | |
| 1064 // Test than named arguments can be called. | |
| 1065 | |
| 1066 class C { | |
| 1067 foo({a, named: 'v2', x}) { | |
| 1068 print(named); | |
| 1069 } | |
| 1070 } | |
| 1071 | |
| 1072 var instance; | |
| 1073 | |
| 1074 main() { | |
| 1075 if (instance == null) { | |
| 1076 print('instance is null'); | |
| 1077 instance = new C(); | |
| 1078 } | |
| 1079 """, | |
| 1080 const [ | |
| 1081 r""" | |
| 1082 instance.foo(named: 'v1'); | |
| 1083 """, | |
| 1084 r""" | |
| 1085 instance.foo(); | |
| 1086 """, | |
| 1087 ], | |
| 1088 r""" | |
| 1089 } | |
| 1090 """, | |
| 1091 ], | |
| 1092 const <ProgramExpectation>[ | |
| 1093 const ProgramExpectation( | |
| 1094 const <String>['instance is null', 'v1']), | |
| 1095 const ProgramExpectation( | |
| 1096 const <String>['v2']), | |
| 1097 ]), | |
| 1098 | |
| 1099 const EncodedResult( | |
| 1100 const [ | |
| 1101 r""" | |
| 1102 // Test that an instance tear-off with named parameters can be called. | |
| 1103 | |
| 1104 class C { | |
| 1105 foo({a, named: 'v1', x}) { | |
| 1106 print(named); | |
| 1107 } | |
| 1108 } | |
| 1109 | |
| 1110 var closure; | |
| 1111 | |
| 1112 main() { | |
| 1113 if (closure == null) { | |
| 1114 print('closure is null'); | |
| 1115 closure = new C().foo; | |
| 1116 } | |
| 1117 """, | |
| 1118 const [ | |
| 1119 r""" | |
| 1120 closure(); | |
| 1121 """, | |
| 1122 r""" | |
| 1123 closure(named: 'v2'); | |
| 1124 """, | |
| 1125 ], | |
| 1126 r""" | |
| 1127 } | |
| 1128 """, | |
| 1129 ], | |
| 1130 const <ProgramExpectation>[ | |
| 1131 const ProgramExpectation( | |
| 1132 const <String>['closure is null', 'v1']), | |
| 1133 const ProgramExpectation( | |
| 1134 const <String>['v2']), | |
| 1135 ]), | |
| 1136 | |
| 1137 const EncodedResult( | |
| 1138 const [ | |
| 1139 r""" | |
| 1140 // Test that a lazy static is supported. | |
| 1141 | |
| 1142 var normal; | |
| 1143 | |
| 1144 """, | |
| 1145 const [ | |
| 1146 r""" | |
| 1147 foo() { | |
| 1148 print(normal); | |
| 1149 } | |
| 1150 """, | |
| 1151 r""" | |
| 1152 var lazy = bar(); | |
| 1153 | |
| 1154 foo() { | |
| 1155 print(lazy); | |
| 1156 } | |
| 1157 | |
| 1158 bar() { | |
| 1159 print('v2'); | |
| 1160 return 'lazy'; | |
| 1161 } | |
| 1162 | |
| 1163 """, | |
| 1164 ], | |
| 1165 r""" | |
| 1166 main() { | |
| 1167 if (normal == null) { | |
| 1168 normal = 'v1'; | |
| 1169 } else { | |
| 1170 normal = ''; | |
| 1171 } | |
| 1172 foo(); | |
| 1173 } | |
| 1174 """, | |
| 1175 ], | |
| 1176 const <ProgramExpectation>[ | |
| 1177 const ProgramExpectation( | |
| 1178 const <String>['v1']), | |
| 1179 const ProgramExpectation( | |
| 1180 const <String>['v2', 'lazy']), | |
| 1181 ]), | |
| 1182 | |
| 1183 const EncodedResult( | |
| 1184 const [ | |
| 1185 r""" | |
| 1186 // Test that superclasses of directly instantiated classes are also emitted. | |
| 1187 class A { | |
| 1188 } | |
| 1189 | |
| 1190 class B extends A { | |
| 1191 } | |
| 1192 | |
| 1193 main() { | |
| 1194 """, | |
| 1195 const [ | |
| 1196 r""" | |
| 1197 print('v1'); | |
| 1198 """, | |
| 1199 r""" | |
| 1200 new B(); | |
| 1201 print('v2'); | |
| 1202 """, | |
| 1203 ], | |
| 1204 r""" | |
| 1205 } | |
| 1206 """, | |
| 1207 ], | |
| 1208 const <ProgramExpectation>[ | |
| 1209 const ProgramExpectation( | |
| 1210 const <String>['v1']), | |
| 1211 const ProgramExpectation( | |
| 1212 const <String>['v2']), | |
| 1213 ]), | |
| 1214 | |
| 1215 const EncodedResult( | |
| 1216 const [ | |
| 1217 r""" | |
| 1218 // Test that interceptor classes are handled correctly. | |
| 1219 | |
| 1220 main() { | |
| 1221 """, | |
| 1222 const [ | |
| 1223 r""" | |
| 1224 print('v1'); | |
| 1225 """, | |
| 1226 r""" | |
| 1227 ['v2'].forEach(print); | |
| 1228 """, | |
| 1229 ], | |
| 1230 r""" | |
| 1231 } | |
| 1232 """, | |
| 1233 ], | |
| 1234 const <ProgramExpectation>[ | |
| 1235 const ProgramExpectation( | |
| 1236 const <String>['v1']), | |
| 1237 const ProgramExpectation( | |
| 1238 const <String>['v2']), | |
| 1239 ]), | |
| 1240 | |
| 1241 const EncodedResult( | |
| 1242 const [ | |
| 1243 r""" | |
| 1244 // Test that newly instantiated superclasses are handled correctly when there | |
| 1245 // is more than one change. | |
| 1246 | |
| 1247 class A { | |
| 1248 foo() { | |
| 1249 print('Called foo'); | |
| 1250 } | |
| 1251 | |
| 1252 bar() { | |
| 1253 print('Called bar'); | |
| 1254 } | |
| 1255 } | |
| 1256 | |
| 1257 class B extends A { | |
| 1258 } | |
| 1259 | |
| 1260 main() { | |
| 1261 """, | |
| 1262 const [ | |
| 1263 r""" | |
| 1264 new B().foo(); | |
| 1265 """, | |
| 1266 r""" | |
| 1267 new B().foo(); | |
| 1268 """, | |
| 1269 r""" | |
| 1270 new A().bar(); | |
| 1271 """, | |
| 1272 ], | |
| 1273 r""" | |
| 1274 } | |
| 1275 """, | |
| 1276 ], | |
| 1277 const <ProgramExpectation>[ | |
| 1278 const ProgramExpectation( | |
| 1279 const <String>['Called foo']), | |
| 1280 const ProgramExpectation( | |
| 1281 const <String>['Called foo']), | |
| 1282 const ProgramExpectation( | |
| 1283 const <String>['Called bar']), | |
| 1284 ]), | |
| 1285 | |
| 1286 const EncodedResult( | |
| 1287 const [ | |
| 1288 r""" | |
| 1289 // Test that newly instantiated subclasses are handled correctly when there is | |
| 1290 // more than one change. | |
| 1291 | |
| 1292 class A { | |
| 1293 foo() { | |
| 1294 print('Called foo'); | |
| 1295 } | |
| 1296 | |
| 1297 bar() { | |
| 1298 print('Called bar'); | |
| 1299 } | |
| 1300 } | |
| 1301 | |
| 1302 class B extends A { | |
| 1303 } | |
| 1304 | |
| 1305 main() { | |
| 1306 """, | |
| 1307 const [ | |
| 1308 r""" | |
| 1309 new A().foo(); | |
| 1310 """, | |
| 1311 r""" | |
| 1312 new A().foo(); | |
| 1313 """, | |
| 1314 r""" | |
| 1315 new B().bar(); | |
| 1316 """, | |
| 1317 ], | |
| 1318 r""" | |
| 1319 } | |
| 1320 """, | |
| 1321 ], | |
| 1322 const <ProgramExpectation>[ | |
| 1323 const ProgramExpectation( | |
| 1324 const <String>['Called foo']), | |
| 1325 const ProgramExpectation( | |
| 1326 const <String>['Called foo']), | |
| 1327 const ProgramExpectation( | |
| 1328 const <String>['Called bar']), | |
| 1329 ]), | |
| 1330 | |
| 1331 const EncodedResult( | |
| 1332 const [ | |
| 1333 r""" | |
| 1334 // Test that constants are handled correctly. | |
| 1335 | |
| 1336 class C { | |
| 1337 final String value; | |
| 1338 const C(this.value); | |
| 1339 } | |
| 1340 | |
| 1341 main() { | |
| 1342 """, | |
| 1343 const [ | |
| 1344 r""" | |
| 1345 print(const C('v1').value); | |
| 1346 """, | |
| 1347 r""" | |
| 1348 print(const C('v2').value); | |
| 1349 """, | |
| 1350 ], | |
| 1351 r""" | |
| 1352 } | |
| 1353 """, | |
| 1354 ], | |
| 1355 const <ProgramExpectation>[ | |
| 1356 const ProgramExpectation( | |
| 1357 const <String>['v1']), | |
| 1358 const ProgramExpectation( | |
| 1359 const <String>['v2']), | |
| 1360 ]), | |
| 1361 | |
| 1362 const EncodedResult( | |
| 1363 const [ | |
| 1364 r""" | |
| 1365 // Test that an instance field can be added to a compound declaration. | |
| 1366 | |
| 1367 class C { | |
| 1368 """, | |
| 1369 const [ | |
| 1370 r""" | |
| 1371 int x; | |
| 1372 """, | |
| 1373 r""" | |
| 1374 int x, y; | |
| 1375 """, | |
| 1376 ], | |
| 1377 r""" | |
| 1378 } | |
| 1379 | |
| 1380 var instance; | |
| 1381 | |
| 1382 main() { | |
| 1383 if (instance == null) { | |
| 1384 print('[instance] is null'); | |
| 1385 instance = new C(); | |
| 1386 instance.x = 'v1'; | |
| 1387 } else { | |
| 1388 instance.y = 'v2'; | |
| 1389 } | |
| 1390 try { | |
| 1391 print(instance.x); | |
| 1392 } catch (e) { | |
| 1393 print('[instance.x] threw'); | |
| 1394 } | |
| 1395 try { | |
| 1396 print(instance.y); | |
| 1397 } catch (e) { | |
| 1398 print('[instance.y] threw'); | |
| 1399 } | |
| 1400 } | |
| 1401 """, | |
| 1402 ], | |
| 1403 const <ProgramExpectation>[ | |
| 1404 const ProgramExpectation( | |
| 1405 const <String>[ | |
| 1406 '[instance] is null', 'v1', '[instance.y] threw']), | |
| 1407 const ProgramExpectation( | |
| 1408 const <String>['v1', 'v2'], | |
| 1409 // TODO(ahe): Shouldn't throw. | |
| 1410 compileUpdatesShouldThrow: true), | |
| 1411 ]), | |
| 1412 | |
| 1413 const EncodedResult( | |
| 1414 const [ | |
| 1415 r""" | |
| 1416 // Test that an instance field can be removed from a compound declaration. | |
| 1417 | |
| 1418 class C { | |
| 1419 """, | |
| 1420 const [ | |
| 1421 r""" | |
| 1422 int x, y; | |
| 1423 """, | |
| 1424 r""" | |
| 1425 int x; | |
| 1426 """, | |
| 1427 ], | |
| 1428 r""" | |
| 1429 } | |
| 1430 | |
| 1431 var instance; | |
| 1432 | |
| 1433 main() { | |
| 1434 if (instance == null) { | |
| 1435 print('[instance] is null'); | |
| 1436 instance = new C(); | |
| 1437 instance.x = 'v1'; | |
| 1438 instance.y = 'v2'; | |
| 1439 } | |
| 1440 try { | |
| 1441 print(instance.x); | |
| 1442 } catch (e) { | |
| 1443 print('[instance.x] threw'); | |
| 1444 } | |
| 1445 try { | |
| 1446 print(instance.y); | |
| 1447 } catch (e) { | |
| 1448 print('[instance.y] threw'); | |
| 1449 } | |
| 1450 } | |
| 1451 """, | |
| 1452 ], | |
| 1453 const <ProgramExpectation>[ | |
| 1454 const ProgramExpectation( | |
| 1455 const <String>['[instance] is null', 'v1', 'v2']), | |
| 1456 const ProgramExpectation( | |
| 1457 const <String>['v1', '[instance.y] threw'], | |
| 1458 // TODO(ahe): Shouldn't throw. | |
| 1459 compileUpdatesShouldThrow: true), | |
| 1460 ]), | |
| 1461 | |
| 1462 const EncodedResult( | |
| 1463 const [ | |
| 1464 r""" | |
| 1465 // Test that a static field can be made an instance field. | |
| 1466 | |
| 1467 class C { | |
| 1468 """, | |
| 1469 | |
| 1470 const [ | |
| 1471 r""" | |
| 1472 static int x; | |
| 1473 """, | |
| 1474 r""" | |
| 1475 int x; | |
| 1476 """, | |
| 1477 ], | |
| 1478 r""" | |
| 1479 } | |
| 1480 | |
| 1481 var instance; | |
| 1482 | |
| 1483 main() { | |
| 1484 if (instance == null) { | |
| 1485 print('[instance] is null'); | |
| 1486 instance = new C(); | |
| 1487 C.x = 'v1'; | |
| 1488 } else { | |
| 1489 instance.x = 'v2'; | |
| 1490 } | |
| 1491 try { | |
| 1492 print(C.x); | |
| 1493 } catch (e) { | |
| 1494 print('[C.x] threw'); | |
| 1495 } | |
| 1496 try { | |
| 1497 print(instance.x); | |
| 1498 } catch (e) { | |
| 1499 print('[instance.x] threw'); | |
| 1500 } | |
| 1501 } | |
| 1502 """, | |
| 1503 ], | |
| 1504 const <ProgramExpectation>[ | |
| 1505 const ProgramExpectation( | |
| 1506 const <String>['[instance] is null', 'v1', '[instance.x] threw']
), | |
| 1507 const ProgramExpectation( | |
| 1508 const <String>['[C.x] threw', 'v2'], | |
| 1509 // TODO(ahe): Shouldn't throw. | |
| 1510 compileUpdatesShouldThrow: true), | |
| 1511 ]), | |
| 1512 | |
| 1513 const EncodedResult( | |
| 1514 const [ | |
| 1515 r""" | |
| 1516 // Test that instance field can be made static. | |
| 1517 | |
| 1518 class C { | |
| 1519 """, | |
| 1520 const [ | |
| 1521 r""" | |
| 1522 int x; | |
| 1523 """, | |
| 1524 r""" | |
| 1525 static int x; | |
| 1526 """, | |
| 1527 ], | |
| 1528 r""" | |
| 1529 } | |
| 1530 | |
| 1531 var instance; | |
| 1532 | |
| 1533 main() { | |
| 1534 if (instance == null) { | |
| 1535 print('[instance] is null'); | |
| 1536 instance = new C(); | |
| 1537 instance.x = 'v1'; | |
| 1538 } else { | |
| 1539 C.x = 'v2'; | |
| 1540 } | |
| 1541 try { | |
| 1542 print(C.x); | |
| 1543 } catch (e) { | |
| 1544 print('[C.x] threw'); | |
| 1545 } | |
| 1546 try { | |
| 1547 print(instance.x); | |
| 1548 } catch (e) { | |
| 1549 print('[instance.x] threw'); | |
| 1550 } | |
| 1551 } | |
| 1552 """, | |
| 1553 ], | |
| 1554 const <ProgramExpectation>[ | |
| 1555 const ProgramExpectation( | |
| 1556 const <String>['[instance] is null', '[C.x] threw', 'v1']), | |
| 1557 const ProgramExpectation( | |
| 1558 const <String>['v2', '[instance.x] threw'], | |
| 1559 // TODO(ahe): Shouldn't throw. | |
| 1560 compileUpdatesShouldThrow: true), | |
| 1561 ]), | |
| 1562 | |
| 1563 const EncodedResult( | |
| 1564 const [ | |
| 1565 r""" | |
| 1566 // Test compound constants. | |
| 1567 | |
| 1568 class A { | |
| 1569 final value; | |
| 1570 const A(this.value); | |
| 1571 | |
| 1572 toString() => 'A($value)'; | |
| 1573 } | |
| 1574 | |
| 1575 class B { | |
| 1576 final value; | |
| 1577 const B(this.value); | |
| 1578 | |
| 1579 toString() => 'B($value)'; | |
| 1580 } | |
| 1581 | |
| 1582 main() { | |
| 1583 """, | |
| 1584 const [ | |
| 1585 r""" | |
| 1586 print(const A('v1')); | |
| 1587 print(const B('v1')); | |
| 1588 """, | |
| 1589 r""" | |
| 1590 print(const B(const A('v2'))); | |
| 1591 print(const A(const B('v2'))); | |
| 1592 """, | |
| 1593 ], | |
| 1594 r""" | |
| 1595 } | |
| 1596 """, | |
| 1597 ], | |
| 1598 const <ProgramExpectation>[ | |
| 1599 const ProgramExpectation( | |
| 1600 const <String>['A(v1)', 'B(v1)']), | |
| 1601 const ProgramExpectation( | |
| 1602 const <String>['B(A(v2))', 'A(B(v2))']), | |
| 1603 ]), | |
| 1604 | |
| 1605 const EncodedResult( | |
| 1606 const [ | |
| 1607 r""" | |
| 1608 // Test constants of new classes. | |
| 1609 | |
| 1610 class A { | |
| 1611 final value; | |
| 1612 const A(this.value); | |
| 1613 | |
| 1614 toString() => 'A($value)'; | |
| 1615 } | |
| 1616 """, | |
| 1617 const [ | |
| 1618 "", | |
| 1619 r""" | |
| 1620 class B { | |
| 1621 final value; | |
| 1622 const B(this.value); | |
| 1623 | |
| 1624 toString() => 'B($value)'; | |
| 1625 } | |
| 1626 | |
| 1627 """, | |
| 1628 ], | |
| 1629 r""" | |
| 1630 main() { | |
| 1631 """, | |
| 1632 | |
| 1633 const [ | |
| 1634 r""" | |
| 1635 print(const A('v1')); | |
| 1636 """, | |
| 1637 r""" | |
| 1638 print(const A('v2')); | |
| 1639 print(const B('v2')); | |
| 1640 print(const B(const A('v2'))); | |
| 1641 print(const A(const B('v2'))); | |
| 1642 """, | |
| 1643 ], | |
| 1644 r""" | |
| 1645 } | |
| 1646 """, | |
| 1647 | |
| 1648 ], | |
| 1649 const <ProgramExpectation>[ | |
| 1650 const ProgramExpectation( | |
| 1651 const <String>['A(v1)']), | |
| 1652 const ProgramExpectation( | |
| 1653 const <String>['A(v2)', 'B(v2)', 'B(A(v2))', 'A(B(v2))']), | |
| 1654 ]), | |
| 1655 | |
| 1656 const EncodedResult( | |
| 1657 r""" | |
| 1658 ==> main.dart <== | |
| 1659 // Test that a change in a part is handled. | |
| 1660 library test.main; | |
| 1661 | |
| 1662 part 'part.dart'; | |
| 1663 | |
| 1664 | |
| 1665 ==> part.dart.patch <== | |
| 1666 part of test.main; | |
| 1667 | |
| 1668 main() { | |
| 1669 <<<<<<< | |
| 1670 print('Hello, World!'); | |
| 1671 ======= | |
| 1672 print('Hello, Brave New World!'); | |
| 1673 >>>>>>> | |
| 1674 } | |
| 1675 """, | |
| 1676 const [ | |
| 1677 'Hello, World!', | |
| 1678 'Hello, Brave New World!', | |
| 1679 ]), | |
| 1680 | |
| 1681 const EncodedResult( | |
| 1682 r""" | |
| 1683 ==> main.dart.patch <== | |
| 1684 // Test that a change in library name is handled. | |
| 1685 <<<<<<< | |
| 1686 library test.main1; | |
| 1687 ======= | |
| 1688 library test.main2; | |
| 1689 >>>>>>> | |
| 1690 | |
| 1691 main() { | |
| 1692 print('Hello, World!'); | |
| 1693 } | |
| 1694 """, | |
| 1695 const [ | |
| 1696 'Hello, World!', | |
| 1697 const ProgramExpectation( | |
| 1698 const <String>['Hello, World!'], | |
| 1699 // TODO(ahe): Shouldn't throw. | |
| 1700 compileUpdatesShouldThrow: true), | |
| 1701 ]), | |
| 1702 | |
| 1703 const EncodedResult( | |
| 1704 r""" | |
| 1705 ==> main.dart.patch <== | |
| 1706 // Test that adding an import is handled. | |
| 1707 <<<<<<< | |
| 1708 ======= | |
| 1709 import 'dart:core'; | |
| 1710 >>>>>>> | |
| 1711 | |
| 1712 main() { | |
| 1713 print('Hello, World!'); | |
| 1714 } | |
| 1715 """, | |
| 1716 const [ | |
| 1717 'Hello, World!', | |
| 1718 const ProgramExpectation( | |
| 1719 const <String>['Hello, World!'], | |
| 1720 // TODO(ahe): Shouldn't throw. | |
| 1721 compileUpdatesShouldThrow: true), | |
| 1722 ]), | |
| 1723 | |
| 1724 const EncodedResult( | |
| 1725 r""" | |
| 1726 ==> main.dart.patch <== | |
| 1727 // Test that adding an export is handled. | |
| 1728 <<<<<<< | |
| 1729 ======= | |
| 1730 export 'dart:core'; | |
| 1731 >>>>>>> | |
| 1732 | |
| 1733 main() { | |
| 1734 print('Hello, World!'); | |
| 1735 } | |
| 1736 """, | |
| 1737 const [ | |
| 1738 'Hello, World!', | |
| 1739 const ProgramExpectation( | |
| 1740 const <String>['Hello, World!'], | |
| 1741 // TODO(ahe): Shouldn't throw. | |
| 1742 compileUpdatesShouldThrow: true), | |
| 1743 ]), | |
| 1744 | |
| 1745 const EncodedResult( | |
| 1746 r""" | |
| 1747 ==> main.dart.patch <== | |
| 1748 // Test that adding a part is handled. | |
| 1749 library test.main; | |
| 1750 | |
| 1751 <<<<<<< | |
| 1752 ======= | |
| 1753 part 'part.dart'; | |
| 1754 >>>>>>> | |
| 1755 | |
| 1756 main() { | |
| 1757 print('Hello, World!'); | |
| 1758 } | |
| 1759 | |
| 1760 | |
| 1761 ==> part.dart <== | |
| 1762 part of test.main | |
| 1763 """, | |
| 1764 const [ | |
| 1765 'Hello, World!', | |
| 1766 const ProgramExpectation( | |
| 1767 const <String>['Hello, World!'], | |
| 1768 // TODO(ahe): Shouldn't throw. | |
| 1769 compileUpdatesShouldThrow: true), | |
| 1770 ]), | |
| 1771 | |
| 1772 const EncodedResult( | |
| 1773 r""" | |
| 1774 ==> main.dart <== | |
| 1775 // Test that changes in multiple libraries is handled. | |
| 1776 import 'library1.dart' as lib1; | |
| 1777 import 'library2.dart' as lib2; | |
| 1778 | |
| 1779 main() { | |
| 1780 lib1.method(); | |
| 1781 lib2.method(); | |
| 1782 } | |
| 1783 | |
| 1784 | |
| 1785 ==> library1.dart.patch <== | |
| 1786 library test.library1; | |
| 1787 | |
| 1788 method() { | |
| 1789 <<<<<<< | |
| 1790 print('lib1.v1'); | |
| 1791 ======= | |
| 1792 print('lib1.v2'); | |
| 1793 ======= | |
| 1794 print('lib1.v3'); | |
| 1795 >>>>>>> | |
| 1796 } | |
| 1797 | |
| 1798 | |
| 1799 ==> library2.dart.patch <== | |
| 1800 library test.library2; | |
| 1801 | |
| 1802 method() { | |
| 1803 <<<<<<< | |
| 1804 print('lib2.v1'); | |
| 1805 ======= | |
| 1806 print('lib2.v2'); | |
| 1807 ======= | |
| 1808 print('lib2.v3'); | |
| 1809 >>>>>>> | |
| 1810 } | |
| 1811 """, | |
| 1812 const [ | |
| 1813 const <String>['lib1.v1', 'lib2.v1'], | |
| 1814 const <String>['lib1.v2', 'lib2.v2'], | |
| 1815 const <String>['lib1.v3', 'lib2.v3'], | |
| 1816 ]), | |
| 1817 ]; | |
| 1818 | |
| 1819 void main() { | |
| 1820 listener.start(); | |
| 1821 | |
| 1822 document.head.append(lineNumberStyle()); | |
| 1823 | |
| 1824 summary = new SpanElement(); | |
| 1825 document.body.append(new HeadingElement.h1() | |
| 1826 ..appendText("Incremental compiler tests") | |
| 1827 ..append(summary)); | |
| 1828 | |
| 1829 String query = window.location.search; | |
| 1830 int skip = 0; | |
| 1831 if (query != null && query.length > 1) { | |
| 1832 query = query.substring(1); | |
| 1833 String skipParameter = Uri.splitQueryString(window.location.search)['skip']; | |
| 1834 if (skipParameter != null) { | |
| 1835 skip = int.parse(skipParameter); | |
| 1836 } | |
| 1837 String verboseParameter = | |
| 1838 Uri.splitQueryString(window.location.search)['verbose']; | |
| 1839 verboseStatus = verboseParameter != null; | |
| 1840 } | |
| 1841 testCount += skip; | |
| 1842 | |
| 1843 return asyncTest(() => Future.forEach(tests.skip(skip), compileAndRun) | |
| 1844 .then(updateSummary)); | |
| 1845 } | |
| 1846 | |
| 1847 SpanElement summary; | |
| 1848 | |
| 1849 int testCount = 1; | |
| 1850 | |
| 1851 bool verboseStatus = false; | |
| 1852 | |
| 1853 void updateSummary(_) { | |
| 1854 summary.text = " (${testCount - 1}/${tests.length})"; | |
| 1855 } | |
| 1856 | |
| 1857 Future compileAndRun(EncodedResult encodedResult) { | |
| 1858 updateSummary(null); | |
| 1859 List<ProgramResult> programs = encodedResult.decode(); | |
| 1860 var status = new DivElement(); | |
| 1861 document.body.append(status); | |
| 1862 | |
| 1863 IFrameElement iframe = | |
| 1864 appendIFrame( | |
| 1865 '/root_dart/tests/try/web/incremental_compilation_update.html', | |
| 1866 document.body) | |
| 1867 ..style.width = '100%' | |
| 1868 ..style.height = '600px'; | |
| 1869 | |
| 1870 return listener.expect('iframe-ready').then((_) { | |
| 1871 ProgramResult program = programs.first; | |
| 1872 | |
| 1873 status.append( | |
| 1874 new HeadingElement.h2() | |
| 1875 ..appendText("Full program #${testCount++}:")); | |
| 1876 status.append(numberedLines(program.code)); | |
| 1877 | |
| 1878 status.style.color = 'orange'; | |
| 1879 WebCompilerTestCase test = new WebCompilerTestCase(program.code); | |
| 1880 return test.run().then((String jsCode) { | |
| 1881 status.style.color = 'red'; | |
| 1882 var objectUrl = | |
| 1883 Url.createObjectUrl(new Blob([jsCode], 'application/javascript')); | |
| 1884 | |
| 1885 iframe.contentWindow.postMessage(['add-script', objectUrl], '*'); | |
| 1886 Future future = | |
| 1887 listener.expect(program.messagesWith('iframe-dart-main-done')); | |
| 1888 return future.then((_) { | |
| 1889 int version = 2; | |
| 1890 return Future.forEach(programs.skip(1), (ProgramResult program) { | |
| 1891 | |
| 1892 status.append(new HeadingElement.h2()..appendText("Update:")); | |
| 1893 status.append(numberedLines(program.code)); | |
| 1894 | |
| 1895 WebInputProvider inputProvider = | |
| 1896 test.incrementalCompiler.inputProvider; | |
| 1897 Uri base = test.scriptUri; | |
| 1898 Map<String, String> code = program.code is String | |
| 1899 ? { 'main.dart': program.code } | |
| 1900 : program.code; | |
| 1901 Map<Uri, Uri> uriMap = <Uri, Uri>{}; | |
| 1902 for (String name in code.keys) { | |
| 1903 Uri uri = base.resolve('$name?v${version++}'); | |
| 1904 inputProvider.cachedSources[uri] = new Future.value(code[name]); | |
| 1905 uriMap[base.resolve(name)] = uri; | |
| 1906 } | |
| 1907 Future future = test.incrementalCompiler.compileUpdates( | |
| 1908 uriMap, logVerbose: logger, logTime: logger); | |
| 1909 bool compileUpdatesThrew = false; | |
| 1910 future = future.catchError((error, trace) { | |
| 1911 String statusMessage; | |
| 1912 Future result; | |
| 1913 compileUpdatesThrew = true; | |
| 1914 if (program.compileUpdatesShouldThrow && | |
| 1915 error is IncrementalCompilationFailed) { | |
| 1916 statusMessage = "Expected error in compileUpdates."; | |
| 1917 result = null; | |
| 1918 } else { | |
| 1919 statusMessage = "Unexpected error in compileUpdates."; | |
| 1920 result = new Future.error(error, trace); | |
| 1921 } | |
| 1922 status.append(new HeadingElement.h3()..appendText(statusMessage)); | |
| 1923 return result; | |
| 1924 }); | |
| 1925 return future.then((String update) { | |
| 1926 if (program.compileUpdatesShouldThrow) { | |
| 1927 Expect.isTrue( | |
| 1928 compileUpdatesThrew, | |
| 1929 "Expected an exception in compileUpdates"); | |
| 1930 Expect.isNull( update, "Expected update == null"); | |
| 1931 return null; | |
| 1932 } | |
| 1933 print({'update': update}); | |
| 1934 iframe.contentWindow.postMessage(['apply-update', update], '*'); | |
| 1935 | |
| 1936 return listener.expect( | |
| 1937 program.messagesWith('iframe-dart-updated-main-done')) | |
| 1938 .then((_) { | |
| 1939 // TODO(ahe): Enable SerializeScopeTestCase for multiple | |
| 1940 // parts. | |
| 1941 if (program.code is! String) return null; | |
| 1942 return new SerializeScopeTestCase( | |
| 1943 program.code, test.incrementalCompiler.mainApp, | |
| 1944 test.incrementalCompiler.compiler).run(); | |
| 1945 }); | |
| 1946 }); | |
| 1947 }); | |
| 1948 }); | |
| 1949 }); | |
| 1950 }).then((_) { | |
| 1951 status.style.color = 'limegreen'; | |
| 1952 | |
| 1953 // Remove the iframe and status to work around a bug in test.dart | |
| 1954 // (https://code.google.com/p/dart/issues/detail?id=21691). | |
| 1955 if (!verboseStatus) status.remove(); | |
| 1956 iframe.remove(); | |
| 1957 }); | |
| 1958 } | |
| 1959 | |
| 1960 class SerializeScopeTestCase extends CompilerTestCase { | |
| 1961 final String scopeInfo; | |
| 1962 | |
| 1963 SerializeScopeTestCase( | |
| 1964 String source, | |
| 1965 LibraryElement library, | |
| 1966 Compiler compiler) | |
| 1967 : scopeInfo = computeScopeInfo(compiler, library), | |
| 1968 super(source, '${library.canonicalUri}'); | |
| 1969 | |
| 1970 Future run() => loadMainApp().then(checkScopes); | |
| 1971 | |
| 1972 void checkScopes(LibraryElement library) { | |
| 1973 Expect.stringEquals(computeScopeInfo(compiler, library), scopeInfo); | |
| 1974 } | |
| 1975 | |
| 1976 static String computeScopeInfo(Compiler compiler, LibraryElement library) { | |
| 1977 ScopeInformationVisitor visitor = | |
| 1978 new ScopeInformationVisitor(compiler, library, 0); | |
| 1979 | |
| 1980 visitor.ignoreImports = true; | |
| 1981 visitor.sortMembers = true; | |
| 1982 visitor.indented.write('[\n'); | |
| 1983 visitor.indentationLevel++; | |
| 1984 visitor.indented; | |
| 1985 library.accept(visitor); | |
| 1986 library.forEachLocalMember((Element member) { | |
| 1987 if (member.isClass) { | |
| 1988 visitor.buffer.write(',\n'); | |
| 1989 visitor.indented; | |
| 1990 member.accept(visitor); | |
| 1991 } | |
| 1992 }); | |
| 1993 visitor.buffer.write('\n'); | |
| 1994 visitor.indentationLevel--; | |
| 1995 visitor.indented.write(']'); | |
| 1996 return '${visitor.buffer}'; | |
| 1997 } | |
| 1998 } | |
| 1999 | |
| 2000 void logger(x) { | |
| 2001 print(x); | |
| 2002 bool isCheckedMode = false; | |
| 2003 assert(isCheckedMode = true); | |
| 2004 int timeout = isCheckedMode ? TIMEOUT * 2 : TIMEOUT; | |
| 2005 if (listener.elapsed > timeout) { | |
| 2006 throw 'Test timed out.'; | |
| 2007 } | |
| 2008 } | |
| 2009 | |
| 2010 DivElement numberedLines(code) { | |
| 2011 if (code is! Map) { | |
| 2012 code = {'main.dart': code}; | |
| 2013 } | |
| 2014 DivElement result = new DivElement(); | |
| 2015 code.forEach((String fileName, String code) { | |
| 2016 result.append(new HeadingElement.h4()..appendText(fileName)); | |
| 2017 DivElement lines = new DivElement(); | |
| 2018 result.append(lines); | |
| 2019 lines.classes.add("output"); | |
| 2020 | |
| 2021 for (String text in splitLines(code)) { | |
| 2022 PreElement line = new PreElement() | |
| 2023 ..appendText(text.trimRight()) | |
| 2024 ..classes.add("line"); | |
| 2025 lines.append(line); | |
| 2026 } | |
| 2027 }); | |
| 2028 return result; | |
| 2029 } | |
| 2030 | |
| 2031 StyleElement lineNumberStyle() { | |
| 2032 StyleElement style = new StyleElement()..appendText(''' | |
| 2033 h2, h3, h4 { | |
| 2034 color: black; | |
| 2035 } | |
| 2036 | |
| 2037 .output { | |
| 2038 padding: 0px; | |
| 2039 counter-reset: line-number; | |
| 2040 padding-bottom: 1em; | |
| 2041 } | |
| 2042 | |
| 2043 .line { | |
| 2044 white-space: pre-wrap; | |
| 2045 padding-left: 3.5em; | |
| 2046 margin-top: 0; | |
| 2047 margin-bottom: 0; | |
| 2048 } | |
| 2049 | |
| 2050 .line::before { | |
| 2051 counter-increment: line-number; | |
| 2052 content: counter(line-number) " "; | |
| 2053 position: absolute; | |
| 2054 left: 0px; | |
| 2055 width: 3em; | |
| 2056 text-align: right; | |
| 2057 background-color: lightgoldenrodyellow; | |
| 2058 } | |
| 2059 '''); | |
| 2060 style.type = 'text/css'; | |
| 2061 return style; | |
| 2062 } | |
| OLD | NEW |