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

Side by Side Diff: pkg/barback/lib/src/phase_input.dart

Issue 188673004: Roll forward commits r33138, r33135, and r33134. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « pkg/barback/lib/src/phase_forwarder.dart ('k') | pkg/barback/lib/src/transform_node.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 library barback.phase_input; 5 library barback.phase_input;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'asset_forwarder.dart'; 9 import 'asset_forwarder.dart';
10 import 'asset_node.dart'; 10 import 'asset_node.dart';
11 import 'asset_node_set.dart';
11 import 'errors.dart'; 12 import 'errors.dart';
12 import 'log.dart'; 13 import 'log.dart';
13 import 'phase.dart'; 14 import 'phase.dart';
14 import 'stream_pool.dart'; 15 import 'stream_pool.dart';
15 import 'transform_node.dart'; 16 import 'transform_node.dart';
16 import 'transformer.dart'; 17 import 'transformer.dart';
17 import 'utils.dart'; 18 import 'utils.dart';
18 19
19 /// A class for watching a single [AssetNode] and running any transforms that 20 /// A class for watching a single [AssetNode] and running any transforms that
20 /// take that node as a primary input. 21 /// take that node as a primary input.
(...skipping 15 matching lines...) Expand all
36 final _transforms = new Set<TransformNode>(); 37 final _transforms = new Set<TransformNode>();
37 38
38 /// A forwarder for the input [AssetNode] for this phase. 39 /// A forwarder for the input [AssetNode] for this phase.
39 /// 40 ///
40 /// This is used to mark the node as removed should the input ever be removed. 41 /// This is used to mark the node as removed should the input ever be removed.
41 final AssetForwarder _inputForwarder; 42 final AssetForwarder _inputForwarder;
42 43
43 /// The asset node for this input. 44 /// The asset node for this input.
44 AssetNode get input => _inputForwarder.node; 45 AssetNode get input => _inputForwarder.node;
45 46
46 /// The controller that's used for the output node if [input] isn't consumed 47 /// The controller that's used for the output node if [input] isn't
47 /// by any transformers. 48 /// overwritten by any transformers.
48 /// 49 ///
49 /// This needs an intervening controller to ensure that the output can be 50 /// This needs an intervening controller to ensure that the output can be
50 /// marked dirty when determining whether transforms apply, and removed if 51 /// marked dirty when determining whether transforms will overwrite it, and be
51 /// they do. It's null if the asset is not being passed through. 52 /// marked removed if they do. It's null if the asset is not being passed
53 /// through.
52 AssetNodeController _passThroughController; 54 AssetNodeController _passThroughController;
53 55
54 /// A stream that emits an event whenever [this] is no longer dirty. 56 /// A stream that emits an event whenever [this] is no longer dirty.
55 /// 57 ///
56 /// This is synchronous in order to guarantee that it will emit an event as 58 /// This is synchronous in order to guarantee that it will emit an event as
57 /// soon as [isDirty] flips from `true` to `false`. 59 /// soon as [isDirty] flips from `true` to `false`.
58 Stream get onDone => _onDoneController.stream; 60 Stream get onDone => _onDoneController.stream;
59 final _onDoneController = new StreamController.broadcast(sync: true); 61 final _onDoneController = new StreamController.broadcast(sync: true);
60 62
61 /// A stream that emits any new assets emitted by [this]. 63 /// A stream that emits any new assets emitted by [this].
62 /// 64 ///
63 /// Assets are emitted synchronously to ensure that any changes are thoroughly 65 /// Assets are emitted synchronously to ensure that any changes are thoroughly
64 /// propagated as soon as they occur. 66 /// propagated as soon as they occur.
65 Stream<AssetNode> get onAsset => _onAssetPool.stream; 67 Stream<AssetNode> get onAsset => _onAssetController.stream;
66 final _onAssetPool = new StreamPool<AssetNode>();
67
68 /// A controller for emitting assets.
69 ///
70 /// This will be added to [_onAssetPool]. It's used to emit pass-through
71 /// assets.
72 final _onAssetController = new StreamController<AssetNode>(sync: true); 68 final _onAssetController = new StreamController<AssetNode>(sync: true);
73 69
74 /// Whether [this] is dirty and still has more processing to do. 70 /// Whether [this] is dirty and still has more processing to do.
75 bool get isDirty => _isAdjustingTransformers || 71 bool get isDirty => _isAdjustingTransformers ||
76 _transforms.any((transform) => transform.isDirty); 72 _transforms.any((transform) => transform.isDirty);
77 73
74 /// The set of assets emitted by the transformers for this input that have the
75 /// same id as [input].
76 final _overwritingOutputs = new AssetNodeSet();
77
78 /// Whether [this] has been rmeoved. 78 /// Whether [this] has been rmeoved.
79 bool get _isRemoved => _onAssetController.isClosed; 79 bool get _isRemoved => _onAssetController.isClosed;
80 80
81 /// Whether [input] has become dirty since [_adjustTransformers] last started 81 /// Whether [input] has become dirty since [_adjustTransformers] last started
82 /// running. 82 /// running.
83 bool _hasBecomeDirty = false; 83 bool _hasBecomeDirty = false;
84 84
85 /// Whether [_isAdjustingTransformers] is currently running. 85 /// Whether [_isAdjustingTransformers] is currently running.
86 bool _isAdjustingTransformers = false; 86 bool _isAdjustingTransformers = false;
87 87
88 /// A stream that emits an event whenever any transforms that use [input] as 88 /// A stream that emits an event whenever any transforms that use [input] as
89 /// their primary input log an entry. 89 /// their primary input log an entry.
90 Stream<LogEntry> get onLog => _onLogPool.stream; 90 Stream<LogEntry> get onLog => _onLogPool.stream;
91 final _onLogPool = new StreamPool<LogEntry>.broadcast(); 91 final _onLogPool = new StreamPool<LogEntry>.broadcast();
92 92
93 PhaseInput(this._phase, AssetNode input, Iterable<Transformer> transformers, 93 PhaseInput(this._phase, AssetNode input, Iterable<Transformer> transformers,
94 this._location) 94 this._location)
95 : _transformers = transformers.toSet(), 95 : _transformers = transformers.toSet(),
96 _inputForwarder = new AssetForwarder(input) { 96 _inputForwarder = new AssetForwarder(input) {
97 _onAssetPool.add(_onAssetController.stream);
98
99 input.onStateChange.listen((state) { 97 input.onStateChange.listen((state) {
100 if (state.isRemoved) { 98 if (state.isRemoved) {
101 remove(); 99 remove();
102 } else { 100 } else {
103 _dirty(); 101 _dirty();
104 } 102 }
105 }); 103 });
106 104
107 _adjustTransformers(); 105 _adjustTransformers();
108 } 106 }
109 107
110 /// Removes this input. 108 /// Removes this input.
111 /// 109 ///
112 /// This marks all outputs of the input as removed. 110 /// This marks all outputs of the input as removed.
113 void remove() { 111 void remove() {
114 _onDoneController.close(); 112 _onDoneController.close();
115 _hasBecomeDirty = false; 113 _hasBecomeDirty = false;
116 _onAssetPool.close();
117 _onAssetController.close(); 114 _onAssetController.close();
118 _onLogPool.close(); 115 _onLogPool.close();
119 _inputForwarder.close(); 116 _inputForwarder.close();
120 if (_passThroughController != null) { 117 if (_passThroughController != null) {
121 _passThroughController.setRemoved(); 118 _passThroughController.setRemoved();
122 _passThroughController = null; 119 _passThroughController = null;
123 } 120 }
124 } 121 }
125 122
126 /// Mark [this] as dirty and start re-running [_adjustTransformers] if 123 /// Mark [this] as dirty and start re-running [_adjustTransformers] if
127 /// necessary. 124 /// necessary.
128 void _dirty() { 125 void _dirty() {
129 // If there's a pass-through for this input, mark it dirty until we figure 126 // If there's a pass-through for this input, mark it dirty until we figure
130 // out whether we need to add any transforms for it. 127 // out if a transformer will emit an asset with that id.
131 if (_passThroughController != null) _passThroughController.setDirty(); 128 if (_passThroughController != null) _passThroughController.setDirty();
132 _hasBecomeDirty = true; 129 _hasBecomeDirty = true;
133 if (!_isAdjustingTransformers) _adjustTransformers(); 130 if (!_isAdjustingTransformers) _adjustTransformers();
134 } 131 }
135 132
136 /// Set this input's transformers to [transformers]. 133 /// Set this input's transformers to [transformers].
137 void updateTransformers(Iterable<Transformer> newTransformersIterable) { 134 void updateTransformers(Iterable<Transformer> newTransformersIterable) {
138 var newTransformers = newTransformersIterable.toSet(); 135 var newTransformers = newTransformersIterable.toSet();
139 var oldTransformers = _transformers.toSet(); 136 var oldTransformers = _transformers.toSet();
140 var removedTransformers = oldTransformers.difference(newTransformers); 137 var removedTransformers = oldTransformers.difference(newTransformers);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 // Since [_removeStaleTransforms] will check each of these transformers to 172 // Since [_removeStaleTransforms] will check each of these transformers to
176 // be sure [input] is still primary for them, we use this set to avoid 173 // be sure [input] is still primary for them, we use this set to avoid
177 // needlessly re-checking in [_addFreshTransforms]. 174 // needlessly re-checking in [_addFreshTransforms].
178 var oldTransformers = 175 var oldTransformers =
179 _transforms.map((transform) => transform.transformer).toSet(); 176 _transforms.map((transform) => transform.transformer).toSet();
180 177
181 return _removeStaleTransforms().then((_) { 178 return _removeStaleTransforms().then((_) {
182 if (_hasBecomeDirty || _isRemoved) return null; 179 if (_hasBecomeDirty || _isRemoved) return null;
183 return _addFreshTransforms(oldTransformers); 180 return _addFreshTransforms(oldTransformers);
184 }); 181 });
185 }).then((_) {
186 if (_hasBecomeDirty || _isRemoved) return null;
187 _adjustPassThrough();
188 }).catchError((error, stackTrace) { 182 }).catchError((error, stackTrace) {
189 if (error is! AssetNotFoundException || error.id != input.id) throw error; 183 if (error is! AssetNotFoundException || error.id != input.id) throw error;
190 184
191 // If the asset is removed, [input.whenAvailable] will throw an 185 // If the asset is removed, [input.whenAvailable] will throw an
192 // [AssetNotFoundException]. In that case, just remove it. 186 // [AssetNotFoundException]. In that case, just remove it.
193 remove(); 187 remove();
194 }).then((_) { 188 }).then((_) {
195 if (_isRemoved) return; 189 if (_isRemoved) return;
196 190
197 _isAdjustingTransformers = false; 191 _isAdjustingTransformers = false;
198 if (_hasBecomeDirty) { 192 if (_hasBecomeDirty) {
199 _adjustTransformers(); 193 _adjustTransformers();
200 } else if (!isDirty) { 194 } else if (!isDirty) {
195 _adjustPassThrough();
201 _onDoneController.add(null); 196 _onDoneController.add(null);
202 } 197 }
203 }); 198 });
204 } 199 }
205 200
206 // Remove any old transforms that used to have [input]'s asset as a primary 201 // Remove any old transforms that used to have [input]'s asset as a primary
207 // asset but no longer apply to its new contents. 202 // asset but no longer apply to its new contents.
208 Future _removeStaleTransforms() { 203 Future _removeStaleTransforms() {
209 assert(input.state.isAvailable); 204 assert(input.state.isAvailable);
210 205
(...skipping 28 matching lines...) Expand all
239 return Future.wait(_transformers.map((transformer) { 234 return Future.wait(_transformers.map((transformer) {
240 if (oldTransformers.contains(transformer)) return new Future.value(); 235 if (oldTransformers.contains(transformer)) return new Future.value();
241 236
242 // TODO(rnystrom): Catch all errors from isPrimary() and redirect to 237 // TODO(rnystrom): Catch all errors from isPrimary() and redirect to
243 // results. 238 // results.
244 return transformer.isPrimary(input.asset).then((isPrimary) { 239 return transformer.isPrimary(input.asset).then((isPrimary) {
245 if (_hasBecomeDirty || !isPrimary) return; 240 if (_hasBecomeDirty || !isPrimary) return;
246 var transform = new TransformNode( 241 var transform = new TransformNode(
247 _phase, transformer, input, _location); 242 _phase, transformer, input, _location);
248 _transforms.add(transform); 243 _transforms.add(transform);
249 _onAssetPool.add(transform.onAsset); 244
245 transform.onStateChange.listen((_) {
246 if (isDirty) {
247 if (_passThroughController == null) return;
248 _passThroughController.setDirty();
249 } else {
250 _adjustPassThrough();
251 _onDoneController.add(null);
252 }
253 });
254
255 transform.onAsset.listen((asset) {
256 if (asset.id == input.id) {
257 _overwritingOutputs.add(asset);
258 asset.whenRemoved(_adjustPassThrough);
259 _adjustPassThrough();
260 }
261
262 _onAssetController.add(asset);
263 }, onDone: () => _transforms.remove(transform));
264
250 _onLogPool.add(transform.onLog); 265 _onLogPool.add(transform.onLog);
251 transform.onDone.listen((_) {
252 if (!isDirty) _onDoneController.add(null);
253 }, onDone: () => _transforms.remove(transform));
254 }); 266 });
255 })); 267 }));
256 } 268 }
257 269
258 /// Adjust whether [input] is passed through the phase unmodified, based on 270 /// Adjust whether [input] is passed through the phase unmodified, based on
259 /// whether it's consumed by other transforms in this phase. 271 /// whether it's overwritten by other transforms in this phase.
260 /// 272 ///
261 /// If [input] was already passed-through, this will update the passed-through 273 /// If [input] was already passed-through, this will update the passed-through
262 /// value. 274 /// value.
263 void _adjustPassThrough() { 275 void _adjustPassThrough() {
264 assert(input.state.isAvailable); 276 // If [input] is removed, [_adjustPassThrough] can still be called due to
277 // [TransformNode]s marking their outputs as removed.
278 if (!input.state.isAvailable) return;
265 279
266 if (_transforms.isEmpty) { 280 // If there's an output with the same id as the primary input, that
281 // overwrites the input so it doesn't get passed through. Otherwise,
282 // create a pass-through controller if none exists, or set the existing
283 // one available.
284 if (_overwritingOutputs.isNotEmpty) {
267 if (_passThroughController != null) { 285 if (_passThroughController != null) {
268 _passThroughController.setAvailable(input.asset); 286 _passThroughController.setRemoved();
269 } else { 287 _passThroughController = null;
270 _passThroughController = new AssetNodeController.from(input);
271 _onAssetController.add(_passThroughController.node);
272 } 288 }
273 } else if (_passThroughController != null) { 289 } else if (isDirty) {
274 _passThroughController.setRemoved(); 290 // If the input is dirty, we're still figuring out whether a transform
275 _passThroughController = null; 291 // will overwrite the input. As such, we shouldn't pass through the asset
292 // yet.
293 } else if (_passThroughController == null) {
294 _passThroughController = new AssetNodeController.from(input);
295 _onAssetController.add(_passThroughController.node);
296 } else if (_passThroughController.node.state.isDirty) {
297 _passThroughController.setAvailable(input.asset);
276 } 298 }
277 } 299 }
278 300
279 String toString() => "phase input in $_location for $input"; 301 String toString() => "phase input in $_location for $input";
280 } 302 }
OLDNEW
« no previous file with comments | « pkg/barback/lib/src/phase_forwarder.dart ('k') | pkg/barback/lib/src/transform_node.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698