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

Unified Diff: pkg/barback/lib/src/transform_node.dart

Issue 149243009: Add support for lazy transformers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 10 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
« no previous file with comments | « pkg/barback/lib/src/transform_logger.dart ('k') | pkg/barback/lib/src/transformer.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/barback/lib/src/transform_node.dart
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 8a79b6c6cd5df1ded2a88cc0b3c61f2e1871e9e3..bba950a825c5d82c536fe2d9c5e3f8fda554cea6 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -12,11 +12,14 @@ import 'asset.dart';
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
+import 'declaring_transform.dart';
import 'errors.dart';
+import 'lazy_transformer.dart';
import 'log.dart';
import 'phase.dart';
import 'transform.dart';
import 'transformer.dart';
+import 'utils.dart';
/// Describes a transform on a set of assets and its relationship to the build
/// dependency graph.
@@ -44,6 +47,9 @@ class TransformNode {
bool get isDirty => _isDirty;
var _isDirty = true;
+ /// Whether [transformer] is lazy and this transform has yet to be forced.
+ bool _isLazy;
+
/// The subscriptions to each input's [AssetNode.onStateChange] stream.
var _inputSubscriptions = new Map<AssetId, StreamSubscription>();
@@ -67,7 +73,10 @@ class TransformNode {
Stream<LogEntry> get onLog => _onLogController.stream;
final _onLogController = new StreamController<LogEntry>.broadcast(sync: true);
- TransformNode(this.phase, this.transformer, this.primary, this._location) {
+ TransformNode(this.phase, Transformer transformer, this.primary,
+ this._location)
+ : transformer = transformer,
+ _isLazy = transformer is LazyTransformer {
_primarySubscription = primary.onStateChange.listen((state) {
if (state.isRemoved) {
remove();
@@ -101,6 +110,16 @@ class TransformNode {
}
}
+ /// If [transformer] is lazy, ensures that its concrete outputs will be
+ /// generated.
+ void force() {
+ // TODO(nweiz): we might want to have a timeout after which, if the
+ // transform's outputs have gone unused, we switch it back to lazy mode.
+ if (!_isLazy) return;
+ _isLazy = false;
+ _dirty();
+ }
+
/// Marks this transform as dirty.
///
/// This causes all of the transform's outputs to be marked as dirty as well.
@@ -119,9 +138,6 @@ class TransformNode {
Future<Set<AssetNode>> apply() {
assert(!_onDirtyController.isClosed);
- var newOutputs = new AssetSet();
- var transform = createTransform(this, newOutputs, _log);
-
// Clear all the old input subscriptions. If an input is re-used, we'll
// re-subscribe.
for (var subscription in _inputSubscriptions.values) {
@@ -131,25 +147,26 @@ class TransformNode {
_isDirty = false;
- return transformer.apply(transform).catchError((error, stack) {
+ return syncFuture(() {
+ // TODO(nweiz): If [transformer] is a [DeclaringTransformer] but not a
+ // [LazyTransformer], we can get some mileage out of doing a declarative
+ // first so we know how to hook up the assets.
+ if (_isLazy) return _declareLazy();
+ return _applyImmediate();
+ }).catchError((error, stackTrace) {
// If the transform became dirty while processing, ignore any errors from
// it.
- if (_isDirty) return;
+ if (_isDirty) return new Set();
if (error is! MissingInputException) {
- error = new TransformerException(info, error, stack);
+ error = new TransformerException(info, error, stackTrace);
}
- // Catch all transformer errors and pipe them to the results stream.
- // This is so a broken transformer doesn't take down the whole graph.
+ // Catch all transformer errors and pipe them to the results stream. This
+ // is so a broken transformer doesn't take down the whole graph.
phase.cascade.reportError(error);
- // Don't allow partial results from a failed transform.
- newOutputs.clear();
- }).then((_) {
- if (_isDirty) return new Set();
-
- return _adjustOutputs(newOutputs);
+ return new Set();
});
}
@@ -180,40 +197,88 @@ class TransformNode {
});
}
- /// Adjusts the outputs of the transform to reflect the outputs emitted on its
- /// most recent run.
- Set<AssetNode> _adjustOutputs(AssetSet newOutputs) {
- // Any ids that are for a different package are invalid.
- var invalidIds = newOutputs
- .map((asset) => asset.id)
- .where((id) => id.package != phase.cascade.package)
- .toSet();
- for (var id in invalidIds) {
- newOutputs.removeId(id);
- // TODO(nweiz): report this as a warning rather than a failing error.
- phase.cascade.reportError(new InvalidOutputException(info, id));
- }
+ /// Applies the transform so that it produces concrete (as opposed to lazy)
+ /// outputs.
+ Future<Set<AssetNode>> _applyImmediate() {
+ var newOutputs = new AssetSet();
+ var transform = new Transform(this, newOutputs, _log);
- // Remove outputs that used to exist but don't anymore.
- for (var id in _outputControllers.keys.toList()) {
- if (newOutputs.containsId(id)) continue;
- _outputControllers.remove(id).setRemoved();
- }
+ return syncFuture(() => transformer.apply(transform)).then((_) {
+ if (_isDirty) return new Set();
- var brandNewOutputs = new Set<AssetNode>();
- // Store any new outputs or new contents for existing outputs.
- for (var asset in newOutputs) {
- var controller = _outputControllers[asset.id];
- if (controller != null) {
- controller.setAvailable(asset);
- } else {
- var controller = new AssetNodeController.available(asset, this);
- _outputControllers[asset.id] = controller;
- brandNewOutputs.add(controller.node);
+ // Any ids that are for a different package are invalid.
+ var invalidIds = newOutputs
+ .map((asset) => asset.id)
+ .where((id) => id.package != phase.cascade.package)
+ .toSet();
+ for (var id in invalidIds) {
+ newOutputs.removeId(id);
+ // TODO(nweiz): report this as a warning rather than a failing error.
+ phase.cascade.reportError(new InvalidOutputException(info, id));
+ }
+
+ // Remove outputs that used to exist but don't anymore.
+ for (var id in _outputControllers.keys.toList()) {
+ if (newOutputs.containsId(id)) continue;
+ _outputControllers.remove(id).setRemoved();
}
- }
- return brandNewOutputs;
+ var brandNewOutputs = new Set<AssetNode>();
+ // Store any new outputs or new contents for existing outputs.
+ for (var asset in newOutputs) {
+ var controller = _outputControllers[asset.id];
+ if (controller != null) {
+ controller.setAvailable(asset);
+ } else {
+ var controller = new AssetNodeController.available(asset, this);
+ _outputControllers[asset.id] = controller;
+ brandNewOutputs.add(controller.node);
+ }
+ }
+
+ return brandNewOutputs;
+ });
+ }
+
+ /// Applies the transform in declarative mode so that it produces lazy
+ /// outputs.
+ Future<Set<AssetNode>> _declareLazy() {
+ var newIds = new Set();
+ var transform = new DeclaringTransform(this, newIds, _log);
+
+ return syncFuture(() {
+ return (transformer as LazyTransformer).declareOutputs(transform);
+ }).then((_) {
+ if (_isDirty) return new Set();
+
+ var invalidIds =
+ newIds.where((id) => id.package != phase.cascade.package).toSet();
+ for (var id in invalidIds) {
+ newIds.remove(id);
+ // TODO(nweiz): report this as a warning rather than a failing error.
+ phase.cascade.reportError(new InvalidOutputException(info, id));
+ }
+
+ // Remove outputs that used to exist but don't anymore.
+ for (var id in _outputControllers.keys.toList()) {
+ if (newIds.contains(id)) continue;
+ _outputControllers.remove(id).setRemoved();
+ }
+
+ var brandNewOutputs = new Set<AssetNode>();
+ for (var id in newIds) {
+ var controller = _outputControllers[id];
+ if (controller != null) {
+ controller.setLazy(force);
+ } else {
+ var controller = new AssetNodeController.lazy(id, force, this);
+ _outputControllers[id] = controller;
+ brandNewOutputs.add(controller.node);
+ }
+ }
+
+ return brandNewOutputs;
+ });
}
void _log(AssetId asset, LogLevel level, String message, Span span) {
« no previous file with comments | « pkg/barback/lib/src/transform_logger.dart ('k') | pkg/barback/lib/src/transformer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698