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 |