perf(dart/transform): Only process deferred libs when necessary
Previously, every .dart file in a package was processed to ensure proper initialization of deferred loaded libraries. Update the transformer to avoid processing libraries which we know do not import any deferred libraries. Closes #6745
This commit is contained in:
parent
3a40cd79f0
commit
f56df65d48
|
@ -6,6 +6,7 @@ const SETUP_METHOD_NAME = 'initReflector';
|
|||
const REFLECTOR_VAR_NAME = 'reflector';
|
||||
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
||||
const CSS_EXTENSION = '.css';
|
||||
const DEFERRED_EXTENSION = '.dart.deferredCount';
|
||||
const SHIMMED_STYLESHEET_EXTENSION = '.css.shim.dart';
|
||||
const NON_SHIMMED_STYLESHEET_EXTENSION = '.css.dart';
|
||||
const META_EXTENSION = '.ng_meta.json';
|
||||
|
@ -21,8 +22,10 @@ const TEMPLATE_EXTENSION = '.template.dart';
|
|||
|
||||
/// Note that due to the implementation of `_toExtension`, ordering is
|
||||
/// important. For example, putting '.dart' first in this list will cause
|
||||
/// incorrect behavior.
|
||||
/// incorrect behavior because it will (incompletely) match '.template.dart'
|
||||
/// files.
|
||||
const ALL_EXTENSIONS = const [
|
||||
DEFERRED_EXTENSION,
|
||||
META_EXTENSION,
|
||||
SUMMARY_META_EXTENSION,
|
||||
TEMPLATE_EXTENSION,
|
||||
|
@ -36,6 +39,7 @@ const ALL_EXTENSIONS = const [
|
|||
/// any files named like transformer outputs will be reported as generated.
|
||||
bool isGenerated(String uri) {
|
||||
return const [
|
||||
DEFERRED_EXTENSION,
|
||||
META_EXTENSION,
|
||||
NON_SHIMMED_STYLESHEET_EXTENSION,
|
||||
SHIMMED_STYLESHEET_EXTENSION,
|
||||
|
@ -44,6 +48,10 @@ bool isGenerated(String uri) {
|
|||
].any((ext) => uri.endsWith(ext));
|
||||
}
|
||||
|
||||
/// Returns `uri` with its extension updated to [DEFERRED_EXTENSION].
|
||||
String toDeferredExtension(String uri) =>
|
||||
_toExtension(uri, ALL_EXTENSIONS, DEFERRED_EXTENSION);
|
||||
|
||||
/// Returns `uri` with its extension updated to [META_EXTENSION].
|
||||
String toMetaExtension(String uri) =>
|
||||
_toExtension(uri, ALL_EXTENSIONS, META_EXTENSION);
|
||||
|
|
|
@ -14,7 +14,7 @@ import 'rewriter.dart';
|
|||
/// Transformer responsible for rewriting deferred library loads to enable
|
||||
/// initializing the reflector in a deferred way to keep the code with the
|
||||
/// deferred library.
|
||||
class DeferredRewriter extends Transformer implements LazyTransformer {
|
||||
class DeferredRewriter extends AggregateTransformer implements LazyTransformer {
|
||||
final TransformerOptions options;
|
||||
|
||||
DeferredRewriter(this.options);
|
||||
|
@ -25,23 +25,60 @@ class DeferredRewriter extends Transformer implements LazyTransformer {
|
|||
}
|
||||
|
||||
@override
|
||||
bool isPrimary(AssetId id) =>
|
||||
id.extension.endsWith('dart') && _isNotGenerated(id);
|
||||
dynamic classifyPrimary(AssetId id) {
|
||||
// Map <name>.dart and <name>.dart.deferredCount => <name>.
|
||||
// Anything else to `null`.
|
||||
var extension = null;
|
||||
if (id.path.endsWith(DEFERRED_EXTENSION)) {
|
||||
extension = DEFERRED_EXTENSION;
|
||||
} else if (id.path.endsWith('.dart') && !isGenerated(id.path)) {
|
||||
extension = '.dart';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return id.path.substring(0, id.path.length - extension.length);
|
||||
}
|
||||
|
||||
@override
|
||||
Future apply(Transform transform) async {
|
||||
Future apply(AggregateTransform transform) async {
|
||||
return zone.exec(() async {
|
||||
var asset = transform.primaryInput;
|
||||
var reader = new AssetReader.fromTransform(transform);
|
||||
var transformedCode = await rewriteDeferredLibraries(reader, asset.id);
|
||||
final dartAsset = await _assetToProcess(transform);
|
||||
if (dartAsset == null) return;
|
||||
|
||||
var transformedCode = await rewriteDeferredLibraries(
|
||||
new AssetReader.fromTransform(transform), dartAsset.id);
|
||||
if (transformedCode != null) {
|
||||
transform.addOutput(new Asset.fromString(asset.id, transformedCode));
|
||||
transform
|
||||
.addOutput(new Asset.fromString(dartAsset.id, transformedCode));
|
||||
}
|
||||
}, log: transform.logger);
|
||||
}
|
||||
}
|
||||
|
||||
bool _isNotGenerated(AssetId id) => !isGenerated(id.path);
|
||||
/// Returns the asset we need to process or `null` if none exists.
|
||||
///
|
||||
/// Consumes the .dart.deferredCount asset if it is present.
|
||||
Future<Asset> _assetToProcess(AggregateTransform transform) async {
|
||||
// We only need to process .dart files that have an associated
|
||||
// .dart.deferredCount file with a value != "0".
|
||||
//
|
||||
// The .dart.deferredCount file is generated by a previous phase for files
|
||||
// which have deferred imports. An absent .dart.deferredCount asset is the
|
||||
// treated the same as a .dart.deferredCount asset with value "0".
|
||||
var dartAsset, deferredCountAsset;
|
||||
await for (Asset a in transform.primaryInputs) {
|
||||
if (a.id.path.endsWith(DEFERRED_EXTENSION)) {
|
||||
deferredCountAsset = a;
|
||||
} else if (a.id.path.endsWith('.dart')) {
|
||||
dartAsset = a;
|
||||
}
|
||||
}
|
||||
if (deferredCountAsset == null) return null;
|
||||
// No longer necessary.
|
||||
transform.consumePrimary(deferredCountAsset.id);
|
||||
if ((await deferredCountAsset.readAsString()) == "0") return null;
|
||||
return dartAsset;
|
||||
}
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
Future<String> rewriteDeferredLibraries(AssetReader reader, AssetId id) async {
|
||||
|
|
|
@ -33,6 +33,7 @@ class DirectiveProcessor extends Transformer implements LazyTransformer {
|
|||
|
||||
@override
|
||||
declareOutputs(DeclaringTransform transform) {
|
||||
transform.declareOutput(_deferredAssetId(transform.primaryId));
|
||||
transform.declareOutput(_ngSummaryAssetId(transform.primaryId));
|
||||
}
|
||||
|
||||
|
@ -49,6 +50,17 @@ class DirectiveProcessor extends Transformer implements LazyTransformer {
|
|||
}
|
||||
transform.addOutput(new Asset.fromString(
|
||||
_ngSummaryAssetId(primaryId), _encoder.convert(ngMeta.toJson())));
|
||||
|
||||
var deferredCount = 0;
|
||||
if (ngMeta.ngDeps != null) {
|
||||
deferredCount = ngMeta.ngDeps.imports.where((i) => i.isDeferred).length;
|
||||
}
|
||||
if (deferredCount > 0) {
|
||||
// The existence of this file with the value != "0" signals
|
||||
// DeferredRewriter that the associated .dart file needs attention.
|
||||
transform.addOutput(new Asset.fromString(
|
||||
_deferredAssetId(primaryId), deferredCount.toString()));
|
||||
}
|
||||
}, log: transform.logger);
|
||||
}
|
||||
}
|
||||
|
@ -57,3 +69,8 @@ AssetId _ngSummaryAssetId(AssetId primaryInputId) {
|
|||
return new AssetId(
|
||||
primaryInputId.package, toSummaryExtension(primaryInputId.path));
|
||||
}
|
||||
|
||||
AssetId _deferredAssetId(AssetId primaryInputId) {
|
||||
return new AssetId(
|
||||
primaryInputId.package, toDeferredExtension(primaryInputId.path));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue