| Index: pkg/barback/lib/src/phase_input.dart
|
| diff --git a/pkg/barback/lib/src/phase_input.dart b/pkg/barback/lib/src/phase_input.dart
|
| index 3506560da0ef4cc5898357ca8323c5eac93591f9..aafbb90415486f22ff9ead29d9f75e46fec5f44e 100644
|
| --- a/pkg/barback/lib/src/phase_input.dart
|
| +++ b/pkg/barback/lib/src/phase_input.dart
|
| @@ -10,6 +10,7 @@ import 'dart:collection';
|
| import 'asset.dart';
|
| import 'asset_forwarder.dart';
|
| import 'asset_node.dart';
|
| +import 'asset_node_set.dart';
|
| import 'errors.dart';
|
| import 'log.dart';
|
| import 'phase.dart';
|
| @@ -45,18 +46,21 @@ class PhaseInput {
|
| /// The asset node for this input.
|
| AssetNode get input => _inputForwarder.node;
|
|
|
| - /// The controller that's used for the output node if [input] isn't consumed
|
| - /// by any transformers.
|
| + /// The controller that's used for the output node if [input] isn't
|
| + /// overwritten by any transformers.
|
| ///
|
| /// This needs an intervening controller to ensure that the output can be
|
| - /// marked dirty when determining whether transforms apply, and removed if
|
| - /// they do. It's null if the asset is not being passed through.
|
| + /// marked dirty when determining whether transforms will overwrite it, and be
|
| + /// marked removed if they do. It's null if the asset is not being passed
|
| + /// through.
|
| AssetNodeController _passThroughController;
|
|
|
| /// Whether [_passThroughController] has been newly created since [process]
|
| /// last completed.
|
| bool _newPassThrough = false;
|
|
|
| + final _outputs = new AssetNodeSet();
|
| +
|
| /// A Future that will complete once the transformers that consume [input] are
|
| /// determined.
|
| Future _adjustTransformersFuture;
|
| @@ -137,12 +141,6 @@ class PhaseInput {
|
| });
|
| }
|
|
|
| - if (_transforms.isEmpty && _adjustTransformersFuture == null &&
|
| - _passThroughController == null) {
|
| - _passThroughController = new AssetNodeController.from(input);
|
| - _newPassThrough = true;
|
| - }
|
| -
|
| var brandNewTransformers = newTransformers.difference(oldTransformers);
|
| if (brandNewTransformers.isEmpty) return;
|
|
|
| @@ -170,8 +168,8 @@ class PhaseInput {
|
| // kick off a build, even if that build does nothing.
|
| _onDirtyController.add(null);
|
|
|
| - // If there's a pass-through for this input, mark it dirty while we figure
|
| - // out whether we need to add any transforms for it.
|
| + // If there's a pass-through for this input, mark it dirty until we figure
|
| + // out if a transformer will emit an asset with that id.
|
| if (_passThroughController != null) _passThroughController.setDirty();
|
|
|
| // Once the input is available, hook up transformers for it. If it changes
|
| @@ -243,34 +241,15 @@ class PhaseInput {
|
| var transform = new TransformNode(
|
| _phase, transformer, input, _location);
|
| _transforms.add(transform);
|
| + transform.onDirty.listen((_) {
|
| + if (_passThroughController != null) _passThroughController.setDirty();
|
| + });
|
| _onDirtyPool.add(transform.onDirty);
|
| _onLogPool.add(transform.onLog);
|
| });
|
| }));
|
| }
|
|
|
| - /// Adjust whether [input] is passed through the phase unmodified, based on
|
| - /// whether it's consumed by other transforms in this phase.
|
| - ///
|
| - /// If [input] was already passed-through, this will update the passed-through
|
| - /// value.
|
| - void _adjustPassThrough() {
|
| - assert(input.state.isAvailable);
|
| -
|
| - if (_transforms.isEmpty) {
|
| - if (_passThroughController != null) {
|
| - _passThroughController.setAvailable(input.asset);
|
| - } else {
|
| - _passThroughController = new AssetNodeController.from(input);
|
| - _newPassThrough = true;
|
| - }
|
| - } else if (_passThroughController != null) {
|
| - _passThroughController.setRemoved();
|
| - _passThroughController = null;
|
| - _newPassThrough = false;
|
| - }
|
| - }
|
| -
|
| /// Like [AssetNode.tryUntilStable], but also re-runs [callback] if this
|
| /// phase's transformers are modified.
|
| Future _tryUntilStable(
|
| @@ -291,8 +270,27 @@ class PhaseInput {
|
| /// for this input. The assets returned this way are guaranteed not to be
|
| /// [AssetState.REMOVED].
|
| Future<Set<AssetNode>> process() {
|
| - return _waitForTransformers(() => _processTransforms()).then((outputs) {
|
| + return _waitForTransformers(() {
|
| + if (input.state.isRemoved) return new Future.value(new Set());
|
| +
|
| + return Future.wait(_transforms.map((transform) {
|
| + if (!transform.isDirty) return new Future.value(new Set());
|
| + return transform.apply();
|
| + })).then((outputs) => unionAll(outputs));
|
| + }).then((outputs) {
|
| if (input.state.isRemoved) return new Set();
|
| +
|
| + for (var output in outputs) {
|
| + assert(!output.state.isRemoved);
|
| + _outputs.add(output);
|
| + output.whenRemoved(_adjustPassThrough);
|
| + }
|
| +
|
| + _adjustPassThrough();
|
| + if (_newPassThrough) {
|
| + outputs.add(_passThroughController.node);
|
| + _newPassThrough = false;
|
| + }
|
| return outputs;
|
| });
|
| }
|
| @@ -309,21 +307,30 @@ class PhaseInput {
|
| (_) => _waitForTransformers(callback));
|
| }
|
|
|
| - /// Applies all currently wired up and dirty transforms.
|
| - Future<Set<AssetNode>> _processTransforms() {
|
| - if (input.state.isRemoved) return new Future.value(new Set());
|
| + /// Adjust whether [input] is passed through the phase unmodified, based on
|
| + /// whether it's overwritten by other transforms in this phase.
|
| + ///
|
| + /// If [input] was already passed-through, this will update the passed-through
|
| + /// value.
|
| + void _adjustPassThrough() {
|
| + if (!input.state.isAvailable) return;
|
|
|
| - if (_passThroughController != null) {
|
| - if (!_newPassThrough) return new Future.value(new Set());
|
| - _newPassThrough = false;
|
| - return new Future.value(
|
| - new Set<AssetNode>.from([_passThroughController.node]));
|
| + // If there's an output with the same id as the primary input, that
|
| + // overwrites the input so it doesn't get passed through. Otherwise,
|
| + // create a pass-through controller if none exists, or set the existing
|
| + // one available.
|
| + if (_outputs.any((output) => output.id == input.id)) {
|
| + if (_passThroughController != null) {
|
| + _passThroughController.setRemoved();
|
| + _passThroughController = null;
|
| + _newPassThrough = false;
|
| + }
|
| + } else if (_passThroughController == null) {
|
| + _passThroughController = new AssetNodeController.from(input);
|
| + _newPassThrough = true;
|
| + } else if (_passThroughController.node.state.isDirty) {
|
| + _passThroughController.setAvailable(input.asset);
|
| }
|
| -
|
| - return Future.wait(_transforms.map((transform) {
|
| - if (!transform.isDirty) return new Future.value(new Set());
|
| - return transform.apply();
|
| - })).then((outputs) => unionAll(outputs));
|
| }
|
|
|
| String toString() => "phase input in $_location for $input";
|
|
|