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

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

Issue 18650004: Make Assets know their ID. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 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
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; 5 library barback.phase;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'asset.dart'; 9 import 'asset.dart';
10 import 'asset_graph.dart'; 10 import 'asset_graph.dart';
(...skipping 24 matching lines...) Expand all
35 35
36 /// The transformers that can access [inputs]. 36 /// The transformers that can access [inputs].
37 /// 37 ///
38 /// Their outputs will be available to the next phase. 38 /// Their outputs will be available to the next phase.
39 final List<Transformer> _transformers; 39 final List<Transformer> _transformers;
40 40
41 /// The inputs that are available for transforms in this phase to consume. 41 /// The inputs that are available for transforms in this phase to consume.
42 /// 42 ///
43 /// For the first phase, these will be the source assets. For all other 43 /// For the first phase, these will be the source assets. For all other
44 /// phases, they will be the outputs from the previous phase. 44 /// phases, they will be the outputs from the previous phase.
45 final inputs = new Map<AssetId, AssetNode>(); 45 final inputs = new Map<AssetId, AssetNode>();
nweiz 2013/07/03 20:08:25 If you get rid of AssetNode, this could just be an
Bob Nystrom 2013/07/03 22:32:11 See previous comment.
46 46
47 /// The transforms currently applicable to assets in [inputs]. 47 /// The transforms currently applicable to assets in [inputs].
48 /// 48 ///
49 /// These are the transforms that have been "wired up": they represent a 49 /// These are the transforms that have been "wired up": they represent a
50 /// repeatable transformation of a single concrete set of inputs. "dart2js" 50 /// repeatable transformation of a single concrete set of inputs. "dart2js"
51 /// is a transformer. "dart2js on web/main.dart" is a transform. 51 /// is a transformer. "dart2js on web/main.dart" is a transform.
52 final _transforms = new Set<TransformNode>(); 52 final _transforms = new Set<TransformNode>();
53 53
54 /// The nodes that are new in this phase since the last time [process] was 54 /// The nodes that are new in this phase since the last time [process] was
55 /// called. 55 /// called.
56 /// 56 ///
57 /// When we process, we'll check these to see if we can hang new transforms 57 /// When we process, we'll check these to see if we can hang new transforms
58 /// off them. 58 /// off them.
59 final _newInputs = new Set<AssetNode>(); 59 final _newInputs = new Set<AssetNode>();
60 60
61 /// The phase after this one. 61 /// The phase after this one.
62 /// 62 ///
63 /// Outputs from this phase will be passed to it. 63 /// Outputs from this phase will be passed to it.
64 final Phase _next; 64 final Phase _next;
65 65
66 Phase(this.graph, this._index, this._transformers, this._next); 66 Phase(this.graph, this._index, this._transformers, this._next);
67 67
68 /// Updates the phase's inputs with [updated] and removes [removed]. 68 /// Updates the phase's inputs with [updated] and removes [removed].
69 /// 69 ///
70 /// This marks any affected [transforms] as dirty or discards them if their 70 /// This marks any affected [transforms] as dirty or discards them if their
71 /// inputs are removed. 71 /// inputs are removed.
72 void updateInputs(Map<AssetId, Asset> updated, Set<AssetId> removed) { 72 void updateInputs(Set<Asset> updated, Set<AssetId> removed) {
73 // Remove any nodes that are no longer being output. Handle removals first 73 // Remove any nodes that are no longer being output. Handle removals first
74 // in case there are assets that were removed by one transform but updated 74 // in case there are assets that were removed by one transform but updated
75 // by another. In that case, the update should win. 75 // by another. In that case, the update should win.
76 for (var id in removed) { 76 for (var id in removed) {
77 var node = inputs.remove(id); 77 var node = inputs.remove(id);
78 78
79 // Every transform that was using it is dirty now. 79 // Every transform that was using it is dirty now.
80 if (node != null) { 80 if (node != null) {
81 node.consumers.forEach((consumer) => consumer.dirty()); 81 node.consumers.forEach((consumer) => consumer.dirty());
82 } 82 }
83 } 83 }
84 84
85 // Update and new or modified assets. 85 // Update and new or modified assets.
86 updated.forEach((id, asset) { 86 for (var asset in updated) {
87 var node = inputs.putIfAbsent(id, () => new AssetNode(id)); 87 var node = inputs[asset.id];
88 88 if (node == null) {
89 // If it's a new node, remember that so we can see if any new transforms 89 // It's a new node. Add it and remember it so we can see if any new
90 // will consume it. 90 // transforms will consume it.
91 if (node.asset == null) _newInputs.add(node); 91 node = new AssetNode(asset);
92 92 inputs[asset.id] = node;
93 node.updateAsset(asset); 93 _newInputs.add(node);
94 }); 94 } else {
95 node.updateAsset(asset);
96 }
97 }
95 } 98 }
96 99
97 /// Processes this phase. 100 /// Processes this phase.
98 /// 101 ///
99 /// For all new inputs, it tries to see if there are transformers that can 102 /// For all new inputs, it tries to see if there are transformers that can
100 /// consume them. Then all applicable transforms are applied. 103 /// consume them. Then all applicable transforms are applied.
101 /// 104 ///
102 /// Returns a future that completes when processing is done. If there is 105 /// Returns a future that completes when processing is done. If there is
103 /// nothing to process, returns `null`. 106 /// nothing to process, returns `null`.
104 Future process() { 107 Future process() {
105 var future = _processNewInputs(); 108 var future = _processNewInputs();
106 if (future == null) { 109 if (future == null) {
107 return _processTransforms(); 110 return _processTransforms();
108 } 111 }
109 112
110 return future.then((_) => _processTransforms()); 113 return future.then((_) => _processTransforms());
111 } 114 }
112 115
113 /// Creates new transforms for any new inputs that are applicable. 116 /// Creates new transforms for any new inputs that are applicable.
114 Future _processNewInputs() { 117 Future _processNewInputs() {
115 if (_newInputs.isEmpty) return null; 118 if (_newInputs.isEmpty) return null;
116 119
117 var futures = []; 120 var futures = [];
118 for (var node in _newInputs) { 121 for (var node in _newInputs) {
119 for (var transformer in _transformers) { 122 for (var transformer in _transformers) {
120 // TODO(rnystrom): Catch all errors from isPrimary() and redirect 123 // TODO(rnystrom): Catch all errors from isPrimary() and redirect
121 // to results. 124 // to results.
122 futures.add(transformer.isPrimary(node.id).then((isPrimary) { 125 futures.add(transformer.isPrimary(node.asset).then((isPrimary) {
123 if (!isPrimary) return; 126 if (!isPrimary) return;
124 var transform = new TransformNode(this, transformer, node); 127 var transform = new TransformNode(this, transformer, node);
125 node.consumers.add(transform); 128 node.consumers.add(transform);
126 _transforms.add(transform); 129 _transforms.add(transform);
127 })); 130 }));
128 } 131 }
129 } 132 }
130 133
131 _newInputs.clear(); 134 _newInputs.clear();
132 135
133 return Future.wait(futures); 136 return Future.wait(futures);
134 } 137 }
135 138
136 /// Applies all currently wired up and dirty transforms. 139 /// Applies all currently wired up and dirty transforms.
137 /// 140 ///
138 /// Passes their outputs to the next phase. 141 /// Passes their outputs to the next phase.
139 Future _processTransforms() { 142 Future _processTransforms() {
140 var dirtyTransforms = _transforms.where((transform) => transform.isDirty); 143 var dirtyTransforms = _transforms.where((transform) => transform.isDirty);
141 if (dirtyTransforms.isEmpty) return null; 144 if (dirtyTransforms.isEmpty) return null;
142 145
143 return Future.wait(dirtyTransforms.map((transform) => transform.apply())) 146 return Future.wait(dirtyTransforms.map((transform) => transform.apply()))
144 .then((transformOutputs) { 147 .then((transformOutputs) {
145 // Collect all of the outputs. Since the transforms are run in parallel, 148 // Collect all of the outputs. Since the transforms are run in parallel,
146 // we have to be careful here to ensure that the result is deterministic 149 // we have to be careful here to ensure that the result is deterministic
147 // and not influenced by the order that transforms complete. 150 // and not influenced by the order that transforms complete.
148 var updated = new Map<AssetId, Asset>(); 151 var updated = new Set<Asset>();
152 var updatedIds = new Set<AssetId>();
nweiz 2013/07/03 20:08:25 Another good place for AssetSet.
Bob Nystrom 2013/07/03 22:32:11 Done.
149 var removed = new Set<AssetId>(); 153 var removed = new Set<AssetId>();
150 var collisions = new Set<AssetId>(); 154 var collisions = new Set<AssetId>();
151 155
152 // Handle the generated outputs of all transforms first. 156 // Handle the generated outputs of all transforms first.
153 for (var outputs in transformOutputs) { 157 for (var outputs in transformOutputs) {
154 // Collect the outputs of all transformers together. 158 // Collect the outputs of all transformers together.
155 outputs.updated.forEach((id, asset) { 159 for (var asset in outputs.updated) {
156 if (updated.containsKey(id)) { 160 if (updatedIds.contains(asset.id)) {
157 // Report a collision. 161 // Report a collision.
158 collisions.add(id); 162 collisions.add(asset.id);
159 } else { 163 } else {
160 // TODO(rnystrom): In the case of a collision, the asset that 164 // TODO(rnystrom): In the case of a collision, the asset that
161 // "wins" is chosen non-deterministically. Do something better. 165 // "wins" is chosen non-deterministically. Do something better.
162 updated[id] = asset; 166 updated.add(asset);
167 updatedIds.add(asset.id);
163 } 168 }
164 }); 169 }
165 170
166 // Track any assets no longer output by this transform. We don't 171 // Track any assets no longer output by this transform. We don't
167 // handle the case where *another* transform generates the asset 172 // handle the case where *another* transform generates the asset
168 // no longer generated by this one. updateInputs() handles that. 173 // no longer generated by this one. updateInputs() handles that.
169 removed.addAll(outputs.removed); 174 removed.addAll(outputs.removed);
170 } 175 }
171 176
172 // Report any collisions in deterministic order. 177 // Report any collisions in deterministic order.
173 collisions = collisions.toList(); 178 collisions = collisions.toList();
174 collisions.sort((a, b) => a.toString().compareTo(b.toString())); 179 collisions.sort((a, b) => a.toString().compareTo(b.toString()));
175 for (var collision in collisions) { 180 for (var collision in collisions) {
176 graph.reportError(new AssetCollisionException(collision)); 181 graph.reportError(new AssetCollisionException(collision));
177 // TODO(rnystrom): Define what happens after a collision occurs. 182 // TODO(rnystrom): Define what happens after a collision occurs.
178 } 183 }
179 184
180 // Pass the outputs to the next phase. 185 // Pass the outputs to the next phase.
181 _next.updateInputs(updated, removed); 186 _next.updateInputs(updated, removed);
182 }); 187 });
183 } 188 }
184 } 189 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698