Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: tools/dom/src/EventStreamProvider.dart

Issue 2162643002: Revert "Reapply zone tasks." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/dom/scripts/htmlrenamer.py ('k') | tools/dom/src/shared_html.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of html; 5 part of html;
6 6
7 /** 7 /**
8 * A factory to expose DOM events as Streams. 8 * A factory to expose DOM events as Streams.
9 */ 9 */
10 class EventStreamProvider<T extends Event> { 10 class EventStreamProvider<T extends Event> {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 * is first processed for the event target and then bubbles upward. 111 * is first processed for the event target and then bubbles upward.
112 * 112 *
113 * ## Other resources 113 * ## Other resources
114 * 114 *
115 * * [Event Capture](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Event s-flow-capture) 115 * * [Event Capture](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Event s-flow-capture)
116 * from the W3C DOM Events specification. 116 * from the W3C DOM Events specification.
117 */ 117 */
118 StreamSubscription<T> capture(void onData(T event)); 118 StreamSubscription<T> capture(void onData(T event));
119 } 119 }
120 120
121 /// Task specification for DOM Events.
122 ///
123 /// *Experimental*. May disappear without notice.
124 class EventSubscriptionSpecification<T extends Event>
125 implements TaskSpecification {
126 @override
127 final String name;
128 @override
129 final bool isOneShot;
130
131 final EventTarget target;
132 /// The event-type of the event. For example 'click' for click events.
133 final String eventType;
134 // TODO(floitsch): the first generic argument should be 'void'.
135 final ZoneUnaryCallback<dynamic, T> onData;
136 final bool useCapture;
137
138 EventSubscriptionSpecification({this.name, this.isOneShot, this.target,
139 this.eventType, void this.onData(T event), this.useCapture});
140
141 /// Returns a copy of this instance, with every non-null argument replaced
142 /// by the given value.
143 EventSubscriptionSpecification<T> replace(
144 {String name, bool isOneShot, EventTarget target,
145 String eventType, void onData(T event), bool useCapture}) {
146 return new EventSubscriptionSpecification<T>(
147 name: name ?? this.name,
148 isOneShot: isOneShot ?? this.isOneShot,
149 target: target ?? this.target,
150 eventType: eventType ?? this.eventType,
151 onData: onData ?? this.onData,
152 useCapture: useCapture ?? this.useCapture);
153 }
154 }
155
156 /** 121 /**
157 * Adapter for exposing DOM events as Dart streams. 122 * Adapter for exposing DOM events as Dart streams.
158 */ 123 */
159 class _EventStream<T extends Event> extends Stream<T> { 124 class _EventStream<T extends Event> extends Stream<T> {
160 final EventTarget _target; 125 final EventTarget _target;
161 final String _eventType; 126 final String _eventType;
162 final bool _useCapture; 127 final bool _useCapture;
163 /// The name that is used in the task specification.
164 final String _name;
165 /// Whether the stream can trigger multiple times.
166 final bool _isOneShot;
167 128
168 _EventStream(this._target, String eventType, this._useCapture, 129 _EventStream(this._target, this._eventType, this._useCapture);
169 {String name, bool isOneShot: false})
170 : _eventType = eventType,
171 _isOneShot = isOneShot,
172 _name = name ?? "dart.html.event.$eventType";
173 130
174 // DOM events are inherently multi-subscribers. 131 // DOM events are inherently multi-subscribers.
175 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) , 132 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
176 void onCancel(StreamSubscription<T> subscription) }) 133 void onCancel(StreamSubscription<T> subscription) })
177 => this; 134 => this;
178 bool get isBroadcast => true; 135 bool get isBroadcast => true;
179 136
180 StreamSubscription<T> _listen(
181 void onData(T event), {bool useCapture}) {
182
183 if (identical(Zone.current, Zone.ROOT)) {
184 return new _EventStreamSubscription<T>(
185 this._target, this._eventType, onData, this._useCapture,
186 Zone.current);
187 }
188
189 var specification = new EventSubscriptionSpecification<T>(
190 name: this._name, isOneShot: this._isOneShot,
191 target: this._target, eventType: this._eventType,
192 onData: onData, useCapture: useCapture);
193 // We need to wrap the _createStreamSubscription call, since a tear-off
194 // would not bind the generic type 'T'.
195 return Zone.current.createTask((spec, Zone zone) {
196 return _createStreamSubscription/*<T>*/(spec, zone);
197 }, specification);
198 }
199
200 StreamSubscription<T> listen(void onData(T event), 137 StreamSubscription<T> listen(void onData(T event),
201 { Function onError, 138 { Function onError,
202 void onDone(), 139 void onDone(),
203 bool cancelOnError}) { 140 bool cancelOnError}) {
204 return _listen(onData, useCapture: this._useCapture); 141
142 return new _EventStreamSubscription<T>(
143 this._target, this._eventType, onData, this._useCapture);
205 } 144 }
206 } 145 }
207 146
208 bool _matchesWithAncestors(Event event, String selector) { 147 bool _matchesWithAncestors(Event event, String selector) {
209 var target = event.target; 148 var target = event.target;
210 return target is Element ? target.matchesWithAncestors(selector) : false; 149 return target is Element ? target.matchesWithAncestors(selector) : false;
211 } 150 }
212 151
213 /** 152 /**
214 * Adapter for exposing DOM Element events as streams, while also allowing 153 * Adapter for exposing DOM Element events as streams, while also allowing
215 * event delegation. 154 * event delegation.
216 */ 155 */
217 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T> 156 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T>
218 implements ElementStream<T> { 157 implements ElementStream<T> {
219 _ElementEventStreamImpl(target, eventType, useCapture, 158 _ElementEventStreamImpl(target, eventType, useCapture) :
220 {String name, bool isOneShot: false}) : 159 super(target, eventType, useCapture);
221 super(target, eventType, useCapture, name: name, isOneShot: isOneShot);
222 160
223 Stream<T> matches(String selector) => this.where( 161 Stream<T> matches(String selector) => this.where(
224 (event) => _matchesWithAncestors(event, selector)).map((e) { 162 (event) => _matchesWithAncestors(event, selector)).map((e) {
225 e._selector = selector; 163 e._selector = selector;
226 return e; 164 return e;
227 }); 165 });
228 166
229 StreamSubscription<T> capture(void onData(T event)) { 167 StreamSubscription<T> capture(void onData(T event)) =>
230 return _listen(onData, useCapture: true); 168 new _EventStreamSubscription<T>(
231 } 169 this._target, this._eventType, onData, true);
232 } 170 }
233 171
234 /** 172 /**
235 * Adapter for exposing events on a collection of DOM Elements as streams, 173 * Adapter for exposing events on a collection of DOM Elements as streams,
236 * while also allowing event delegation. 174 * while also allowing event delegation.
237 */ 175 */
238 class _ElementListEventStreamImpl<T extends Event> extends Stream<T> 176 class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
239 implements ElementStream<T> { 177 implements ElementStream<T> {
240 final Iterable<Element> _targetList; 178 final Iterable<Element> _targetList;
241 final bool _useCapture; 179 final bool _useCapture;
(...skipping 28 matching lines...) Expand all
270 } 208 }
271 return pool.stream.listen(onData); 209 return pool.stream.listen(onData);
272 } 210 }
273 211
274 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) , 212 Stream<T> asBroadcastStream({void onListen(StreamSubscription<T> subscription) ,
275 void onCancel(StreamSubscription<T> subscription) }) 213 void onCancel(StreamSubscription<T> subscription) })
276 => this; 214 => this;
277 bool get isBroadcast => true; 215 bool get isBroadcast => true;
278 } 216 }
279 217
280 StreamSubscription/*<T>*/ _createStreamSubscription/*<T>*/( 218 // We would like this to just be EventListener<T> but that typdef cannot
281 EventSubscriptionSpecification/*<T>*/ spec, Zone zone) {
282 return new _EventStreamSubscription/*<T>*/(spec.target, spec.eventType,
283 spec.onData, spec.useCapture, zone);
284 }
285
286 // We would like this to just be EventListener<T> but that typedef cannot
287 // use generics until dartbug/26276 is fixed. 219 // use generics until dartbug/26276 is fixed.
288 typedef _EventListener<T extends Event>(T event); 220 typedef _EventListener<T extends Event>(T event);
289 221
290 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { 222 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
291 int _pauseCount = 0; 223 int _pauseCount = 0;
292 EventTarget _target; 224 EventTarget _target;
293 final String _eventType; 225 final String _eventType;
294 EventListener _onData; 226 EventListener _onData;
295 EventListener _domCallback;
296 final bool _useCapture; 227 final bool _useCapture;
297 final Zone _zone;
298 228
299 // TODO(jacobr): for full strong mode correctness we should write 229 // TODO(jacobr): for full strong mode correctness we should write
300 // _onData = onData == null ? null : _wrapZone/*<dynamic, Event>*/((e) => onDa ta(e as T)) 230 // _onData = onData == null ? null : _wrapZone/*<Event, dynamic>*/((e) => onDa ta(e as T))
301 // but that breaks 114 co19 tests as well as multiple html tests as it is reas onable 231 // but that breaks 114 co19 tests as well as multiple html tests as it is reas onable
302 // to pass the wrong type of event object to an event listener as part of a 232 // to pass the wrong type of event object to an event listener as part of a
303 // test. 233 // test.
304 _EventStreamSubscription(this._target, this._eventType, void onData(T event), 234 _EventStreamSubscription(this._target, this._eventType, void onData(T event),
305 this._useCapture, Zone zone) 235 this._useCapture) : _onData = _wrapZone/*<Event, dynamic>*/(onData) {
306 : _zone = zone,
307 _onData = _registerZone/*<dynamic, Event>*/(zone, onData) {
308 _tryResume(); 236 _tryResume();
309 } 237 }
310 238
311 Future cancel() { 239 Future cancel() {
312 if (_canceled) return null; 240 if (_canceled) return null;
313 241
314 _unlisten(); 242 _unlisten();
315 // Clear out the target to indicate this is complete. 243 // Clear out the target to indicate this is complete.
316 _target = null; 244 _target = null;
317 _onData = null; 245 _onData = null;
318 return null; 246 return null;
319 } 247 }
320 248
321 bool get _canceled => _target == null; 249 bool get _canceled => _target == null;
322 250
323 void onData(void handleData(T event)) { 251 void onData(void handleData(T event)) {
324 if (_canceled) { 252 if (_canceled) {
325 throw new StateError("Subscription has been canceled."); 253 throw new StateError("Subscription has been canceled.");
326 } 254 }
327 // Remove current event listener. 255 // Remove current event listener.
328 _unlisten(); 256 _unlisten();
329 _onData = _registerZone/*<dynamic, Event>*/(_zone, handleData); 257 _onData = _wrapZone/*<Event, dynamic>*/(handleData);
330 _tryResume(); 258 _tryResume();
331 } 259 }
332 260
333 /// Has no effect. 261 /// Has no effect.
334 void onError(Function handleError) {} 262 void onError(Function handleError) {}
335 263
336 /// Has no effect. 264 /// Has no effect.
337 void onDone(void handleDone()) {} 265 void onDone(void handleDone()) {}
338 266
339 void pause([Future resumeSignal]) { 267 void pause([Future resumeSignal]) {
340 if (_canceled) return; 268 if (_canceled) return;
341 ++_pauseCount; 269 ++_pauseCount;
342 _unlisten(); 270 _unlisten();
343 271
344 if (resumeSignal != null) { 272 if (resumeSignal != null) {
345 resumeSignal.whenComplete(resume); 273 resumeSignal.whenComplete(resume);
346 } 274 }
347 } 275 }
348 276
349 bool get isPaused => _pauseCount > 0; 277 bool get isPaused => _pauseCount > 0;
350 278
351 void resume() { 279 void resume() {
352 if (_canceled || !isPaused) return; 280 if (_canceled || !isPaused) return;
353 --_pauseCount; 281 --_pauseCount;
354 _tryResume(); 282 _tryResume();
355 } 283 }
356 284
357 void _tryResume() { 285 void _tryResume() {
358 if (_onData == null || isPaused) return; 286 if (_onData != null && !isPaused) {
359 if (identical(_zone, Zone.ROOT)) { 287 _target.addEventListener(_eventType, _onData, _useCapture);
360 _domCallback = _onData;
361 } else {
362 _domCallback = (event) {
363 _zone.runTask(_runEventNotification, this, event);
364 };
365 } 288 }
366 _target.addEventListener(_eventType, _domCallback, _useCapture);
367 }
368
369 static void _runEventNotification/*<T>*/(
370 _EventStreamSubscription/*<T>*/ subscription, /*=T*/ event) {
371 subscription._onData(event);
372 } 289 }
373 290
374 void _unlisten() { 291 void _unlisten() {
375 if (_onData != null) { 292 if (_onData != null) {
376 _target.removeEventListener(_eventType, _domCallback, _useCapture); 293 _target.removeEventListener(_eventType, _onData, _useCapture);
377 } 294 }
378 } 295 }
379 296
380 Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]) { 297 Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]) {
381 // We just need a future that will never succeed or fail. 298 // We just need a future that will never succeed or fail.
382 var completer = new Completer/*<E>*/(); 299 var completer = new Completer/*<E>*/();
383 return completer.future; 300 return completer.future;
384 } 301 }
385 } 302 }
386 303
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture ); 437 return new _ElementListEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture );
521 } 438 }
522 439
523 String getEventType(EventTarget target) { 440 String getEventType(EventTarget target) {
524 return _eventTypeGetter(target); 441 return _eventTypeGetter(target);
525 } 442 }
526 443
527 String get _eventType => 444 String get _eventType =>
528 throw new UnsupportedError('Access type through getEventType method.'); 445 throw new UnsupportedError('Access type through getEventType method.');
529 } 446 }
OLDNEW
« no previous file with comments | « tools/dom/scripts/htmlrenamer.py ('k') | tools/dom/src/shared_html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698