|  | // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | library async_await_test; | 
|  |  | 
|  | import "package:unittest/unittest.dart"; | 
|  | import "dart:async"; | 
|  |  | 
|  | main() { | 
|  | bool checkedMode = false; | 
|  | assert((checkedMode = true)); | 
|  |  | 
|  | group("basic", () { | 
|  | test("async w/o await", () { | 
|  | f() async { return id(42); } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("async waits", () { | 
|  | // Calling an "async" function won't do anything immediately. | 
|  | var result = []; | 
|  | f() async { | 
|  | result.add(1); | 
|  | return id(42); | 
|  | }; | 
|  | var future = f(); | 
|  | result.add(0); | 
|  | return future.whenComplete(() { | 
|  | expect(result, equals([0, 1])); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("async throws", () { | 
|  | f() async { | 
|  | throw "err"; | 
|  | return id(42); | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await future", () { | 
|  | f() async { | 
|  | var v = await new Future.value(42); | 
|  | return v; | 
|  | }; | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await value", () { | 
|  | f() async { | 
|  | var v = await id(42); | 
|  | return v; | 
|  | }; | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await null", () { | 
|  | f() async { | 
|  | var v = await null; | 
|  | expect(v, equals(null)); | 
|  | }; | 
|  | return f(); | 
|  | }); | 
|  |  | 
|  | test("await await", () { | 
|  | f() async { | 
|  | return await await new Future.value(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await fake value future", () { | 
|  | f() async { | 
|  | return await new FakeValueFuture(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await fake error future", () { | 
|  | f() async { | 
|  | return await new FakeErrorFuture("err"); | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await value is delayed", () { | 
|  | f() async { | 
|  | bool x = false; | 
|  | scheduleMicrotask(() { x = true; }); | 
|  | var y = await true; | 
|  | expect(x, equals(y)); | 
|  | } | 
|  | return f(); | 
|  | }); | 
|  |  | 
|  | test("await throw", () { | 
|  | f() async { | 
|  | await (throw "err");  // Check grammar: Are parentheses necessary? | 
|  | return id(42); | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("throw before await", () { | 
|  | f() async { | 
|  | var x = throw "err"; | 
|  | await x;  // Check grammar: Are parentheses necessary? | 
|  | return id(42); | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | if (checkedMode) { | 
|  | test("assert before await", () { | 
|  | f(v) async { | 
|  | assert(v == 87); | 
|  | return await new Future.microtask(() => 42); | 
|  | } | 
|  | return f(42).then((_) { | 
|  | fail("assert didn't throw"); | 
|  | }, onError: (e, s) { | 
|  | expect(e is AssertionError, isTrue); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("assert after await", () { | 
|  | f(v) async { | 
|  | var x = await new Future.microtask(() => 42); | 
|  | assert(v == 87); | 
|  | return x; | 
|  | } | 
|  | return f(42).then((_) { | 
|  | fail("assert didn't throw"); | 
|  | }, onError: (e, s) { | 
|  | expect(e is AssertionError, isTrue); | 
|  | }); | 
|  | }); | 
|  | } | 
|  |  | 
|  | test("async await error", () { | 
|  | f() async { | 
|  | await new Future.error("err"); | 
|  | return id(42); | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("async flattens futures", () { | 
|  | f() async { | 
|  | return new Future.value(42);  // Not awaited. | 
|  | }; | 
|  | return f().then((v) { | 
|  | expect(v, equals(42));  // And not a Future with value 42. | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("async flattens futures, error", () { | 
|  | f() async { | 
|  | return new Future.error("err");  // Not awaited. | 
|  | }; | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await for", () { | 
|  | f(s) async { | 
|  | int i = 0; | 
|  | await for (int v in s) { | 
|  | i += v; | 
|  | } | 
|  | return i; | 
|  | } | 
|  | return f(mkStream()).then((v) { | 
|  | expect(v, equals(45));  // 0 + 1 + ... + 9 | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await for w/ await", () { | 
|  | f(s) async { | 
|  | int i = 0; | 
|  | await for (int v in s) { | 
|  | i += await new Future.value(v); | 
|  | } | 
|  | return i; | 
|  | } | 
|  | return f(mkStream()).then((v) { | 
|  | expect(v, equals(45));  // 0 + 1 + ... + 9 | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await for empty", () { | 
|  | f(s) async { | 
|  | int v = 0; | 
|  | await for (int i in s) { | 
|  | v += i; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | var s = (new StreamController()..close()).stream; | 
|  | return f(s).then((v) { | 
|  | expect(v, equals(0)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | if (checkedMode) { | 
|  | test("await for w/ await, asseert", () { | 
|  | f(s) async { | 
|  | int i = 0; | 
|  | await for (int v in s) { | 
|  | i += await new Future.microtask(() => v); | 
|  | assert(v < 8); | 
|  | } | 
|  | return i; | 
|  | } | 
|  | return f(mkStream()).then((v) { | 
|  | fail("assert didn't throw"); | 
|  | }, onError: (e, s) { | 
|  | expect(e is AssertionError, isTrue); | 
|  | }); | 
|  | }); | 
|  | } | 
|  | }); | 
|  |  | 
|  | group("for", () { | 
|  | test("await in for-loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i++) { | 
|  | v += await new Future.value(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * id(42))); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in for-init", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = await new Future.value(42); i >= 0; i -= 10) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * 5)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in for-test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < await new Future.value(42); i += 10) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * 5)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in for-incr", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 100; i += await new Future.value(42)) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * 3)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in for-loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i++) { | 
|  | v += await new Future.error("err"); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await err in for-init", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = await new Future.error("err"); i >= 0; i -= 10) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await err in for-test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < await new Future.error("err"); i += 10) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await err in for-incr", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 100; i += await new Future.error("err")) { | 
|  | v += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await in empty for-loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i > 0; i += 1) { | 
|  | v += await new Future.value(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(0)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in empty for-loop 2", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i > 0; i += await new Future.value(1)) { | 
|  | v += 1; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(0)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("break before await in for-loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i += 1) { | 
|  | if (i == 2) break; | 
|  | v += await new Future.value(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 2)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("break before await in for-loop 2", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i += await new Future.value(1)) { | 
|  | if (i == 2) break; | 
|  | v += id(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 2)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue before await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i += 1) { | 
|  | if (i == 2) continue; | 
|  | v += await new Future.value(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue after await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | for (int i = 0; i < 10; i += 1) { | 
|  | var j = await new Future.value(42); | 
|  | if (i == 2) continue; | 
|  | v += j; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("while", () { | 
|  | test("await in while-loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | v += await new Future.value(42); | 
|  | i++; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * id(42))); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in while-test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < await new Future.value(42)) { | 
|  | v += 10; | 
|  | i += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * 5)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | v += await new Future.error("err"); | 
|  | i++; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("await err in test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < await new Future.error("err")) { | 
|  | v += 10; | 
|  | i += 10; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return throwsErr(f()); | 
|  | }); | 
|  |  | 
|  | test("break before await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | if (i == 2) break; | 
|  | v += await new Future.value(42); | 
|  | i += 1; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 2)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("break after await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | v += await new Future.value(42); | 
|  | if (i == 2) break; | 
|  | i += 1; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 3)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue before await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | i += 1; | 
|  | if (i == 2) continue; | 
|  | v += await new Future.value(42); | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue after await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | while (i < 10) { | 
|  | i += 1; | 
|  | int j = await new Future.value(42); | 
|  | if (i == 2) continue; | 
|  | v += j; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("do-while", () { | 
|  | test("await in loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | v += await new Future.value(42); | 
|  | i++; | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * id(42))); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | v += 10; | 
|  | i += 10; | 
|  | } while (i < await new Future.value(42)); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10 * 5)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in loop", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | v += await new Future.error("err"); | 
|  | i++; | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("await err in test", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | v += 10; | 
|  | i += 10; | 
|  | } while (i < await new Future.error("err")); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("break before await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | if (i == 2) break; | 
|  | v += await new Future.value(42); | 
|  | i += 1; | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 2)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("break after await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | v += await new Future.value(42); | 
|  | if (i == 2) break; | 
|  | i += 1; | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 3)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue before await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | i += 1; | 
|  | if (i == 2) continue; | 
|  | v += await new Future.value(42); | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("continue after await", () { | 
|  | f() async { | 
|  | int v = 0; | 
|  | int i = 0; | 
|  | do { | 
|  | i += 1; | 
|  | int j = await new Future.value(42); | 
|  | if (i == 2) continue; | 
|  | v += j; | 
|  | } while (i < 10); | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42 * 9)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("for-in", () { | 
|  | test("await in for-in", () { | 
|  | f() async { | 
|  | var v = 0; | 
|  | for (var fut in [1, 2, 3].map((v) => new Future.value(v))) { | 
|  | v += await fut; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(6)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await in for-in iterable", () { | 
|  | f() async { | 
|  | var v = 0; | 
|  | for (var i in await new Future.value([1, 2, 3])) { | 
|  | v += i; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(6)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in for-in", () { | 
|  | f() async { | 
|  | var v = 0; | 
|  | for (var fut in [1, 2, 3].map((v) => (v != 1) | 
|  | ? new Future.value(v) | 
|  | : new Future.error("err"))) { | 
|  | v += await fut; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("await err in for-in iterable", () { | 
|  | f() async { | 
|  | var v = 0; | 
|  | for (var i in await new Future.error("err")) { | 
|  | v += i; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("break before await in for-in", () { | 
|  | f() async { | 
|  | var v = 0; | 
|  | for (var fut in [1, 2, 3].map((v) => new Future.value(v))) { | 
|  | if (v == 3) break; | 
|  | v += await fut; | 
|  | } | 
|  | return v; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(3)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("try-catch", () { | 
|  | test("try-no-catch", () { | 
|  | f() async { | 
|  | try { | 
|  | return await id(42); | 
|  | } catch(e) { | 
|  | return 37; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in body", () { | 
|  | f() async { | 
|  | try { | 
|  | await new Future.error(42); | 
|  | } catch(e) { | 
|  | return e; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("throw before await in body", () { | 
|  | int i = id(0); | 
|  | f() async { | 
|  | try { | 
|  | if (i >= 0) throw id(42); | 
|  | return await new Future.value(10); | 
|  | } catch(e) { | 
|  | return e; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("try-catch await in catch", () { | 
|  | f() async { | 
|  | try { | 
|  | throw id(42); | 
|  | } catch(e) { | 
|  | return await new Future.value(e); | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("try-catch await error in catch", () { | 
|  | f() async { | 
|  | try { | 
|  | throw id(42); | 
|  | } catch(e) { | 
|  | await new Future.error("err"); | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("try-catch-rethrow", () { | 
|  | f() async { | 
|  | try { | 
|  | await new Future.error("err"); | 
|  | } catch(e) { | 
|  | if (e == id(42)) return; | 
|  | rethrow; | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("try-finally", () { | 
|  | test("await in body", () { | 
|  | f() async { | 
|  | try { | 
|  | return await new Future.value(42); | 
|  | } finally { | 
|  | // Don't do anything. | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in finally", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | try { | 
|  | return id(42); | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | } | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(37)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in body", () { | 
|  | f() async { | 
|  | try { | 
|  | return await new Future.error("err"); | 
|  | } finally { | 
|  | // Don't do anything. | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("await err in finally", () { | 
|  | f() async { | 
|  | try { | 
|  | return id(42); | 
|  | } finally { | 
|  | await new Future.error("err"); | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("await err in both", () { | 
|  | f() async { | 
|  | try { | 
|  | await new Future.error("not err"); | 
|  | } finally { | 
|  | await new Future.error("err"); | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | }); | 
|  |  | 
|  | test("await err in body, override in finally", () { | 
|  | f() async { | 
|  | try { | 
|  | return await new Future.error("err"); | 
|  | } finally { | 
|  | return id(42); | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in body, override in finally", () { | 
|  | f() async { | 
|  | label: try { | 
|  | return await new Future.value(37); | 
|  | } finally { | 
|  | break label; | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await, override in finally", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | label: try { | 
|  | return 87; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | break label; | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(37)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("throw in body, await, override in finally 3", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | label: try { | 
|  | throw "err"; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | break label; | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(37)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("await err in body, override in finally 2", () { | 
|  | f() async { | 
|  | label: try { | 
|  | return await new Future.error("err"); | 
|  | } finally { | 
|  | break label; | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in body, no-exit in finally", () { | 
|  | f() async { | 
|  | for (int i = 0; i < 10; i++) { | 
|  | try { | 
|  | return await i; | 
|  | } finally { | 
|  | continue; | 
|  | } | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("no-exit after await in finally", () { | 
|  | f() async { | 
|  | int i = 0; | 
|  | for (; i < 10; i++) { | 
|  | try { | 
|  | break; | 
|  | } finally { | 
|  | await new Future.value(42); | 
|  | continue; | 
|  | } | 
|  | } | 
|  | return id(i); | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(10)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("exit after continue, await in finally", () { | 
|  | f() async { | 
|  | int i = 0; | 
|  | for (; i < 10; i++) { | 
|  | try { | 
|  | continue; | 
|  | } finally { | 
|  | await new Future.value(42); | 
|  | break; | 
|  | } | 
|  | } | 
|  | return id(i); | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(0)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("no-exit before await in finally 2", () { | 
|  | f() async { | 
|  | for (int i = 0; i < 10; i++) { | 
|  | try { | 
|  | return i; | 
|  | } finally { | 
|  | if (i >= 0) continue; | 
|  | await new Future.value(42); | 
|  | } | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("no-exit after await in finally", () { | 
|  | f() async { | 
|  | for (int i = 0; i < 10; i++) { | 
|  | try { | 
|  | return i; | 
|  | } finally { | 
|  | await new Future.value(42); | 
|  | continue; | 
|  | } | 
|  | } | 
|  | return id(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("nested finallies", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | try { | 
|  | try { | 
|  | return 42; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | } | 
|  | } finally { | 
|  | x += await new Future.value(37); | 
|  | } | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(74)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("nested finallies 2", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | label: try { | 
|  | try { | 
|  | break label; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | } | 
|  | } finally { | 
|  | x += await new Future.value(37); | 
|  | } | 
|  | return 42; | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(74)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test("nested finallies 3", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | label: try { | 
|  | try { | 
|  | break label; | 
|  | } finally { | 
|  | return await new Future.value(42); | 
|  | } | 
|  | } finally { | 
|  | break label; | 
|  | } | 
|  | return 42; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("nested finallies, throw", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | try { | 
|  | try { | 
|  | throw "err"; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | } | 
|  | } finally { | 
|  | x += await new Future.value(37); | 
|  | } | 
|  | } | 
|  | return f().then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { | 
|  | expect(e, equals("err")); | 
|  | expect(x, equals(2 * 37)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("try-catch-finally", () { | 
|  | test("await in body", () { | 
|  | f() async { | 
|  | try { | 
|  | return await new Future.value(42); | 
|  | } catch (e) { | 
|  | throw null; | 
|  | } finally { | 
|  | if (id(42) == id(10)) return 10; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in catch, not hit", () { | 
|  | f() async { | 
|  | try { | 
|  | return id(42); | 
|  | } catch (e) { | 
|  | await new Future.error("err"); | 
|  | } finally { | 
|  | if (id(42) == id(10)) return 10; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in catch, hit", () { | 
|  | f() async { | 
|  | try { | 
|  | return throw id(42); | 
|  | } catch (e) { | 
|  | return await new Future.value(e); | 
|  | } finally { | 
|  | if (id(42) == id(10)) return 10; | 
|  | } | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("await in finally", () { | 
|  | var x = 0; | 
|  | f() async { | 
|  | try { | 
|  | return id(42); | 
|  | } catch (e) { | 
|  | throw null; | 
|  | } finally { | 
|  | x = await new Future.value(37); | 
|  | if (id(42) == id(10)) return 10; | 
|  | } | 
|  | } | 
|  | return f().then((v) { | 
|  | expect(v, equals(42)); | 
|  | expect(x, equals(37)); | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("switch", () { | 
|  | test("await in expression", () { | 
|  | f(v) async { | 
|  | switch (await new Future.value(v)) { | 
|  | case 1: return 1; | 
|  | case 2: return 42; | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return expect42(f(2)); | 
|  | }); | 
|  |  | 
|  | test("await err in expression", () { | 
|  | f(v) async { | 
|  | switch (await new Future.error("err")) { | 
|  | case 1: return 1; | 
|  | case 2: return 42; | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return throwsErr(f(2)); | 
|  | }); | 
|  |  | 
|  | test("await in case", () { | 
|  | f(v) async { | 
|  | switch (v) { | 
|  | case 1: return 1; | 
|  | case 2: return await new Future.value(42); | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return expect42(f(2)); | 
|  | }); | 
|  |  | 
|  | test("await err in case", () { | 
|  | f(v) async { | 
|  | switch (v) { | 
|  | case 1: return 1; | 
|  | case 2: return await new Future.error("err"); | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return throwsErr(f(2)); | 
|  | }); | 
|  |  | 
|  | test("continue before await in case", () { | 
|  | f(v) async { | 
|  | switch (v) { | 
|  | label: | 
|  | case 1: return 42; | 
|  | case 2: | 
|  | if (v <= 2) continue label; | 
|  | return await new Future.value(10); | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return expect42(f(2)); | 
|  | }); | 
|  |  | 
|  | test("continue after await in case", () { | 
|  | f(v) async { | 
|  | switch (v) { | 
|  | label: | 
|  | case 1: return 42; | 
|  | case 2: | 
|  | await new Future.value(10); | 
|  | continue label; | 
|  | default: return 3; | 
|  | } | 
|  | return null; | 
|  | } | 
|  | return expect42(f(2)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("if", () { | 
|  | test("await in test", () { | 
|  | f(v) async { | 
|  | if (await new Future.value(v)) { | 
|  | return 42; | 
|  | } else { | 
|  | return 37; | 
|  | } | 
|  | } | 
|  | return expect42(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await err in test", () { | 
|  | f(v) async { | 
|  | if (await new Future.error("err")) { | 
|  | return 42; | 
|  | } else { | 
|  | return 37; | 
|  | } | 
|  | } | 
|  | return throwsErr(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await in then", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return await new Future.value(42); | 
|  | } | 
|  | return 37; | 
|  | } | 
|  | return expect42(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await err in then", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return await new Future.error("err"); | 
|  | } | 
|  | return 37; | 
|  | } | 
|  | return throwsErr(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await in then with else", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return await new Future.value(42); | 
|  | } else { | 
|  | return 87; | 
|  | } | 
|  | return 37; | 
|  | } | 
|  | return expect42(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await err in then with else", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return await new Future.error("err"); | 
|  | } else { | 
|  | return 87; | 
|  | } | 
|  | return 37; | 
|  | } | 
|  | return throwsErr(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await in else", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return 37; | 
|  | } else { | 
|  | return await new Future.value(42); | 
|  | } | 
|  | return 87; | 
|  | } | 
|  | return expect42(f(false)); | 
|  | }); | 
|  |  | 
|  | test("await err in else", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return 37; | 
|  | } else { | 
|  | return await new Future.error("err"); | 
|  | } | 
|  | return 87; | 
|  | } | 
|  | return throwsErr(f(false)); | 
|  | }); | 
|  |  | 
|  | test("await in else-if test", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return 37; | 
|  | } else if (!await new Future.value(v)) { | 
|  | return 42; | 
|  | } else { | 
|  | return 37; | 
|  | } | 
|  | return 87; | 
|  | } | 
|  | return expect42(f(false)); | 
|  | }); | 
|  |  | 
|  | test("await in else-if then", () { | 
|  | f(v) async { | 
|  | if (v) { | 
|  | return 37; | 
|  | } else if (!v) { | 
|  | return await new Future.value(42); | 
|  | } else { | 
|  | return 37; | 
|  | } | 
|  | return 87; | 
|  | } | 
|  | return expect42(f(false)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("conditional operator", () { | 
|  | test("await in test", () { | 
|  | f(v) async { | 
|  | return (await new Future.value(v)) ? 42 : 37; | 
|  | } | 
|  | return expect42(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await err in test", () { | 
|  | f(v) async { | 
|  | return (await new Future.error("err")) ? 42 : 37; | 
|  | } | 
|  | return throwsErr(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await in then", () { | 
|  | f(v) async { | 
|  | return v ? (await new Future.value(42)) : 37; | 
|  | } | 
|  | return expect42(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await err in then", () { | 
|  | f(v) async { | 
|  | return v ? (await new Future.error("err")) : 37; | 
|  | } | 
|  | return throwsErr(f(true)); | 
|  | }); | 
|  |  | 
|  | test("await in else", () { | 
|  | f(v) async { | 
|  | return v ? 37 : (await new Future.value(42)); | 
|  | } | 
|  | return expect42(f(false)); | 
|  | }); | 
|  |  | 
|  | test("await err in else", () { | 
|  | f(v) async { | 
|  | return v ? 37 : (await new Future.error("err")); | 
|  | } | 
|  | return throwsErr(f(false)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("async declarations", () { | 
|  | var f42 = new Future.value(42); | 
|  |  | 
|  | // Top-level declarations or local declarations in top-level functions. | 
|  | test("topMethod", () { | 
|  | return expect42(topMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("topArrowMethod", () { | 
|  | return expect42(topArrowMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("topGetter", () { | 
|  | return expect42(topGetter); | 
|  | }); | 
|  |  | 
|  | test("topArrowGetter", () { | 
|  | return expect42(topArrowGetter); | 
|  | }); | 
|  |  | 
|  | test("topLocal", () { | 
|  | return expect42(topLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("topArrowLocal", () { | 
|  | return expect42(topArrowLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("topExpression", () { | 
|  | return expect42(topExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("topArrowExpression", () { | 
|  | return expect42(topArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("topVarExpression", () { | 
|  | return expect42(topVarExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("topVarArrowExpression", () { | 
|  | return expect42(topVarArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | // Static declarations or local declarations in static functions. | 
|  | test("staticMethod", () { | 
|  | return expect42(Async.staticMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticArrowMethod", () { | 
|  | return expect42(Async.staticArrowMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticGetter", () { | 
|  | return expect42(Async.staticGetter); | 
|  | }); | 
|  |  | 
|  | test("staticArrowGetter", () { | 
|  | return expect42(Async.staticArrowGetter); | 
|  | }); | 
|  |  | 
|  | test("staticLocal", () { | 
|  | return expect42(Async.staticLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticArrowLocal", () { | 
|  | return expect42(Async.staticArrowLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticExpression", () { | 
|  | return expect42(Async.staticExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticArrowExpression", () { | 
|  | return expect42(Async.staticArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticVarExpression", () { | 
|  | return expect42(Async.staticVarExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("staticVarArrowExpression", () { | 
|  | return expect42(Async.staticVarArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | // Instance declarations or local declarations in instance functions. | 
|  | var async = new Async(); | 
|  |  | 
|  | test("instanceMethod", () { | 
|  | return expect42(async.instanceMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceArrowMethod", () { | 
|  | return expect42(async.instanceArrowMethod(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceGetter", () { | 
|  | return expect42(async.instanceGetter); | 
|  | }); | 
|  |  | 
|  | test("instanceArrowGetter", () { | 
|  | return expect42(async.instanceArrowGetter); | 
|  | }); | 
|  |  | 
|  | test("instanceLocal", () { | 
|  | return expect42(async.instanceLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceArrowLocal", () { | 
|  | return expect42(async.instanceArrowLocal(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceExpression", () { | 
|  | return expect42(async.instanceExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceArrowExpression", () { | 
|  | return expect42(async.instanceArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceVarExpression", () { | 
|  | return expect42(async.instanceVarExpression(f42)); | 
|  | }); | 
|  |  | 
|  | test("instanceVarArrowExpression", () { | 
|  | return expect42(async.instanceVarArrowExpression(f42)); | 
|  | }); | 
|  |  | 
|  | // Local functions in constructor initializer list. | 
|  | test("initializerExpression", () { | 
|  | var async = new Async.initializer(f42); | 
|  | return expect42(async.initValue); | 
|  | }); | 
|  |  | 
|  | test("initializerArrowExpression", () { | 
|  | var async = new Async.initializerArrow(f42); | 
|  | return expect42(async.initValue); | 
|  | }); | 
|  |  | 
|  | test("async in async", () { | 
|  | return expect42(asyncInAsync(f42)); | 
|  | }); | 
|  |  | 
|  | test("sync in async", () { | 
|  | return expect42(syncInAsync(f42)); | 
|  | }); | 
|  |  | 
|  | test("async in sync", () { | 
|  | return expect42(asyncInSync(f42)); | 
|  | }); | 
|  |  | 
|  | // Equality and identity. | 
|  | test("Identical and equals", () { | 
|  | expect(async.instanceMethod, equals(async.instanceMethod)); | 
|  | expect(Async.staticMethod, same(Async.staticMethod)); | 
|  | expect(topMethod, same(topMethod)); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group("await expression", () { | 
|  | const c42 = 42; | 
|  | final v42 = 42; | 
|  |  | 
|  | test("local variable", () { | 
|  | var l42 = 42; | 
|  | f() async { | 
|  | return await l42; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("parameter", () { | 
|  | f(p) async { | 
|  | return await p; | 
|  | } | 
|  | return expect42(f(42)); | 
|  | }); | 
|  |  | 
|  | test("final local variable", () { | 
|  | f() async { | 
|  | return await v42; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("const local variable", () { | 
|  | f() async { | 
|  | return await c42; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("unary prefix operator", () { | 
|  | f() async { | 
|  | return -await -42; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("suffix operator", () { | 
|  | f() async { | 
|  | var v = [42]; | 
|  | return await v[0]; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("unary postfix operator", () { | 
|  | f() async { | 
|  | var x = 42; | 
|  | return await x++; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("suffix operator + increment", () { | 
|  | f() async { | 
|  | var v = [42]; | 
|  | return await v[0]++; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("suffix operator + increment 2", () { | 
|  | f() async { | 
|  | var v = [42]; | 
|  | return await v[await 0]++; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("unary pre-increment operator", () { | 
|  | f() async { | 
|  | var x = 41; | 
|  | return await ++x; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("suffix operator + pre-increment", () { | 
|  | f() async { | 
|  | var v = [41]; | 
|  | return await ++v[0]; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("assignment operator", () { | 
|  | f() async { | 
|  | var x = 37; | 
|  | return await (x = 42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("assignment-op operator", () { | 
|  | f() async { | 
|  | var x = 37; | 
|  | return await (x += 5); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("binary operator", () { | 
|  | f() async { | 
|  | return await (10 + 11) + await (10 + 11); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("ternary operator", () { | 
|  | f(v) async { | 
|  | return await ((v == 10) ? new Future.value(42) : 37); | 
|  | } | 
|  | return expect42(f(10)); | 
|  | }); | 
|  |  | 
|  | test("top-level function call", () { | 
|  | f() async { | 
|  | return await topMethod(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("static function call", () { | 
|  | f() async { | 
|  | return await Async.staticMethod(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("instance function call", () { | 
|  | f() async { | 
|  | var a = new Async(); | 
|  | return await a.instanceMethod(42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("top-level function call w/ await", () { | 
|  | f() async { | 
|  | return await topMethod(await 42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("static function call w/ await", () { | 
|  | f() async { | 
|  | return await Async.staticMethod(await 42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("instance function call w/ await", () { | 
|  | f() async { | 
|  | var a = new Async(); | 
|  | return await a.instanceMethod(await 42); | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("top-level getter call", () { | 
|  | f() async { | 
|  | return await topGetter; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("static getter call", () { | 
|  | f() async { | 
|  | return await Async.staticGetter; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | test("top-level getter call", () { | 
|  | f() async { | 
|  | var a = new Async(); | 
|  | return await a.instanceGetter; | 
|  | } | 
|  | return expect42(f()); | 
|  | }); | 
|  |  | 
|  | if (!checkedMode) return; | 
|  |  | 
|  | test("inside assert, true", () {                       /// 03: ok | 
|  | f() async {                                          /// 03: continued | 
|  | assert(await new Future.microtask(() => true));    /// 03: continued | 
|  | return 42;                                         /// 03: continued | 
|  | }                                                    /// 03: continued | 
|  | return expect42(f());                                /// 03: continued | 
|  | });                                                    /// 03: continued | 
|  |  | 
|  | test("inside assert, false", () {                      /// 03: continued | 
|  | f() async {                                          /// 03: continued | 
|  | assert(await new Future.microtask(() => false));   /// 03: continued | 
|  | return 42;                                         /// 03: continued | 
|  | }                                                    /// 03: continued | 
|  | return f().then((_) {                                /// 03: continued | 
|  | fail("assert didn't throw");                       /// 03: continued | 
|  | }, onError: (e, s) {                                 /// 03: continued | 
|  | expect(e is AssertionError, isTrue);               /// 03: continued | 
|  | });                                                  /// 03: continued | 
|  | });                                                    /// 03: continued | 
|  |  | 
|  | test("inside assert, function -> false", () {          /// 03: continued | 
|  | f() async {                                          /// 03: continued | 
|  | assert(await new Future.microtask(() => false));   /// 03: continued | 
|  | return 42;                                         /// 03: continued | 
|  | }                                                    /// 03: continued | 
|  | return f().then((_) {                                /// 03: continued | 
|  | fail("assert didn't throw");                       /// 03: continued | 
|  | }, onError: (e, s) {                                 /// 03: continued | 
|  | expect(e is AssertionError, isTrue);               /// 03: continued | 
|  | });                                                  /// 03: continued | 
|  | });                                                    /// 03: continued | 
|  |  | 
|  | }); | 
|  |  | 
|  | group("syntax", () { | 
|  | test("async as variable", () { | 
|  | // Valid identifiers outside of async function. | 
|  | var async = 42; | 
|  | expect(async, equals(42)); | 
|  | }); | 
|  |  | 
|  | test("await as variable", () {                         /// 02: ok | 
|  | // Valid identifiers outside of async function.      /// 02: continued | 
|  | var await = 42;                                      /// 02: continued | 
|  | expect(await, equals(42));                           /// 02: continued | 
|  | });                                                    /// 02: continued | 
|  |  | 
|  | test("yield as variable", () { | 
|  | // Valid identifiers outside of async function. | 
|  | var yield = 42; | 
|  | expect(yield, equals(42)); | 
|  | }); | 
|  | }); | 
|  | } | 
|  |  | 
|  |  | 
|  | // Attempt to obfuscates value to avoid too much constant folding. | 
|  | id(v) { | 
|  | try { | 
|  | if (v != null) throw v; | 
|  | } catch (e) { | 
|  | return e; | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  | // Create a stream for testing "async for-in". | 
|  | Stream mkStream() { | 
|  | var c; | 
|  | int i = 0; | 
|  | next() { | 
|  | c.add(i++); | 
|  | if (i == 10) { | 
|  | c.close(); | 
|  | } else { | 
|  | scheduleMicrotask(next); | 
|  | } | 
|  | } | 
|  | c = new StreamController(onListen: () { | 
|  | scheduleMicrotask(next); | 
|  | }); | 
|  | return c.stream; | 
|  | } | 
|  |  | 
|  | // Check that future contains the error "err". | 
|  | Future throwsErr(Future future) { | 
|  | return future.then((v) { fail("didn't throw"); }, | 
|  | onError: (e) { expect(e, equals("err")); }); | 
|  | } | 
|  |  | 
|  | // Check that future contains the value 42. | 
|  | Future expect42(Future future) { | 
|  | return future.then((v) { | 
|  | expect(v, equals(42)); | 
|  | }); | 
|  | } | 
|  |  | 
|  |  | 
|  | // Various async declarations. | 
|  |  | 
|  | Future topMethod(f) async { return await f; } | 
|  |  | 
|  | Future topArrowMethod(f) async => await f; | 
|  |  | 
|  | Future get topGetter async { | 
|  | return await new Future.value(42); | 
|  | } | 
|  |  | 
|  | Future get topArrowGetter async => await new Future.value(42); | 
|  |  | 
|  | Future topLocal(f) { | 
|  | local() async { return await f; } | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | Future topArrowLocal(f) { | 
|  | local() async => await f; | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | Future topExpression(f) { | 
|  | return () async { return await f; } (); | 
|  | } | 
|  |  | 
|  | Future topArrowExpression(f) { | 
|  | return (() async => await f) (); | 
|  | } | 
|  |  | 
|  | var topVarExpression = (f) async { return await f; }; | 
|  |  | 
|  | var topVarArrowExpression = (f) async => await f; | 
|  |  | 
|  | class Async { | 
|  | var initValue; | 
|  | Async(); | 
|  |  | 
|  | Async.initializer(f) : initValue = (() async { return await f; } ()); | 
|  |  | 
|  | Async.initializerArrow(f) : initValue = ((() async => await f) ()); | 
|  |  | 
|  | /* static */ | 
|  | static Future staticMethod(f) async { return await f; } | 
|  |  | 
|  | static Future staticArrowMethod(f) async => await f; | 
|  |  | 
|  | static Future get staticGetter async { | 
|  | return await new Future.value(42); | 
|  | } | 
|  |  | 
|  | static Future get staticArrowGetter async => await new Future.value(42); | 
|  |  | 
|  | static Future staticLocal(f) { | 
|  | local() async { return await f; } | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | static Future staticArrowLocal(f) { | 
|  | local() async => await f; | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | static Future staticExpression(f) { | 
|  | return () async { return await f; } (); | 
|  | } | 
|  |  | 
|  | static Future staticArrowExpression(f) { | 
|  | return (() async => await f) (); | 
|  | } | 
|  |  | 
|  | static var staticVarExpression = (f) async { return await f; }; | 
|  |  | 
|  | static var staticVarArrowExpression = (f) async => await f; | 
|  |  | 
|  | /* instance */ | 
|  | Future instanceMethod(f) async { return await f; } | 
|  |  | 
|  | Future instanceArrowMethod(f) async => await f; | 
|  |  | 
|  | Future get instanceGetter async { | 
|  | return await new Future.value(42); | 
|  | } | 
|  |  | 
|  | Future get instanceArrowGetter async => await new Future.value(42); | 
|  |  | 
|  | Future instanceLocal(f) { | 
|  | local() async { return await f; } | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | Future instanceArrowLocal(f) { | 
|  | local() async => await f; | 
|  | return local(); | 
|  | } | 
|  |  | 
|  | Future instanceExpression(f) { | 
|  | return () async { return await f; } (); | 
|  | } | 
|  |  | 
|  | Future instanceArrowExpression(f) { | 
|  | return (() async => await f) (); | 
|  | } | 
|  |  | 
|  | var instanceVarExpression = (f) async { return await f; }; | 
|  |  | 
|  | var instanceVarArrowExpression = (f) async => await f; | 
|  | } | 
|  |  | 
|  | Future asyncInAsync(f) async { | 
|  | inner(f) async { | 
|  | return await f; | 
|  | } | 
|  | return await inner(f); | 
|  | } | 
|  |  | 
|  | Future asyncInSync(f) { | 
|  | inner(f) async { | 
|  | return await f; | 
|  | } | 
|  | return inner(f); | 
|  | } | 
|  |  | 
|  | Future syncInAsync(f) async { | 
|  | inner(f) { | 
|  | return f; | 
|  | } | 
|  | return await inner(f); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * A non-standard implementation of Future with a value. | 
|  | */ | 
|  | class FakeValueFuture implements Future { | 
|  | final _value; | 
|  | FakeValueFuture(this._value); | 
|  | Future then(callback(value), {Function onError}) { | 
|  | return new Future.microtask(() => callback(_value)); | 
|  | } | 
|  | Future whenComplete(callback()) { | 
|  | return new Future.microtask(() { callback(); }); | 
|  | } | 
|  | Future catchError(Function onError, {bool test(error)}) => this; | 
|  | Stream asStream() => (new StreamController()..add(_value)..close()).stream; | 
|  | Future timeout(Duration duration, {onTimeout}) => this; | 
|  | } | 
|  |  | 
|  | typedef BinaryFunction(a, b); | 
|  |  | 
|  | /** | 
|  | * A non-standard implementation of Future with an error. | 
|  | */ | 
|  | class FakeErrorFuture implements Future { | 
|  | final _error; | 
|  | FakeErrorFuture(this._error); | 
|  | Future then(callback(value), {Function onError}) { | 
|  | if (onError != null) { | 
|  | if (onError is BinaryFunction) { | 
|  | return new Future.microtask(() => onError(_error, null)); | 
|  | } | 
|  | return new Future.microtask(() => onError(_error)); | 
|  | } | 
|  | return this; | 
|  | } | 
|  | Future whenComplete(callback()) { | 
|  | return new Future.microtask(() { callback(); }).then((_) => this); | 
|  | } | 
|  | Future catchError(Function onError, {bool test(error)}) { | 
|  | return new Future.microtask(() { | 
|  | if (test != null && !test(_error)) return this; | 
|  | if (onError is BinaryFunction) { | 
|  | return onError(_error, null); | 
|  | } | 
|  | return onError(_error); | 
|  | }); | 
|  | } | 
|  | Stream asStream() => | 
|  | (new StreamController()..addError(_error)..close()).stream; | 
|  | Future timeout(Duration duration, {onTimeout}) => this; | 
|  | } |