| OLD | NEW |
| 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 /// Transfomer that combines multiple dart script tags into a single one. | 5 /// Transfomer that combines multiple dart script tags into a single one. |
| 6 library polymer.src.build.script_compactor; | 6 library polymer.src.build.script_compactor; |
| 7 | 7 |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 import 'dart:convert'; | 9 import 'dart:convert'; |
| 10 | 10 |
| 11 import 'package:html5lib/dom.dart' show Document, Element, Text; | 11 import 'package:html5lib/dom.dart' show Document, Element, Text; |
| 12 import 'package:html5lib/dom_parsing.dart'; | 12 import 'package:html5lib/dom_parsing.dart'; |
| 13 import 'package:html5lib/parser.dart' show parseFragment; |
| 13 import 'package:analyzer/src/generated/ast.dart'; | 14 import 'package:analyzer/src/generated/ast.dart'; |
| 14 import 'package:analyzer/src/generated/element.dart' hide Element; | 15 import 'package:analyzer/src/generated/element.dart' hide Element; |
| 15 import 'package:analyzer/src/generated/element.dart' as analyzer show Element; | 16 import 'package:analyzer/src/generated/element.dart' as analyzer show Element; |
| 16 import 'package:barback/barback.dart'; | 17 import 'package:barback/barback.dart'; |
| 17 import 'package:code_transformers/assets.dart'; | 18 import 'package:code_transformers/assets.dart'; |
| 18 import 'package:path/path.dart' as path; | 19 import 'package:path/path.dart' as path; |
| 19 import 'package:source_maps/span.dart' show SourceFile; | 20 import 'package:source_maps/span.dart' show SourceFile; |
| 20 import 'package:smoke/codegen/generator.dart'; | 21 import 'package:smoke/codegen/generator.dart'; |
| 21 import 'package:smoke/codegen/recorder.dart'; | 22 import 'package:smoke/codegen/recorder.dart'; |
| 22 import 'package:code_transformers/resolver.dart'; | 23 import 'package:code_transformers/resolver.dart'; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 final AssetId docId; | 64 final AssetId docId; |
| 64 final AssetId bootstrapId; | 65 final AssetId bootstrapId; |
| 65 | 66 |
| 66 /// HTML document parsed from [docId]. | 67 /// HTML document parsed from [docId]. |
| 67 Document document; | 68 Document document; |
| 68 | 69 |
| 69 /// List of ids for each Dart entry script tag (the main tag and any tag | 70 /// List of ids for each Dart entry script tag (the main tag and any tag |
| 70 /// included on each custom element definition). | 71 /// included on each custom element definition). |
| 71 List<AssetId> entryLibraries; | 72 List<AssetId> entryLibraries; |
| 72 | 73 |
| 73 /// The id of the main Dart program. | |
| 74 AssetId mainLibraryId; | |
| 75 | |
| 76 /// Script tag that loads the Dart entry point. | |
| 77 Element mainScriptTag; | |
| 78 | |
| 79 /// Initializers that will register custom tags or invoke `initMethod`s. | 74 /// Initializers that will register custom tags or invoke `initMethod`s. |
| 80 final List<_Initializer> initializers = []; | 75 final List<_Initializer> initializers = []; |
| 81 | 76 |
| 82 /// Attributes published on a custom-tag. We make these available via | 77 /// Attributes published on a custom-tag. We make these available via |
| 83 /// reflection even if @published was not used. | 78 /// reflection even if @published was not used. |
| 84 final Map<String, List<String>> publishedAttributes = {}; | 79 final Map<String, List<String>> publishedAttributes = {}; |
| 85 | 80 |
| 86 /// Hook needed to access the analyzer within barback transformers. | 81 /// Hook needed to access the analyzer within barback transformers. |
| 87 final Resolvers resolvers; | 82 final Resolvers resolvers; |
| 88 | 83 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 118 |
| 124 /// Removes unnecessary script tags, and identifies the main entry point Dart | 119 /// Removes unnecessary script tags, and identifies the main entry point Dart |
| 125 /// script tag (if any). | 120 /// script tag (if any). |
| 126 void _processHtml(_) { | 121 void _processHtml(_) { |
| 127 for (var tag in document.querySelectorAll('script')) { | 122 for (var tag in document.querySelectorAll('script')) { |
| 128 var src = tag.attributes['src']; | 123 var src = tag.attributes['src']; |
| 129 if (src == 'packages/polymer/boot.js') { | 124 if (src == 'packages/polymer/boot.js') { |
| 130 tag.remove(); | 125 tag.remove(); |
| 131 continue; | 126 continue; |
| 132 } | 127 } |
| 133 if (tag.attributes['type'] != 'application/dart') continue; | 128 if (tag.attributes['type'] == 'application/dart;component=1') { |
| 134 if (src == null) { | 129 logger.warning('unexpected script. The ' |
| 135 logger.warning('unexpected script without a src url. The ' | |
| 136 'ScriptCompactor transformer should run after running the ' | 130 'ScriptCompactor transformer should run after running the ' |
| 137 'InlineCodeExtractor', span: tag.sourceSpan); | 131 'ImportInliner', span: tag.sourceSpan); |
| 138 continue; | |
| 139 } | 132 } |
| 140 if (mainLibraryId != null) { | |
| 141 logger.warning('unexpected script. Only one Dart script tag ' | |
| 142 'per document is allowed.', span: tag.sourceSpan); | |
| 143 tag.remove(); | |
| 144 continue; | |
| 145 } | |
| 146 mainLibraryId = uriToAssetId(docId, src, logger, tag.sourceSpan); | |
| 147 mainScriptTag = tag; | |
| 148 } | 133 } |
| 149 } | 134 } |
| 150 | 135 |
| 151 /// Emits the main HTML and Dart bootstrap code for the application. If there | 136 /// Emits the main HTML and Dart bootstrap code for the application. If there |
| 152 /// were not Dart entry point files, then this simply emits the original HTML. | 137 /// were not Dart entry point files, then this simply emits the original HTML. |
| 153 Future _emitNewEntrypoint(_) { | 138 Future _emitNewEntrypoint(_) { |
| 154 if (mainScriptTag == null) { | 139 if (entryLibraries.isEmpty) { |
| 155 // We didn't find any main library, nothing to do. | 140 // We didn't find code, nothing to do. |
| 156 transform.addOutput(transform.primaryInput); | 141 transform.addOutput(transform.primaryInput); |
| 157 return null; | 142 return null; |
| 158 } | 143 } |
| 159 | 144 |
| 160 // Emit the bootstrap .dart file | |
| 161 mainScriptTag.attributes['src'] = path.url.basename(bootstrapId.path); | |
| 162 entryLibraries.add(mainLibraryId); | |
| 163 | |
| 164 return _initResolver() | 145 return _initResolver() |
| 165 .then(_extractUsesOfMirrors) | 146 .then(_extractUsesOfMirrors) |
| 166 .then(_emitFiles) | 147 .then(_emitFiles) |
| 167 .then((_) => resolver.release()); | 148 .whenComplete(() => resolver.release()); |
| 168 } | 149 } |
| 169 | 150 |
| 170 /// Load a resolver that computes information for every library in | 151 /// Load a resolver that computes information for every library in |
| 171 /// [entryLibraries], then use it to initialize the [recorder] (for import | 152 /// [entryLibraries], then use it to initialize the [recorder] (for import |
| 172 /// resolution) and to resolve specific elements (for analyzing the user's | 153 /// resolution) and to resolve specific elements (for analyzing the user's |
| 173 /// code). | 154 /// code). |
| 174 Future _initResolver() => resolvers.get(transform, entryLibraries).then((r) { | 155 Future _initResolver() => resolvers.get(transform, entryLibraries).then((r) { |
| 175 resolver = r; | 156 resolver = r; |
| 176 types = new _ResolvedTypes(resolver); | 157 types = new _ResolvedTypes(resolver); |
| 177 }); | 158 }); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 code.writeln("import '$url' as i$i;"); | 333 code.writeln("import '$url' as i$i;"); |
| 353 prefixes[id] = 'i$i'; | 334 prefixes[id] = 'i$i'; |
| 354 i++; | 335 i++; |
| 355 } | 336 } |
| 356 | 337 |
| 357 // Include smoke initialization. | 338 // Include smoke initialization. |
| 358 generator.writeImports(code); | 339 generator.writeImports(code); |
| 359 generator.writeTopLevelDeclarations(code); | 340 generator.writeTopLevelDeclarations(code); |
| 360 code.writeln('\nvoid main() {'); | 341 code.writeln('\nvoid main() {'); |
| 361 generator.writeInitCall(code); | 342 generator.writeInitCall(code); |
| 362 code.writeln(' configureForDeployment(['); | 343 code.writeln(' startPolymer(['); |
| 363 | 344 |
| 364 // Include initializers to switch from mirrors_loader to static_loader. | 345 // Include initializers to switch from mirrors_loader to static_loader. |
| 365 for (var init in initializers) { | 346 for (var init in initializers) { |
| 366 var initCode = init.asCode(prefixes[init.assetId]); | 347 var initCode = init.asCode(prefixes[init.assetId]); |
| 367 code.write(" $initCode,\n"); | 348 code.write(" $initCode,\n"); |
| 368 } | 349 } |
| 369 code..writeln(' ]);') | 350 code..writeln(' ]);') |
| 370 ..writeln(' i${entryLibraries.length - 1}.main();') | |
| 371 ..writeln('}'); | 351 ..writeln('}'); |
| 372 transform.addOutput(new Asset.fromString(bootstrapId, code.toString())); | 352 transform.addOutput(new Asset.fromString(bootstrapId, code.toString())); |
| 353 |
| 354 |
| 355 // Emit the bootstrap .dart file |
| 356 var srcUrl = path.url.basename(bootstrapId.path); |
| 357 document.body.nodes.add(parseFragment( |
| 358 '<script type="application/dart" src="$srcUrl"></script>')); |
| 373 transform.addOutput(new Asset.fromString(docId, document.outerHtml)); | 359 transform.addOutput(new Asset.fromString(docId, document.outerHtml)); |
| 374 } | 360 } |
| 375 | 361 |
| 376 _spanForNode(analyzer.Element context, AstNode node) { | 362 _spanForNode(analyzer.Element context, AstNode node) { |
| 377 var file = resolver.getSourceFile(context); | 363 var file = resolver.getSourceFile(context); |
| 378 return file.span(node.offset, node.end); | 364 return file.span(node.offset, node.end); |
| 379 } | 365 } |
| 380 } | 366 } |
| 381 | 367 |
| 382 abstract class _Initializer { | 368 abstract class _Initializer { |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 for (var c in combinators) { | 684 for (var c in combinators) { |
| 699 if (c is ShowElementCombinator) { | 685 if (c is ShowElementCombinator) { |
| 700 var show = c.shownNames.toSet(); | 686 var show = c.shownNames.toSet(); |
| 701 elements.retainWhere((e) => show.contains(e.displayName)); | 687 elements.retainWhere((e) => show.contains(e.displayName)); |
| 702 } else if (c is HideElementCombinator) { | 688 } else if (c is HideElementCombinator) { |
| 703 var hide = c.hiddenNames.toSet(); | 689 var hide = c.hiddenNames.toSet(); |
| 704 elements.removeWhere((e) => hide.contains(e.displayName)); | 690 elements.removeWhere((e) => hide.contains(e.displayName)); |
| 705 } | 691 } |
| 706 } | 692 } |
| 707 } | 693 } |
| OLD | NEW |