mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:27:17 +00:00
a2b556b937
Change-Id: Ia5c41dda6503e1fbb8cc6099835d07588425e2ba Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128310 Commit-Queue: Bob Nystrom <rnystrom@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
146 lines
3.3 KiB
Dart
146 lines
3.3 KiB
Dart
// 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.
|
|
|
|
// Test that async functions don't zone-register their callbacks for each
|
|
// await. Async functions should register their callback once in the beginning
|
|
// and then reuse it for all awaits in their body.
|
|
// This has two advantages: it is faster, when there are several awaits (on
|
|
// the Future class from dart:async), and it avoids zone-nesting when tracing
|
|
// stacktraces.
|
|
// See http://dartbug.com/23394 for more information.
|
|
|
|
import 'dart:async';
|
|
import 'package:expect/expect.dart';
|
|
import 'package:async_helper/async_helper.dart';
|
|
|
|
Future<int> gee(int i) async {
|
|
return await i;
|
|
}
|
|
|
|
Stream<int> bar() async* {
|
|
var i = 0;
|
|
while (true) yield await gee(i++);
|
|
}
|
|
|
|
awaitForTest() async {
|
|
var sum = 0;
|
|
await for (var x in bar().take(100)) {
|
|
sum += x;
|
|
}
|
|
Expect.equals(4950, sum);
|
|
}
|
|
|
|
awaitTest() async {
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
await null;
|
|
return await 499;
|
|
}
|
|
|
|
runTests() async {
|
|
await awaitTest();
|
|
await awaitForTest();
|
|
}
|
|
|
|
var depth = 0;
|
|
|
|
var depthIncreases = 0;
|
|
|
|
increaseDepth() {
|
|
depthIncreases++;
|
|
depth++;
|
|
// The async/await code should not register callbacks recursively in the
|
|
// then-calls. As such the depth should never grow too much. We don't want
|
|
// to commit to a specific value, since implementations still have some
|
|
// room in how async/await is implemented, but 20 should be safe.
|
|
Expect.isTrue(depth < 20);
|
|
}
|
|
|
|
ZoneCallback<R> registerCallback<R>(
|
|
Zone self, ZoneDelegate parent, Zone zone, R f()) {
|
|
var oldDepth = depth;
|
|
increaseDepth();
|
|
return parent.registerCallback(zone, () {
|
|
depth = oldDepth;
|
|
return f();
|
|
});
|
|
}
|
|
|
|
ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(
|
|
Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) {
|
|
var oldDepth = depth;
|
|
increaseDepth();
|
|
return parent.registerUnaryCallback(zone, (x) {
|
|
depth = oldDepth;
|
|
return f(x);
|
|
});
|
|
}
|
|
|
|
ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
|
|
Zone self, ZoneDelegate parent, Zone zone, R f(T1 arg1, T2 arg2)) {
|
|
var oldDepth = depth;
|
|
increaseDepth();
|
|
return parent.registerBinaryCallback(zone, (x, y) {
|
|
depth = oldDepth;
|
|
return f(x, y);
|
|
});
|
|
}
|
|
|
|
void sm(Zone self, ZoneDelegate parent, Zone zone, f) {
|
|
var oldDepth = depth;
|
|
increaseDepth();
|
|
return parent.scheduleMicrotask(zone, () {
|
|
depth = oldDepth;
|
|
return f();
|
|
});
|
|
}
|
|
|
|
main() {
|
|
asyncStart();
|
|
var desc = new ZoneSpecification(
|
|
registerCallback: registerCallback,
|
|
registerUnaryCallback: registerUnaryCallback,
|
|
registerBinaryCallback: registerBinaryCallback,
|
|
scheduleMicrotask: sm);
|
|
var future = runZoned(runTests, zoneSpecification: desc);
|
|
future.then((_) => asyncEnd());
|
|
}
|