@@ -5,6 +5,8 @@ part of angular.core_internal;
5
5
*/
6
6
typedef void ZoneOnTurnDone ();
7
7
8
+ typedef void CountPendingAsync (int count);
9
+
8
10
/**
9
11
* Handles a [VmTurnZone] onTurnDone event.
10
12
*/
@@ -39,6 +41,7 @@ class LongStackTrace {
39
41
}
40
42
}
41
43
44
+
42
45
/**
43
46
* A [Zone] wrapper that lets you schedule tasks after its private microtask
44
47
* queue is exhausted but before the next "turn", i.e. event loop iteration.
@@ -75,12 +78,14 @@ class VmTurnZone {
75
78
run: _onRun,
76
79
runUnary: _onRunUnary,
77
80
scheduleMicrotask: _onScheduleMicrotask,
81
+ createTimer: _onCreateTimer,
78
82
handleUncaughtError: _uncaughtError
79
83
));
80
84
onError = _defaultOnError;
81
85
onTurnDone = _defaultOnTurnDone;
82
86
onTurnStart = _defaultOnTurnStart;
83
87
onScheduleMicrotask = _defaultOnScheduleMicrotask;
88
+ countPendingAsync = _defaultCountPendingAsync;
84
89
}
85
90
86
91
List _asyncQueue = [];
@@ -126,6 +131,15 @@ class VmTurnZone {
126
131
}
127
132
}
128
133
134
+ async .Timer _onCreateTimer (async .Zone self, async .ZoneDelegate delegate, async .Zone zone, Duration duration, fn ()) {
135
+ var s = traceEnter (VmTurnZone_createTimer );
136
+ try {
137
+ return new _WrappedTimer (this , delegate, zone, duration, fn);
138
+ } finally {
139
+ traceLeave (s);
140
+ }
141
+ }
142
+
129
143
void _uncaughtError (async .Zone self, async .ZoneDelegate delegate, async .Zone zone,
130
144
e, StackTrace s) {
131
145
if (! _errorThrownFromOnRun) onError (e, s, _longStacktrace);
@@ -199,7 +213,9 @@ class VmTurnZone {
199
213
* the turn will _never_ end.
200
214
*/
201
215
ZoneOnTurnDone onTurnDone;
216
+ CountPendingAsync countPendingAsync;
202
217
void _defaultOnTurnDone () => null ;
218
+ void _defaultCountPendingAsync (int count) => null ;
203
219
204
220
/**
205
221
* Called any time a microtask is scheduled. If you override [onScheduleMicrotask] , you
@@ -276,3 +292,28 @@ class VmTurnZone {
276
292
assertInTurn ();
277
293
}
278
294
}
295
+
296
+
297
+ // Automatically adjusts the pending async task count when the timer is
298
+ // scheduled, canceled or fired.
299
+ class _WrappedTimer implements async .Timer {
300
+ async .Timer _realTimer;
301
+ VmTurnZone _vmTurnZone;
302
+
303
+ _WrappedTimer (this ._vmTurnZone, async .ZoneDelegate delegate, async .Zone zone, Duration duration, Function fn ()) {
304
+ _vmTurnZone.countPendingAsync (1 );
305
+ _realTimer = delegate.createTimer (zone, duration, () {
306
+ fn ();
307
+ _vmTurnZone.countPendingAsync (- 1 );
308
+ });
309
+ }
310
+
311
+ bool get isActive => _realTimer.isActive;
312
+
313
+ void cancel () {
314
+ if (_realTimer.isActive) {
315
+ _vmTurnZone.countPendingAsync (- 1 );
316
+ }
317
+ _realTimer.cancel ();
318
+ }
319
+ }
0 commit comments