Chromium Code Reviews| Index: sky/specs/events.md |
| diff --git a/sky/specs/events.md b/sky/specs/events.md |
| index d839c17059f205b963badcd5d981036cc334aa76..5ce435069c286b7f2363ca7deee714d4a8fcefa5 100644 |
| --- a/sky/specs/events.md |
| +++ b/sky/specs/events.md |
| @@ -6,6 +6,107 @@ SKY MODULE |
| <!-- part of sky:core --> |
| <script> |
| +import 'dart:collection'; |
| +import 'dart:async'; |
| + |
| +class ExceptionAndStackTrace<T> { |
| + const ExceptionAndStackTrace(this.exception, this.stackTrace); |
| + final T exception; |
| + final StackTrace stackTrace; |
| +} |
| + |
| +class ExceptionListException<T> extends Object with IterableMixin<ExceptionAndStackTrace<T>> implements Exception { |
|
abarth-chromium
2015/02/12 00:28:13
extends Object seems a bit silly
Hixie
2015/02/12 21:31:43
Fixed. Turns out you just need extends IterableMix
|
| + List<ExceptionAndStackTrace<T>> _exceptions; |
| + void add(T exception, [StackTrace stackTrace = null]) { |
| + if (_exceptions == null) |
| + _exceptions = new List<ExceptionAndStackTrace<T>>(); |
| + _exceptions.add(new ExceptionAndStackTrace<T>(exception, stackTrace)); |
| + } |
| + int get length => _exceptions == null ? 0 : _exceptions.length; |
| + Iterator<ExceptionAndStackTrace<T>> get iterator => _exceptions.iterator; |
| +} |
| + |
| +typedef bool Filter<T>(T t); |
| +typedef void Handler<T>(T t); |
| + |
| +class DispatcherController<T> { |
| + Dispatcher<T> _dispatcher; |
|
abarth-chromium
2015/02/12 00:28:13
final
Hixie
2015/02/12 21:31:43
Done.
|
| + Dispatcher<T> get dispatcher => _dispatcher; |
| + DispatcherController() { |
| + _dispatcher = new Dispatcher<T>._internal(); |
| + } |
| + void add(T data) => _dispatcher._add(data); |
| +} |
| + |
| +class Dispatcher<T> { |
| + Dispatcher.silent() { } // returns a dispatcher that never gets an event |
| + Dispatcher._internal() { } |
|
abarth-chromium
2015/02/12 00:28:13
Remove?
Hixie
2015/02/12 21:31:43
Done.
|
| + |
| + List<Handler> _listeners; |
| + void listen(Handler<T> handler) { |
| + // you should not throw out of this handler |
| + if (_listeners == null) |
| + _listeners = new List<Handler>(); |
| + _listeners.add(handler); |
| + } |
| + bool unlisten(Handler<T> handler) { |
| + if (_listeners == null) |
| + return false; |
| + return _listeners.remove(handler); |
| + } |
| + void _add(T data) { |
| + if (_listeners == null) |
| + return; |
| + ExceptionListException exceptions = new ExceptionListException(); |
| + // we make a copy of the list here so that the listeners can |
| + // mutate our list without worry |
| + _listeners.toList().forEach((Handler handler) { |
| + try { |
| + handler(data); |
|
abarth-chromium
2015/02/12 00:28:13
Zone?
Hixie
2015/02/12 21:31:43
Done.
|
| + } catch (exception, stackTrace) { |
| + exceptions.add(exception, stackTrace); |
| + } |
| + }); |
| + if (exceptions.length > 0) |
| + throw exceptions; |
| + } |
| + |
| + Dispatcher<T> where(Filter<T> filter) { |
| + var subdispatcher = new Dispatcher<T>._internal(); |
| + listen((T data) { |
| + if (filter(data)) |
| + subdispatcher._add(data); |
| + }); |
| + return subdispatcher; |
| + } |
| + |
| + Dispatcher<T> until(Filter<T> filter) { |
| + var subdispatcher = new Dispatcher<T>._internal(); |
| + Handler handler; |
| + handler = (T data) { |
| + if (filter(data)) |
| + unlisten(handler); |
| + else |
| + subdispatcher._add(data); |
| + }; |
| + listen(handler); |
| + return subdispatcher; |
| + } |
| + |
| + Future<T> firstWhere(Filter<T> filter) { |
| + Completer completer = new Completer(); |
| + Handler handler; |
| + handler = (T data) { |
| + if (filter(data)) { |
| + completer.complete(data); |
| + unlisten(handler); |
| + } |
| + }; |
| + listen(handler); |
| + return completer.future; |
| + } |
| +} |
| + |
| abstract class Event<ReturnType> { |
| Event() { init(); } |
| void init() { } |