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

Unified Diff: pkg/polymer/lib/src/build/script_compactor.dart

Issue 189213003: Refactoring two pieces of polymer: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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/polymer/lib/src/build/mirrors_remover.dart ('k') | pkg/polymer/lib/src/declaration.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/polymer/lib/src/build/script_compactor.dart
diff --git a/pkg/polymer/lib/src/build/script_compactor.dart b/pkg/polymer/lib/src/build/script_compactor.dart
index 9f26e22acab22396713f577482ce7dc99cf8a69d..1d0328d044034240bd1c47ea535ab0aa9cc1b134 100644
--- a/pkg/polymer/lib/src/build/script_compactor.dart
+++ b/pkg/polymer/lib/src/build/script_compactor.dart
@@ -8,6 +8,7 @@ library polymer.src.build.script_compactor;
import 'dart:async';
import 'dart:convert';
+import 'package:html5lib/dom.dart' show Document, Element;
import 'package:analyzer/src/generated/ast.dart';
import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
@@ -26,7 +27,7 @@ import 'common.dart';
/// Internally, this transformer will convert each script tag into an import
/// statement to a library, and then uses `initPolymer` (see polymer.dart) to
/// process `@initMethod` and `@CustomTag` annotations in those libraries.
-class ScriptCompactor extends Transformer with PolymerTransformer {
+class ScriptCompactor extends Transformer {
final TransformOptions options;
ScriptCompactor(this.options);
@@ -35,95 +36,134 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
Future<bool> isPrimary(Asset input) =>
new Future.value(options.isHtmlEntryPoint(input.id));
- Future apply(Transform transform) {
- var id = transform.primaryInput.id;
- var secondaryId = id.addExtension('.scriptUrls');
- var logger = transform.logger;
- return readPrimaryAsHtml(transform).then((document) {
- return transform.readInputAsString(secondaryId).then((libraryIds) {
- var libraries = (JSON.decode(libraryIds) as Iterable).map(
- (data) => new AssetId.deserialize(data)).toList();
- var mainLibraryId;
- var mainScriptTag;
- bool changed = false;
-
- for (var tag in document.querySelectorAll('script')) {
- var src = tag.attributes['src'];
- if (src == 'packages/polymer/boot.js') {
- tag.remove();
- continue;
- }
- if (tag.attributes['type'] != 'application/dart') continue;
- if (src == null) {
- logger.warning('unexpected script without a src url. The '
- 'ScriptCompactor transformer should run after running the '
- 'InlineCodeExtractor', span: tag.sourceSpan);
- continue;
- }
- if (mainLibraryId != null) {
- logger.warning('unexpected script. Only one Dart script tag '
- 'per document is allowed.', span: tag.sourceSpan);
- tag.remove();
- continue;
- }
- mainLibraryId = resolve(id, src, logger, tag.sourceSpan);
- mainScriptTag = tag;
- }
+ Future apply(Transform transform) =>
+ new _ScriptCompactor(transform, options).apply();
+}
- if (mainScriptTag == null) {
- // We didn't find any main library, nothing to do.
- transform.addOutput(transform.primaryInput);
- return null;
- }
+/// Helper class mainly use to flatten the async code.
+class _ScriptCompactor extends PolymerTransformer {
+ final TransformOptions options;
+ final Transform transform;
+ final TransformLogger logger;
+ final AssetId docId;
+ final AssetId bootstrapId;
+
+ Document document;
+ List<AssetId> entryLibraries;
+ AssetId mainLibraryId;
+ Element mainScriptTag;
+ final Map<AssetId, List<_Initializer>> initializers = {};
+
+ _ScriptCompactor(Transform transform, this.options)
+ : transform = transform,
+ logger = transform.logger,
+ docId = transform.primaryInput.id,
+ bootstrapId = transform.primaryInput.id.addExtension('_bootstrap.dart');
+
+ Future apply() =>
+ _loadDocument()
+ .then(_loadEntryLibraries)
+ .then(_processHtml)
+ .then(_emitNewEntrypoint);
+
+ /// Loads the primary input as an html document.
+ Future _loadDocument() =>
+ readPrimaryAsHtml(transform).then((doc) { document = doc; });
+
+ /// Populates [entryLibraries] as a list containing the asset ids of each
+ /// library loaded on a script tag. The actual work of computing this is done
+ /// in an earlier phase and emited in the `entrypoint.scriptUrls` asset.
+ Future _loadEntryLibraries(_) =>
+ transform.readInputAsString(docId.addExtension('.scriptUrls'))
+ .then((libraryIds) {
+ entryLibraries = (JSON.decode(libraryIds) as Iterable)
+ .map((data) => new AssetId.deserialize(data)).toList();
+ });
- // Emit the bootstrap .dart file
- var bootstrapId = id.addExtension('_bootstrap.dart');
- mainScriptTag.attributes['src'] =
- path.url.basename(bootstrapId.path);
-
- libraries.add(mainLibraryId);
- var urls = libraries.map((id) => assetUrlFor(id, bootstrapId, logger))
- .where((url) => url != null).toList();
- var buffer = new StringBuffer()..writeln(MAIN_HEADER);
- int i = 0;
- for (; i < urls.length; i++) {
- buffer.writeln("import '${urls[i]}' as i$i;");
- }
+ /// Removes unnecessary script tags, and identifies the main entry point Dart
+ /// script tag (if any).
+ void _processHtml(_) {
+ for (var tag in document.querySelectorAll('script')) {
+ var src = tag.attributes['src'];
+ if (src == 'packages/polymer/boot.js') {
+ tag.remove();
+ continue;
+ }
+ if (tag.attributes['type'] != 'application/dart') continue;
+ if (src == null) {
+ logger.warning('unexpected script without a src url. The '
+ 'ScriptCompactor transformer should run after running the '
+ 'InlineCodeExtractor', span: tag.sourceSpan);
+ continue;
+ }
+ if (mainLibraryId != null) {
+ logger.warning('unexpected script. Only one Dart script tag '
+ 'per document is allowed.', span: tag.sourceSpan);
+ tag.remove();
+ continue;
+ }
+ mainLibraryId = resolve(docId, src, logger, tag.sourceSpan);
+ mainScriptTag = tag;
+ }
+ }
- buffer..write('\n')
- ..writeln('void main() {')
- ..writeln(' configureForDeployment([');
-
- // Inject @CustomTag and @initMethod initializations for each library
- // that is sourced in a script tag.
- i = 0;
- return Future.forEach(libraries, (lib) {
- return _initializersOf(lib, transform, logger).then((initializers) {
- for (var init in initializers) {
- var code = init.asCode('i$i');
- buffer.write(" $code,\n");
- }
- i++;
- });
- }).then((_) {
- buffer..writeln(' ]);')
- ..writeln(' i${urls.length - 1}.main();')
- ..writeln('}');
-
- transform.addOutput(new Asset.fromString(
- bootstrapId, buffer.toString()));
- transform.addOutput(new Asset.fromString(id, document.outerHtml));
- });
- });
+ /// Emits the main HTML and Dart bootstrap code for the application. If there
+ /// were not Dart entry point files, then this simply emits the original HTML.
+ Future _emitNewEntrypoint(_) {
+ if (mainScriptTag == null) {
+ // We didn't find any main library, nothing to do.
+ transform.addOutput(transform.primaryInput);
+ return null;
+ }
+
+ // Emit the bootstrap .dart file
+ mainScriptTag.attributes['src'] = path.url.basename(bootstrapId.path);
+ entryLibraries.add(mainLibraryId);
+ return _computeInitializers().then(_createBootstrapCode).then((code) {
+ transform.addOutput(new Asset.fromString(bootstrapId, code));
+ transform.addOutput(new Asset.fromString(docId, document.outerHtml));
});
}
+ /// Emits the actual bootstrap code.
+ String _createBootstrapCode(_) {
+ StringBuffer code = new StringBuffer()..writeln(MAIN_HEADER);
+ for (int i = 0; i < entryLibraries.length; i++) {
+ var url = assetUrlFor(entryLibraries[i], bootstrapId, logger);
+ if (url != null) code.writeln("import '$url' as i$i;");
+ }
+
+ code..write('\n')
+ ..writeln('void main() {')
+ ..writeln(' configureForDeployment([');
+
+ // Inject @CustomTag and @initMethod initializations for each library
+ // that is sourced in a script tag.
+ for (int i = 0; i < entryLibraries.length; i++) {
+ for (var init in initializers[entryLibraries[i]]) {
+ var initCode = init.asCode('i$i');
+ code.write(" $initCode,\n");
+ }
+ }
+ code..writeln(' ]);')
+ ..writeln(' i${entryLibraries.length - 1}.main();')
+ ..writeln('}');
+ return code.toString();
+ }
+
+ /// Computes initializers needed for each library in [entryLibraries]. Results
+ /// are available afterwards in [initializers].
+ Future _computeInitializers() => Future.forEach(entryLibraries, (lib) {
+ return _initializersOf(lib).then((res) {
+ initializers[lib] = res;
+ });
+ });
+
/// Computes the initializers of [dartLibrary]. That is, a closure that calls
/// Polymer.register for each @CustomTag, and any public top-level methods
/// labeled with @initMethod.
- Future<List<_Initializer>> _initializersOf(
- AssetId dartLibrary, Transform transform, TransformLogger logger) {
- var initializers = [];
+ Future<List<_Initializer>> _initializersOf(AssetId dartLibrary) {
+ var result = [];
return transform.readInputAsString(dartLibrary).then((code) {
var file = new SourceFile.text(_simpleUriForSource(dartLibrary), code);
var unit = parseCompilationUnit(code);
@@ -133,8 +173,7 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
if (directive is PartDirective) {
var targetId = resolve(dartLibrary, directive.uri.stringValue,
logger, _getSpan(file, directive));
- return _initializersOf(targetId, transform, logger)
- .then(initializers.addAll);
+ return _initializersOf(targetId).then(result.addAll);
}
// Similarly, include anything from exports except what's filtered by
@@ -142,20 +181,20 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
if (directive is ExportDirective) {
var targetId = resolve(dartLibrary, directive.uri.stringValue,
logger, _getSpan(file, directive));
- return _initializersOf(targetId, transform, logger)
- .then((r) => _processExportDirective(directive, r, initializers));
+ return _initializersOf(targetId).then(
+ (r) => _processExportDirective(directive, r, result));
}
}).then((_) {
// Scan the code for classes and top-level functions.
for (var node in unit.declarations) {
if (node is ClassDeclaration) {
- _processClassDeclaration(node, initializers, file, logger);
+ _processClassDeclaration(node, result, file, logger);
} else if (node is FunctionDeclaration &&
node.metadata.any(_isInitMethodAnnotation)) {
- _processFunctionDeclaration(node, initializers, file, logger);
+ _processFunctionDeclaration(node, result, file, logger);
}
}
- return initializers;
+ return result;
});
});
}
@@ -165,11 +204,11 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
? 'package:${source.package}/${source.path.substring(4)}' : source.path;
/// Filter [exportedInitializers] according to [directive]'s show/hide
- /// combinators and add the result to [initializers].
+ /// combinators and add the result to [result].
// TODO(sigmund): call the analyzer's resolver instead?
static _processExportDirective(ExportDirective directive,
List<_Initializer> exportedInitializers,
- List<_Initializer> initializers) {
+ List<_Initializer> result) {
for (var combinator in directive.combinators) {
if (combinator is ShowCombinator) {
var show = combinator.shownNames.map((n) => n.name).toSet();
@@ -179,13 +218,13 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
exportedInitializers.removeWhere((e) => hide.contains(e.symbolName));
}
}
- initializers.addAll(exportedInitializers);
+ result.addAll(exportedInitializers);
}
/// Add an initializer to register [node] as a polymer element if it contains
/// an appropriate [CustomTag] annotation.
static _processClassDeclaration(ClassDeclaration node,
- List<_Initializer> initializers, SourceFile file,
+ List<_Initializer> result, SourceFile file,
TransformLogger logger) {
for (var meta in node.metadata) {
if (!_isCustomTagAnnotation(meta)) continue;
@@ -203,13 +242,13 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
'classes: $tagName', span: _getSpan(file, node.name));
continue;
}
- initializers.add(new _CustomTagInitializer(tagName, typeName));
+ result.add(new _CustomTagInitializer(tagName, typeName));
}
}
/// Add a method initializer for [function].
static _processFunctionDeclaration(FunctionDeclaration function,
- List<_Initializer> initializers, SourceFile file,
+ List<_Initializer> result, SourceFile file,
TransformLogger logger) {
var name = function.name.name;
if (name.startsWith('_')) {
@@ -217,7 +256,7 @@ class ScriptCompactor extends Transformer with PolymerTransformer {
'functions: $name', span: _getSpan(file, function.name));
return;
}
- initializers.add(new _InitMethodInitializer(name));
+ result.add(new _InitMethodInitializer(name));
}
}
@@ -256,4 +295,5 @@ const MAIN_HEADER = """
library app_bootstrap;
import 'package:polymer/polymer.dart';
+import 'package:smoke/static.dart' as smoke;
""";
« no previous file with comments | « pkg/polymer/lib/src/build/mirrors_remover.dart ('k') | pkg/polymer/lib/src/declaration.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698