| OLD | NEW |
| 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.transform_node; | 5 library barback.transform_node; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'asset.dart'; | 9 import 'asset.dart'; |
| 10 import 'asset_id.dart'; | 10 import 'asset_id.dart'; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 | 33 |
| 34 /// The node for the primary asset this transform depends on. | 34 /// The node for the primary asset this transform depends on. |
| 35 final AssetNode primary; | 35 final AssetNode primary; |
| 36 | 36 |
| 37 /// A string describing the location of [this] in the transformer graph. | 37 /// A string describing the location of [this] in the transformer graph. |
| 38 final String _location; | 38 final String _location; |
| 39 | 39 |
| 40 /// The subscription to [primary]'s [AssetNode.onStateChange] stream. | 40 /// The subscription to [primary]'s [AssetNode.onStateChange] stream. |
| 41 StreamSubscription _primarySubscription; | 41 StreamSubscription _primarySubscription; |
| 42 | 42 |
| 43 /// The subscription to [phase]'s [Phase.onAsset] stream. |
| 44 StreamSubscription<AssetNode> _phaseSubscription; |
| 45 |
| 43 /// Whether [this] is dirty and still has more processing to do. | 46 /// Whether [this] is dirty and still has more processing to do. |
| 44 bool get isDirty => !_state.isDone; | 47 bool get isDirty => !_state.isDone; |
| 45 | 48 |
| 46 /// Whether [transformer] is lazy and this transform has yet to be forced. | 49 /// Whether [transformer] is lazy and this transform has yet to be forced. |
| 47 bool _isLazy; | 50 bool _isLazy; |
| 48 | 51 |
| 49 /// The subscriptions to each input's [AssetNode.onStateChange] stream. | 52 /// The subscriptions to each input's [AssetNode.onStateChange] stream. |
| 50 var _inputSubscriptions = new Map<AssetId, StreamSubscription>(); | 53 final _inputSubscriptions = new Map<AssetId, StreamSubscription>(); |
| 51 | 54 |
| 52 /// The controllers for the asset nodes emitted by this node. | 55 /// The controllers for the asset nodes emitted by this node. |
| 53 var _outputControllers = new Map<AssetId, AssetNodeController>(); | 56 final _outputControllers = new Map<AssetId, AssetNodeController>(); |
| 57 |
| 58 final _missingInputs = new Set<AssetId>(); |
| 54 | 59 |
| 55 /// The controller that's used to pass [primary] through [this] if it's not | 60 /// The controller that's used to pass [primary] through [this] if it's not |
| 56 /// consumed or overwritten. | 61 /// consumed or overwritten. |
| 57 /// | 62 /// |
| 58 /// This needs an intervening controller to ensure that the output can be | 63 /// This needs an intervening controller to ensure that the output can be |
| 59 /// marked dirty when determining whether [this] will consume or overwrite it, | 64 /// marked dirty when determining whether [this] will consume or overwrite it, |
| 60 /// and be marked removed if it does. [_passThroughController] will be null | 65 /// and be marked removed if it does. [_passThroughController] will be null |
| 61 /// if the asset is not being passed through. | 66 /// if the asset is not being passed through. |
| 62 AssetNodeController _passThroughController; | 67 AssetNodeController _passThroughController; |
| 63 | 68 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 : transformer = transformer, | 107 : transformer = transformer, |
| 103 _isLazy = transformer is LazyTransformer { | 108 _isLazy = transformer is LazyTransformer { |
| 104 _primarySubscription = primary.onStateChange.listen((state) { | 109 _primarySubscription = primary.onStateChange.listen((state) { |
| 105 if (state.isRemoved) { | 110 if (state.isRemoved) { |
| 106 remove(); | 111 remove(); |
| 107 } else { | 112 } else { |
| 108 _dirty(primaryChanged: true); | 113 _dirty(primaryChanged: true); |
| 109 } | 114 } |
| 110 }); | 115 }); |
| 111 | 116 |
| 117 _phaseSubscription = phase.previous.onAsset.listen((node) { |
| 118 if (_missingInputs.contains(node.id)) _dirty(primaryChanged: false); |
| 119 }); |
| 120 |
| 112 _process(); | 121 _process(); |
| 113 } | 122 } |
| 114 | 123 |
| 115 /// The [TransformInfo] describing this node. | 124 /// The [TransformInfo] describing this node. |
| 116 /// | 125 /// |
| 117 /// [TransformInfo] is the publicly-visible representation of a transform | 126 /// [TransformInfo] is the publicly-visible representation of a transform |
| 118 /// node. | 127 /// node. |
| 119 TransformInfo get info => new TransformInfo(transformer, primary.id); | 128 TransformInfo get info => new TransformInfo(transformer, primary.id); |
| 120 | 129 |
| 121 /// Marks this transform as removed. | 130 /// Marks this transform as removed. |
| 122 /// | 131 /// |
| 123 /// This causes all of the transform's outputs to be marked as removed as | 132 /// This causes all of the transform's outputs to be marked as removed as |
| 124 /// well. Normally this will be automatically done internally based on events | 133 /// well. Normally this will be automatically done internally based on events |
| 125 /// from the primary input, but it's possible for a transform to no longer be | 134 /// from the primary input, but it's possible for a transform to no longer be |
| 126 /// valid even if its primary input still exists. | 135 /// valid even if its primary input still exists. |
| 127 void remove() { | 136 void remove() { |
| 128 _onAssetController.close(); | 137 _onAssetController.close(); |
| 129 _onDoneController.close(); | 138 _onDoneController.close(); |
| 130 _primarySubscription.cancel(); | 139 _primarySubscription.cancel(); |
| 140 _phaseSubscription.cancel(); |
| 131 _clearInputSubscriptions(); | 141 _clearInputSubscriptions(); |
| 132 _clearOutputs(); | 142 _clearOutputs(); |
| 133 if (_passThroughController != null) { | 143 if (_passThroughController != null) { |
| 134 _passThroughController.setRemoved(); | 144 _passThroughController.setRemoved(); |
| 135 _passThroughController = null; | 145 _passThroughController = null; |
| 136 } | 146 } |
| 137 } | 147 } |
| 138 | 148 |
| 139 /// If [transformer] is lazy, ensures that its concrete outputs will be | 149 /// If [transformer] is lazy, ensures that its concrete outputs will be |
| 140 /// generated. | 150 /// generated. |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 _state = _TransformNodeState.APPLIED; | 259 _state = _TransformNodeState.APPLIED; |
| 250 _onDoneController.add(null); | 260 _onDoneController.add(null); |
| 251 } | 261 } |
| 252 }); | 262 }); |
| 253 } | 263 } |
| 254 | 264 |
| 255 /// Gets the asset for an input [id]. | 265 /// Gets the asset for an input [id]. |
| 256 /// | 266 /// |
| 257 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. | 267 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. |
| 258 Future<Asset> getInput(AssetId id) { | 268 Future<Asset> getInput(AssetId id) { |
| 259 return phase.getInput(id).then((node) { | 269 return phase.previous.getOutput(id).then((node) { |
| 260 // Throw if the input isn't found. This ensures the transformer's apply | 270 // Throw if the input isn't found. This ensures the transformer's apply |
| 261 // is exited. We'll then catch this and report it through the proper | 271 // is exited. We'll then catch this and report it through the proper |
| 262 // results stream. | 272 // results stream. |
| 263 if (node == null) throw new AssetNotFoundException(id); | 273 if (node == null) { |
| 274 _missingInputs.add(id); |
| 275 throw new AssetNotFoundException(id); |
| 276 } |
| 264 | 277 |
| 265 _inputSubscriptions.putIfAbsent(node.id, () { | 278 _inputSubscriptions.putIfAbsent(node.id, () { |
| 266 return node.onStateChange.listen((_) => _dirty(primaryChanged: false)); | 279 return node.onStateChange.listen((_) => _dirty(primaryChanged: false)); |
| 267 }); | 280 }); |
| 268 | 281 |
| 269 return node.asset; | 282 return node.asset; |
| 270 }); | 283 }); |
| 271 } | 284 } |
| 272 | 285 |
| 273 /// Applies the transform so that it produces concrete (as opposed to lazy) | 286 /// Applies the transform so that it produces concrete (as opposed to lazy) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 _onAssetController.add(controller.node); | 390 _onAssetController.add(controller.node); |
| 378 } | 391 } |
| 379 } | 392 } |
| 380 | 393 |
| 381 return false; | 394 return false; |
| 382 }); | 395 }); |
| 383 } | 396 } |
| 384 | 397 |
| 385 /// Cancels all subscriptions to secondary input nodes. | 398 /// Cancels all subscriptions to secondary input nodes. |
| 386 void _clearInputSubscriptions() { | 399 void _clearInputSubscriptions() { |
| 400 _missingInputs.clear(); |
| 387 for (var subscription in _inputSubscriptions.values) { | 401 for (var subscription in _inputSubscriptions.values) { |
| 388 subscription.cancel(); | 402 subscription.cancel(); |
| 389 } | 403 } |
| 390 _inputSubscriptions.clear(); | 404 _inputSubscriptions.clear(); |
| 391 } | 405 } |
| 392 | 406 |
| 393 /// Removes all output assets. | 407 /// Removes all output assets. |
| 394 void _clearOutputs() { | 408 void _clearOutputs() { |
| 395 // Remove all the previously-emitted assets. | 409 // Remove all the previously-emitted assets. |
| 396 for (var controller in _outputControllers.values) { | 410 for (var controller in _outputControllers.values) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 /// | 506 /// |
| 493 /// Specifically, whether [this] is [APPLIED] or [NOT_PRIMARY]. | 507 /// Specifically, whether [this] is [APPLIED] or [NOT_PRIMARY]. |
| 494 bool get isDone => isApplied || isNotPrimary; | 508 bool get isDone => isApplied || isNotPrimary; |
| 495 | 509 |
| 496 final String name; | 510 final String name; |
| 497 | 511 |
| 498 const _TransformNodeState._(this.name); | 512 const _TransformNodeState._(this.name); |
| 499 | 513 |
| 500 String toString() => name; | 514 String toString() => name; |
| 501 } | 515 } |
| OLD | NEW |