|
1 | 1 | import 'dart:async'; |
2 | 2 |
|
| 3 | +import 'package:meta/meta.dart'; |
3 | 4 | import 'package:stack_trace/stack_trace.dart'; |
4 | 5 |
|
5 | 6 | // TODO: add/fix links to: |
@@ -113,7 +114,7 @@ class NgZone { |
113 | 114 |
|
114 | 115 | // Number of microtasks pending from _innerZone (& descendants) |
115 | 116 | int _pendingMicrotasks = 0; |
116 | | - final List<Timer> _pendingTimers = <Timer>[]; |
| 117 | + final _pendingTimers = <_WrappedTimer>[]; |
117 | 118 |
|
118 | 119 | /// enabled in development mode as they significantly impact perf. |
119 | 120 | NgZone({bool enableLongStackTrace = false}) { |
@@ -234,28 +235,42 @@ class NgZone { |
234 | 235 | } |
235 | 236 |
|
236 | 237 | Timer _createTimer( |
237 | | - Zone self, ZoneDelegate parent, Zone zone, Duration duration, fn()) { |
| 238 | + Zone self, |
| 239 | + ZoneDelegate parent, |
| 240 | + Zone zone, |
| 241 | + Duration duration, |
| 242 | + void Function() fn, |
| 243 | + ) { |
238 | 244 | _WrappedTimer wrappedTimer; |
239 | | - var cb = () { |
| 245 | + final onDone = () { |
| 246 | + _pendingTimers.remove(wrappedTimer); |
| 247 | + _setMacrotask(_pendingTimers.isNotEmpty); |
| 248 | + }; |
| 249 | + final callback = () { |
240 | 250 | try { |
241 | 251 | fn(); |
242 | 252 | } finally { |
243 | | - _pendingTimers.remove(wrappedTimer); |
244 | | - _setMacrotask(_pendingTimers.isNotEmpty); |
| 253 | + onDone(); |
245 | 254 | } |
246 | 255 | }; |
247 | | - Timer timer = parent.createTimer(zone, duration, cb); |
248 | | - wrappedTimer = new _WrappedTimer(timer); |
249 | | - wrappedTimer.addOnCancelCb(() { |
250 | | - _pendingTimers.remove(wrappedTimer); |
251 | | - _setMacrotask(_pendingTimers.isNotEmpty); |
252 | | - }); |
253 | | - |
| 256 | + Timer timer = parent.createTimer(zone, duration, callback); |
| 257 | + wrappedTimer = new _WrappedTimer(timer, duration, onDone); |
254 | 258 | _pendingTimers.add(wrappedTimer); |
255 | 259 | _setMacrotask(true); |
256 | 260 | return wrappedTimer; |
257 | 261 | } |
258 | 262 |
|
| 263 | + /// **INTERNAL ONLY**: See [longestPendingTimer]. |
| 264 | + Duration get _longestPendingTimer { |
| 265 | + var duration = Duration.zero; |
| 266 | + for (final timer in _pendingTimers) { |
| 267 | + if (timer._duration > duration) { |
| 268 | + duration = timer._duration; |
| 269 | + } |
| 270 | + } |
| 271 | + return duration; |
| 272 | + } |
| 273 | + |
259 | 274 | void _setMicrotask(bool hasMicrotasks) { |
260 | 275 | _hasPendingMicrotasks = hasMicrotasks; |
261 | 276 | _checkStable(); |
@@ -379,37 +394,32 @@ class NgZone { |
379 | 394 | } |
380 | 395 | } |
381 | 396 |
|
| 397 | +/// For a [zone], returns the [Duration] of the longest pending timer. |
| 398 | +/// |
| 399 | +/// If no timers are scheduled this will always return [Duration.zero]. |
| 400 | +/// |
| 401 | +/// **INTERNAL ONLY**: This is an experimental API subject to change. |
| 402 | +@experimental |
| 403 | +Duration longestPendingTimer(NgZone zone) => zone._longestPendingTimer; |
| 404 | + |
382 | 405 | /// A `Timer` wrapper that lets you specify additional functions to call when it |
383 | 406 | /// is cancelled. |
384 | 407 | class _WrappedTimer implements Timer { |
385 | 408 | final Timer _timer; |
386 | | - void Function() _onCancelCb; |
| 409 | + final Duration _duration; |
| 410 | + final void Function() _onCancel; |
387 | 411 |
|
388 | | - _WrappedTimer(this._timer); |
389 | | - |
390 | | - void addOnCancelCb(void Function() onCancelCb) { |
391 | | - if (this._onCancelCb != null) { |
392 | | - throw new StateError("On cancel cb already registered"); |
393 | | - } |
394 | | - this._onCancelCb = onCancelCb; |
395 | | - } |
| 412 | + _WrappedTimer(this._timer, this._duration, this._onCancel); |
396 | 413 |
|
397 | 414 | void cancel() { |
398 | | - if (this._onCancelCb != null) { |
399 | | - this._onCancelCb(); |
400 | | - } |
| 415 | + _onCancel(); |
401 | 416 | _timer.cancel(); |
402 | 417 | } |
403 | 418 |
|
404 | 419 | bool get isActive => _timer.isActive; |
405 | 420 |
|
406 | 421 | @override |
407 | | - // TODO: Dart 2.0 requires this method to be implemented. |
408 | | - // See https://github.com/dart-lang/sdk/issues/31664 |
409 | | - // ignore: override_on_non_overriding_getter |
410 | | - int get tick { |
411 | | - throw new UnimplementedError("tick"); |
412 | | - } |
| 422 | + int get tick => _timer.tick; |
413 | 423 | } |
414 | 424 |
|
415 | 425 | /// Stores error information; delivered via [NgZone.onError] stream. |
|
0 commit comments