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

Unified Diff: mojo/public/dart/third_party/barback/lib/src/graph/phase_output.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: mojo/public/dart/third_party/barback/lib/src/graph/phase_output.dart
diff --git a/mojo/public/dart/third_party/barback/lib/src/graph/phase_output.dart b/mojo/public/dart/third_party/barback/lib/src/graph/phase_output.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3d6460b657e3d9edcb90f4e82bdf8d22f6acb448
--- /dev/null
+++ b/mojo/public/dart/third_party/barback/lib/src/graph/phase_output.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.graph.phase_output;
+
+import 'dart:async';
+import 'dart:collection';
+
+import '../asset/asset_forwarder.dart';
+import '../asset/asset_node.dart';
+import '../errors.dart';
+import 'phase.dart';
+
+/// A class that handles a single output of a phase.
+///
+/// Normally there's only a single [AssetNode] for a phase's output, but it's
+/// possible that multiple transformers in the same phase emit assets with the
+/// same id, causing collisions. This handles those collisions by forwarding the
+/// chronologically first asset.
+///
+/// When the asset being forwarding changes, the old value of [output] will be
+/// marked as removed and a new value will replace it. Users of this class can
+/// be notified of this using [onAsset].
+class PhaseOutput {
+ /// The phase for which this is an output.
+ final Phase _phase;
+
+ /// A string describing the location of [this] in the transformer graph.
+ final String _location;
+
+ /// The asset node for this output.
+ AssetNode get output => _outputForwarder.node;
+ AssetForwarder _outputForwarder;
+
+ /// A stream that emits an [AssetNode] each time this output starts forwarding
+ /// a new asset.
+ Stream<AssetNode> get onAsset => _onAssetController.stream;
+ final _onAssetController =
+ new StreamController<AssetNode>.broadcast(sync: true);
+
+ /// The assets for this output.
+ ///
+ /// If there's no collision, this will only have one element. Otherwise, it
+ /// will be ordered by which asset was added first.
+ final _assets = new Queue<AssetNode>();
+
+ /// The [AssetCollisionException] for this output, or null if there is no
+ /// collision currently.
+ AssetCollisionException get collisionException {
+ if (_assets.length == 1) return null;
+ return new AssetCollisionException(
+ _assets.where((asset) => asset.transform != null)
+ .map((asset) => asset.transform.info),
+ output.id);
+ }
+
+ PhaseOutput(this._phase, AssetNode output, this._location)
+ : _outputForwarder = new AssetForwarder(output) {
+ assert(!output.state.isRemoved);
+ add(output);
+ }
+
+ /// Adds an asset node as an output with this id.
+ void add(AssetNode node) {
+ assert(node.id == output.id);
+ assert(!output.state.isRemoved);
+ _assets.add(node);
+ _watchAsset(node);
+ }
+
+ /// Removes all existing listeners on [output] without actually closing
+ /// [this].
+ ///
+ /// This marks [output] as removed, but immediately replaces it with a new
+ /// [AssetNode] in the same state as the old output. This is used when adding
+ /// a new [Phase] to cause consumers of the prior phase's outputs to be to
+ /// start consuming the new phase's outputs instead.
+ void removeListeners() {
+ _outputForwarder.close();
+ _outputForwarder = new AssetForwarder(_assets.first);
+ _onAssetController.add(output);
+ }
+
+ /// Watches [node] to adjust [_assets] and [output] when it's removed.
+ void _watchAsset(AssetNode node) {
+ node.whenRemoved(() {
+ if (_assets.length == 1) {
+ assert(_assets.single == node);
+ _outputForwarder.close();
+ _onAssetController.close();
+ return;
+ }
+
+ // If there was more than one asset, we're resolving a collision --
+ // possibly partially.
+ var wasFirst = _assets.first == node;
+ _assets.remove(node);
+
+ // If this was the first asset, we replace it with the next asset
+ // (chronologically).
+ if (wasFirst) removeListeners();
+
+ // If there's still a collision, report it. This lets the user know if
+ // they've successfully resolved the collision or not.
+ if (_assets.length > 1) {
+ // TODO(nweiz): report this through the output asset.
+ _phase.cascade.reportError(collisionException);
+ }
+ });
+ }
+
+ String toString() => "phase output in $_location for $output";
+}

Powered by Google App Engine
This is Rietveld 408576698