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

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

Issue 183993003: Revert commits r33138, r33135, and r33134. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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/phase_output.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 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'asset.dart'; 10 import 'asset.dart';
11 import 'asset_forwarder.dart'; 11 import 'asset_forwarder.dart';
12 import 'asset_node.dart'; 12 import 'asset_node.dart';
13 import 'asset_node_set.dart';
14 import 'errors.dart'; 13 import 'errors.dart';
15 import 'log.dart'; 14 import 'log.dart';
16 import 'phase.dart'; 15 import 'phase.dart';
17 import 'stream_pool.dart'; 16 import 'stream_pool.dart';
18 import 'transform_node.dart'; 17 import 'transform_node.dart';
19 import 'transformer.dart'; 18 import 'transformer.dart';
20 import 'utils.dart'; 19 import 'utils.dart';
21 20
22 /// A class for watching a single [AssetNode] and running any transforms that 21 /// A class for watching a single [AssetNode] and running any transforms that
23 /// take that node as a primary input. 22 /// take that node as a primary input.
(...skipping 15 matching lines...) Expand all
39 final _transforms = new Set<TransformNode>(); 38 final _transforms = new Set<TransformNode>();
40 39
41 /// A forwarder for the input [AssetNode] for this phase. 40 /// A forwarder for the input [AssetNode] for this phase.
42 /// 41 ///
43 /// This is used to mark the node as removed should the input ever be removed. 42 /// This is used to mark the node as removed should the input ever be removed.
44 final AssetForwarder _inputForwarder; 43 final AssetForwarder _inputForwarder;
45 44
46 /// The asset node for this input. 45 /// The asset node for this input.
47 AssetNode get input => _inputForwarder.node; 46 AssetNode get input => _inputForwarder.node;
48 47
49 /// The controller that's used for the output node if [input] isn't 48 /// The controller that's used for the output node if [input] isn't consumed
50 /// overwritten by any transformers. 49 /// by any transformers.
51 /// 50 ///
52 /// This needs an intervening controller to ensure that the output can be 51 /// This needs an intervening controller to ensure that the output can be
53 /// marked dirty when determining whether transforms will overwrite it, and be 52 /// marked dirty when determining whether transforms apply, and removed if
54 /// marked removed if they do. It's null if the asset is not being passed 53 /// they do. It's null if the asset is not being passed through.
55 /// through.
56 AssetNodeController _passThroughController; 54 AssetNodeController _passThroughController;
57 55
58 /// Whether [_passThroughController] has been newly created since [process] 56 /// Whether [_passThroughController] has been newly created since [process]
59 /// last completed. 57 /// last completed.
60 bool _newPassThrough = false; 58 bool _newPassThrough = false;
61 59
62 final _outputs = new AssetNodeSet();
63
64 /// A Future that will complete once the transformers that consume [input] are 60 /// A Future that will complete once the transformers that consume [input] are
65 /// determined. 61 /// determined.
66 Future _adjustTransformersFuture; 62 Future _adjustTransformersFuture;
67 63
68 /// A stream that emits an event whenever this input becomes dirty and needs 64 /// A stream that emits an event whenever this input becomes dirty and needs
69 /// [process] to be called. 65 /// [process] to be called.
70 /// 66 ///
71 /// This may emit events when the input was already dirty or while processing 67 /// This may emit events when the input was already dirty or while processing
72 /// transforms. Events are emitted synchronously to ensure that the dirty 68 /// transforms. Events are emitted synchronously to ensure that the dirty
73 /// state is thoroughly propagated as soon as any assets are changed. 69 /// state is thoroughly propagated as soon as any assets are changed.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // automatically pick up on [removedTransformer] being gone. 130 // automatically pick up on [removedTransformer] being gone.
135 if (_adjustTransformersFuture != null) continue; 131 if (_adjustTransformersFuture != null) continue;
136 132
137 _transforms.removeWhere((transform) { 133 _transforms.removeWhere((transform) {
138 if (transform.transformer != removedTransformer) return false; 134 if (transform.transformer != removedTransformer) return false;
139 transform.remove(); 135 transform.remove();
140 return true; 136 return true;
141 }); 137 });
142 } 138 }
143 139
140 if (_transforms.isEmpty && _adjustTransformersFuture == null &&
141 _passThroughController == null) {
142 _passThroughController = new AssetNodeController.from(input);
143 _newPassThrough = true;
144 }
145
144 var brandNewTransformers = newTransformers.difference(oldTransformers); 146 var brandNewTransformers = newTransformers.difference(oldTransformers);
145 if (brandNewTransformers.isEmpty) return; 147 if (brandNewTransformers.isEmpty) return;
146 148
147 brandNewTransformers.forEach(_transformers.add); 149 brandNewTransformers.forEach(_transformers.add);
148 if (_adjustTransformersFuture == null) _adjustTransformers(); 150 if (_adjustTransformersFuture == null) _adjustTransformers();
149 } 151 }
150 152
151 /// Force all [LazyTransformer]s' transforms in this input to begin producing 153 /// Force all [LazyTransformer]s' transforms in this input to begin producing
152 /// concrete assets. 154 /// concrete assets.
153 void forceAllTransforms() { 155 void forceAllTransforms() {
154 for (var transform in _transforms) { 156 for (var transform in _transforms) {
155 transform.force(); 157 transform.force();
156 } 158 }
157 } 159 }
158 160
159 /// Asynchronously determines which transformers can consume [input] as a 161 /// Asynchronously determines which transformers can consume [input] as a
160 /// primary input and creates transforms for them. 162 /// primary input and creates transforms for them.
161 /// 163 ///
162 /// This ensures that if [input] is modified or removed during or after the 164 /// This ensures that if [input] is modified or removed during or after the
163 /// time it takes to adjust its transformers, they're appropriately 165 /// time it takes to adjust its transformers, they're appropriately
164 /// re-adjusted. Its progress can be tracked in [_adjustTransformersFuture]. 166 /// re-adjusted. Its progress can be tracked in [_adjustTransformersFuture].
165 void _adjustTransformers() { 167 void _adjustTransformers() {
166 // Mark the input as dirty. This may not actually end up creating any new 168 // Mark the input as dirty. This may not actually end up creating any new
167 // transforms, but we want adding or removing a source asset to consistently 169 // transforms, but we want adding or removing a source asset to consistently
168 // kick off a build, even if that build does nothing. 170 // kick off a build, even if that build does nothing.
169 _onDirtyController.add(null); 171 _onDirtyController.add(null);
170 172
171 // If there's a pass-through for this input, mark it dirty until we figure 173 // If there's a pass-through for this input, mark it dirty while we figure
172 // out if a transformer will emit an asset with that id. 174 // out whether we need to add any transforms for it.
173 if (_passThroughController != null) _passThroughController.setDirty(); 175 if (_passThroughController != null) _passThroughController.setDirty();
174 176
175 // Once the input is available, hook up transformers for it. If it changes 177 // Once the input is available, hook up transformers for it. If it changes
176 // while that's happening, try again. 178 // while that's happening, try again.
177 _adjustTransformersFuture = _tryUntilStable((asset, transformers) { 179 _adjustTransformersFuture = _tryUntilStable((asset, transformers) {
178 var oldTransformers = 180 var oldTransformers =
179 _transforms.map((transform) => transform.transformer).toSet(); 181 _transforms.map((transform) => transform.transformer).toSet();
180 182
181 return _removeStaleTransforms(asset, transformers).then((_) => 183 return _removeStaleTransforms(asset, transformers).then((_) =>
182 _addFreshTransforms(transformers, oldTransformers)); 184 _addFreshTransforms(transformers, oldTransformers));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 // We can safely access [input.asset] here even though it might have 236 // We can safely access [input.asset] here even though it might have
235 // changed since (as above) if it has, [_adjustTransformers] will just be 237 // changed since (as above) if it has, [_adjustTransformers] will just be
236 // re-run. 238 // re-run.
237 // TODO(rnystrom): Catch all errors from isPrimary() and redirect to 239 // TODO(rnystrom): Catch all errors from isPrimary() and redirect to
238 // results. 240 // results.
239 return transformer.isPrimary(input.asset).then((isPrimary) { 241 return transformer.isPrimary(input.asset).then((isPrimary) {
240 if (!isPrimary) return; 242 if (!isPrimary) return;
241 var transform = new TransformNode( 243 var transform = new TransformNode(
242 _phase, transformer, input, _location); 244 _phase, transformer, input, _location);
243 _transforms.add(transform); 245 _transforms.add(transform);
244 transform.onDirty.listen((_) {
245 if (_passThroughController != null) _passThroughController.setDirty();
246 });
247 _onDirtyPool.add(transform.onDirty); 246 _onDirtyPool.add(transform.onDirty);
248 _onLogPool.add(transform.onLog); 247 _onLogPool.add(transform.onLog);
249 }); 248 });
250 })); 249 }));
251 } 250 }
252 251
252 /// Adjust whether [input] is passed through the phase unmodified, based on
253 /// whether it's consumed by other transforms in this phase.
254 ///
255 /// If [input] was already passed-through, this will update the passed-through
256 /// value.
257 void _adjustPassThrough() {
258 assert(input.state.isAvailable);
259
260 if (_transforms.isEmpty) {
261 if (_passThroughController != null) {
262 _passThroughController.setAvailable(input.asset);
263 } else {
264 _passThroughController = new AssetNodeController.from(input);
265 _newPassThrough = true;
266 }
267 } else if (_passThroughController != null) {
268 _passThroughController.setRemoved();
269 _passThroughController = null;
270 _newPassThrough = false;
271 }
272 }
273
253 /// Like [AssetNode.tryUntilStable], but also re-runs [callback] if this 274 /// Like [AssetNode.tryUntilStable], but also re-runs [callback] if this
254 /// phase's transformers are modified. 275 /// phase's transformers are modified.
255 Future _tryUntilStable( 276 Future _tryUntilStable(
256 Future callback(Asset asset, Set<Transformer> transformers)) { 277 Future callback(Asset asset, Set<Transformer> transformers)) {
257 var oldTransformers; 278 var oldTransformers;
258 return input.tryUntilStable((asset) { 279 return input.tryUntilStable((asset) {
259 oldTransformers = _transformers.toSet(); 280 oldTransformers = _transformers.toSet();
260 return callback(asset, _transformers); 281 return callback(asset, _transformers);
261 }).then((result) { 282 }).then((result) {
262 if (setEquals(oldTransformers, _transformers)) return result; 283 if (setEquals(oldTransformers, _transformers)) return result;
263 return _tryUntilStable(callback); 284 return _tryUntilStable(callback);
264 }); 285 });
265 } 286 }
266 287
267 /// Processes the transforms for this input. 288 /// Processes the transforms for this input.
268 /// 289 ///
269 /// Returns the set of newly-created asset nodes that transforms have emitted 290 /// Returns the set of newly-created asset nodes that transforms have emitted
270 /// for this input. The assets returned this way are guaranteed not to be 291 /// for this input. The assets returned this way are guaranteed not to be
271 /// [AssetState.REMOVED]. 292 /// [AssetState.REMOVED].
272 Future<Set<AssetNode>> process() { 293 Future<Set<AssetNode>> process() {
273 return _waitForTransformers(() { 294 return _waitForTransformers(() => _processTransforms()).then((outputs) {
274 if (input.state.isRemoved) return new Future.value(new Set());
275
276 return Future.wait(_transforms.map((transform) {
277 if (!transform.isDirty) return new Future.value(new Set());
278 return transform.apply();
279 })).then((outputs) => unionAll(outputs));
280 }).then((outputs) {
281 if (input.state.isRemoved) return new Set(); 295 if (input.state.isRemoved) return new Set();
282
283 for (var output in outputs) {
284 assert(!output.state.isRemoved);
285 _outputs.add(output);
286 output.whenRemoved(_adjustPassThrough);
287 }
288
289 _adjustPassThrough();
290 if (_newPassThrough) {
291 outputs.add(_passThroughController.node);
292 _newPassThrough = false;
293 }
294 return outputs; 296 return outputs;
295 }); 297 });
296 } 298 }
297 299
298 /// Runs [callback] once all the transformers are adjusted correctly and the 300 /// Runs [callback] once all the transformers are adjusted correctly and the
299 /// input is ready to be processed. 301 /// input is ready to be processed.
300 /// 302 ///
301 /// If the transformers are already properly adjusted, [callback] is called 303 /// If the transformers are already properly adjusted, [callback] is called
302 /// synchronously to ensure that [_adjustTransformers] isn't called before the 304 /// synchronously to ensure that [_adjustTransformers] isn't called before the
303 /// callback. 305 /// callback.
304 Future _waitForTransformers(callback()) { 306 Future _waitForTransformers(callback()) {
305 if (_adjustTransformersFuture == null) return syncFuture(callback); 307 if (_adjustTransformersFuture == null) return syncFuture(callback);
306 return _adjustTransformersFuture.then( 308 return _adjustTransformersFuture.then(
307 (_) => _waitForTransformers(callback)); 309 (_) => _waitForTransformers(callback));
308 } 310 }
309 311
310 /// Adjust whether [input] is passed through the phase unmodified, based on 312 /// Applies all currently wired up and dirty transforms.
311 /// whether it's overwritten by other transforms in this phase. 313 Future<Set<AssetNode>> _processTransforms() {
312 /// 314 if (input.state.isRemoved) return new Future.value(new Set());
313 /// If [input] was already passed-through, this will update the passed-through
314 /// value.
315 void _adjustPassThrough() {
316 if (!input.state.isAvailable) return;
317 315
318 // If there's an output with the same id as the primary input, that 316 if (_passThroughController != null) {
319 // overwrites the input so it doesn't get passed through. Otherwise, 317 if (!_newPassThrough) return new Future.value(new Set());
320 // create a pass-through controller if none exists, or set the existing 318 _newPassThrough = false;
321 // one available. 319 return new Future.value(
322 if (_outputs.any((output) => output.id == input.id)) { 320 new Set<AssetNode>.from([_passThroughController.node]));
323 if (_passThroughController != null) {
324 _passThroughController.setRemoved();
325 _passThroughController = null;
326 _newPassThrough = false;
327 }
328 } else if (_passThroughController == null) {
329 _passThroughController = new AssetNodeController.from(input);
330 _newPassThrough = true;
331 } else if (_passThroughController.node.state.isDirty) {
332 _passThroughController.setAvailable(input.asset);
333 } 321 }
322
323 return Future.wait(_transforms.map((transform) {
324 if (!transform.isDirty) return new Future.value(new Set());
325 return transform.apply();
326 })).then((outputs) => unionAll(outputs));
334 } 327 }
335 328
336 String toString() => "phase input in $_location for $input"; 329 String toString() => "phase input in $_location for $input";
337 } 330 }
OLDNEW
« no previous file with comments | « pkg/barback/lib/src/phase_forwarder.dart ('k') | pkg/barback/lib/src/phase_output.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698