Index: third_party/pkg/angular/lib/mock/zone.dart |
diff --git a/third_party/pkg/angular/lib/mock/zone.dart b/third_party/pkg/angular/lib/mock/zone.dart |
index 862d42014be740c2b0403cbb29426da913affa23..ab8c3868c8a3f860d6ea11b2eeb433d9740800bc 100644 |
--- a/third_party/pkg/angular/lib/mock/zone.dart |
+++ b/third_party/pkg/angular/lib/mock/zone.dart |
@@ -2,14 +2,31 @@ library angular.mock_zone; |
import 'dart:async' as dart_async; |
+// async and sync are function compositions. |
+class FunctionComposition { |
+ Function outer; |
+ Function inner; |
+ |
+ FunctionComposition(this.outer, this.inner); |
+ |
+ call() => outer(inner)(); |
+} |
+ |
final _asyncQueue = <Function>[]; |
final _timerQueue = <_TimerSpec>[]; |
final _asyncErrors = []; |
bool _noMoreAsync = false; |
/** |
- * Runs any queued up async calls and any async calls queued with |
- * running microLeap. Example: |
+ * Processes the asynchronous queue established by [async]. |
+ * |
+ * [microLeap] will process all items in the asynchronous queue, |
+ * including new items queued during its execution. It will re-raise |
+ * any exceptions that occur. |
+ * |
+ * NOTE: [microLeap] can only be used in [async] tests. |
+ * |
+ * Example: |
* |
* it('should run async code', async(() { |
* var thenRan = false; |
@@ -31,7 +48,7 @@ bool _noMoreAsync = false; |
* |
*/ |
microLeap() { |
- while (!_asyncQueue.isEmpty) { |
+ while (_asyncQueue.isNotEmpty) { |
// copy the queue as it may change. |
var toRun = new List.from(_asyncQueue); |
_asyncQueue.clear(); |
@@ -47,6 +64,11 @@ microLeap() { |
} |
/** |
+ * Returns whether the async queue is empty. |
+ */ |
+isAsyncQueueEmpty() => _asyncQueue.isEmpty; |
+ |
+/** |
* Simulates a clock tick by running any scheduled timers. Can only be used |
* in [async] tests.Clock tick will call [microLeap] to process the microtask |
* queue before each timer callback. |
@@ -131,7 +153,16 @@ noMoreAsync() { |
} |
/** |
- * Captures all scheduleMicrotask calls inside of a function. |
+ * Captures all scheduleMicrotask calls and newly created Timers |
+ * inside of a function. |
+ * |
+ * [async] will raise an exception if there are still active Timers |
+ * when the function completes. |
+ * |
+ * Use [clockTick] to process timers, and [microLeap] to process |
+ * scheduleMicrotask calls. |
+ * |
+ * NOTE: [async] will not return the result of [fn]. |
* |
* Typically used within a test: |
* |
@@ -139,7 +170,9 @@ noMoreAsync() { |
* ... |
* })); |
*/ |
-async(Function fn) => () { |
+async(Function fn) => new FunctionComposition(_asyncOuter, fn); |
+ |
+_asyncOuter(Function fn) => () { |
_noMoreAsync = false; |
_asyncErrors.clear(); |
_timerQueue.clear(); |
@@ -186,7 +219,11 @@ _createTimer(Function fn, Duration duration, bool periodic) { |
* Enforces synchronous code. Any calls to scheduleMicrotask inside of 'sync' |
* will throw an exception. |
*/ |
-sync(Function fn) => () { |
+sync(Function fn) => new FunctionComposition(_syncOuter, fn); |
+ |
+_syncOuter(Function fn) => () { |
+ _asyncErrors.clear(); |
+ |
dart_async.runZoned(fn, zoneSpecification: new dart_async.ZoneSpecification( |
scheduleMicrotask: (_, __, ___, asyncFn) { |
throw ['scheduleMicrotask called from sync function.']; |
@@ -197,8 +234,13 @@ sync(Function fn) => () { |
createPeriodicTimer: |
(_, __, ___, Duration period, void f(dart_async.Timer timer)) { |
throw ['periodic Timer created from sync function.']; |
- } |
+ }, |
+ handleUncaughtError: (_, __, ___, e, s) => _asyncErrors.add([e, s]) |
)); |
+ |
+ _asyncErrors.forEach((e) { |
+ throw "During runZoned: ${e[0]}. Stack:\n${e[1]}"; |
+ }); |
}; |
class _TimerSpec implements dart_async.Timer { |