OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 // Test that async functions don't zone-register their callbacks for each |
| 6 // await. Async functions should register their callback once in the beginning |
| 7 // and then reuse it for all awaits in their body. |
| 8 // This has two advantages: it is faster, when there are several awaits (on |
| 9 // the Future class from dart:async), and it avoids zone-nesting when tracing |
| 10 // stacktraces. |
| 11 // See http://dartbug.com/23394 for more information. |
| 12 |
| 13 import 'dart:async'; |
| 14 import 'package:expect/expect.dart'; |
| 15 import 'package:async_helper/async_helper.dart'; |
| 16 |
| 17 gee(i) async { |
| 18 return await i; |
| 19 } |
| 20 |
| 21 bar() async* { |
| 22 var i = 0; |
| 23 while (true) yield await gee(i++); |
| 24 } |
| 25 |
| 26 |
| 27 awaitForTest() async { |
| 28 var sum = 0; |
| 29 await for (var x in bar().take(100)) { |
| 30 sum += x; |
| 31 } |
| 32 Expect.equals(4950, sum); |
| 33 } |
| 34 |
| 35 awaitTest() async { |
| 36 await null; |
| 37 await null; |
| 38 await null; |
| 39 await null; |
| 40 await null; |
| 41 await null; |
| 42 await null; |
| 43 await null; |
| 44 await null; |
| 45 await null; |
| 46 await null; |
| 47 await null; |
| 48 await null; |
| 49 await null; |
| 50 await null; |
| 51 await null; |
| 52 await null; |
| 53 await null; |
| 54 await null; |
| 55 await null; |
| 56 await null; |
| 57 await null; |
| 58 await null; |
| 59 await null; |
| 60 await null; |
| 61 await null; |
| 62 await null; |
| 63 await null; |
| 64 await null; |
| 65 await null; |
| 66 await null; |
| 67 await null; |
| 68 await null; |
| 69 await null; |
| 70 await null; |
| 71 await null; |
| 72 await null; |
| 73 await null; |
| 74 await null; |
| 75 await null; |
| 76 return await 499; |
| 77 } |
| 78 |
| 79 runTests() async { |
| 80 await awaitTest(); |
| 81 await awaitForTest(); |
| 82 } |
| 83 |
| 84 var depth = 0; |
| 85 |
| 86 var depthIncreases = 0; |
| 87 |
| 88 increaseDepth() { |
| 89 depthIncreases++; |
| 90 depth++; |
| 91 // The async/await code should not register callbacks recursively in the |
| 92 // then-calls. As such the depth should never grow too much. We don't want |
| 93 // to commit to a specific value, since implementations still have some |
| 94 // room in how async/await is implemented, but 20 should be safe. |
| 95 Expect.isTrue(depth < 20); |
| 96 } |
| 97 |
| 98 registerCallback(Zone self, ZoneDelegate parent, Zone zone, f) { |
| 99 var oldDepth = depth; |
| 100 increaseDepth(); |
| 101 return parent.registerCallback(zone, () { |
| 102 depth = oldDepth; |
| 103 return f(); |
| 104 }); |
| 105 } |
| 106 registerUnaryCallback(Zone self, ZoneDelegate parent, Zone zone, f) { |
| 107 var oldDepth = depth; |
| 108 increaseDepth(); |
| 109 return parent.registerUnaryCallback(zone, (x) { |
| 110 depth = oldDepth; |
| 111 return f(x); |
| 112 }); |
| 113 } |
| 114 registerBinaryCallback(Zone self, ZoneDelegate parent, Zone zone, f) { |
| 115 var oldDepth = depth; |
| 116 increaseDepth(); |
| 117 return parent.registerBinaryCallback(zone, (x, y) { |
| 118 depth = oldDepth; |
| 119 return f(x, y); |
| 120 }); |
| 121 } |
| 122 |
| 123 sm(Zone self, ZoneDelegate parent, Zone zone, f) { |
| 124 var oldDepth = depth; |
| 125 increaseDepth(); |
| 126 return parent.scheduleMicrotask(zone, () { |
| 127 depth = oldDepth; |
| 128 return f(); |
| 129 }); |
| 130 } |
| 131 |
| 132 main() { |
| 133 asyncStart(); |
| 134 var desc = new ZoneSpecification( |
| 135 registerCallback: registerCallback, |
| 136 registerUnaryCallback: registerUnaryCallback, |
| 137 registerBinaryCallback: registerBinaryCallback, |
| 138 scheduleMicrotask: sm |
| 139 ); |
| 140 var future = runZoned(runTests, zoneSpecification: desc); |
| 141 future.then((_) => asyncEnd()); |
| 142 } |
OLD | NEW |