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 |