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

Side by Side Diff: pkg/polymer/lib/src/build/import_inliner.dart

Issue 293023008: Bring back initPolymer, allow boot.js only if using "polymer_experimental.html". (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/polymer/lib/src/build/common.dart ('k') | pkg/polymer/lib/src/build/linter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 inlines polymer-element definitions from html imports. 5 /// Transfomer that inlines polymer-element definitions from html imports.
6 library polymer.src.build.import_inliner; 6 library polymer.src.build.import_inliner;
7 7
8 import 'dart:async'; 8 import 'dart:async';
9 import 'dart:convert'; 9 import 'dart:convert';
10 10
(...skipping 11 matching lines...) Expand all
22 22
23 // TODO(sigmund): move to web_components package (dartbug.com/18037). 23 // TODO(sigmund): move to web_components package (dartbug.com/18037).
24 class _HtmlInliner extends PolymerTransformer { 24 class _HtmlInliner extends PolymerTransformer {
25 final TransformOptions options; 25 final TransformOptions options;
26 final Transform transform; 26 final Transform transform;
27 final TransformLogger logger; 27 final TransformLogger logger;
28 final AssetId docId; 28 final AssetId docId;
29 final seen = new Set<AssetId>(); 29 final seen = new Set<AssetId>();
30 final scriptIds = <AssetId>[]; 30 final scriptIds = <AssetId>[];
31 final extractedFiles = new Set<AssetId>(); 31 final extractedFiles = new Set<AssetId>();
32 bool experimentalBootstrap = false;
32 33
33 /// The number of extracted inline Dart scripts. Used as a counter to give 34 /// The number of extracted inline Dart scripts. Used as a counter to give
34 /// unique-ish filenames. 35 /// unique-ish filenames.
35 int inlineScriptCounter = 0; 36 int inlineScriptCounter = 0;
36 37
37 _HtmlInliner(this.options, Transform transform) 38 _HtmlInliner(this.options, Transform transform)
38 : transform = transform, 39 : transform = transform,
39 logger = transform.logger, 40 logger = transform.logger,
40 docId = transform.primaryInput.id; 41 docId = transform.primaryInput.id;
41 42
42 Future apply() { 43 Future apply() {
43 seen.add(docId); 44 seen.add(docId);
44 45
45 Document document; 46 Document document;
46 bool changed; 47 bool changed;
47 48
48 return readPrimaryAsHtml(transform).then((doc) { 49 return readPrimaryAsHtml(transform).then((doc) {
49 document = doc; 50 document = doc;
50 // Add the main script's ID, or null if none is present. 51 experimentalBootstrap = document.querySelectorAll('link').any((link) =>
51 // This will be used by ScriptCompactor. 52 link.attributes['rel'] == 'import' &&
53 link.attributes['href'] == POLYMER_EXPERIMENTAL_HTML);
52 changed = _extractScripts(document, docId); 54 changed = _extractScripts(document, docId);
53 return _visitImports(document); 55 return _visitImports(document);
54 }).then((importsFound) { 56 }).then((importsFound) {
55 changed = changed || importsFound; 57 changed = changed || importsFound;
56 return _removeScripts(document); 58 return _removeScripts(document);
57 }).then((scriptsRemoved) { 59 }).then((scriptsRemoved) {
58 changed = changed || scriptsRemoved; 60 changed = changed || scriptsRemoved;
59 61
60 var output = transform.primaryInput; 62 var output = transform.primaryInput;
61 if (changed) output = new Asset.fromString(docId, document.outerHtml); 63 if (changed) output = new Asset.fromString(docId, document.outerHtml);
62 transform.addOutput(output); 64 transform.addOutput(output);
63 65
64 // We produce a secondary asset with extra information for later phases. 66 // We produce a secondary asset with extra information for later phases.
65 transform.addOutput(new Asset.fromString( 67 transform.addOutput(new Asset.fromString(
66 docId.addExtension('.scriptUrls'), 68 docId.addExtension('._data'),
67 JSON.encode(scriptIds, toEncodable: (id) => id.serialize()))); 69 JSON.encode({
70 'experimental_bootstrap': experimentalBootstrap,
71 'script_ids': scriptIds,
72 }, toEncodable: (id) => id.serialize())));
68 }); 73 });
69 } 74 }
70 75
71 /// Visits imports in [document] and add the imported documents to documents. 76 /// Visits imports in [document] and add the imported documents to documents.
72 /// Documents are added in the order they appear, transitive imports are added 77 /// Documents are added in the order they appear, transitive imports are added
73 /// first. 78 /// first.
74 /// 79 ///
75 /// Returns `true` if and only if the document was changed and should be 80 /// Returns `true` if and only if the document was changed and should be
76 /// written out. 81 /// written out.
77 Future<bool> _visitImports(Document document) { 82 Future<bool> _visitImports(Document document) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 // Should we do the same? Alternatively could we inline head into head and 123 // Should we do the same? Alternatively could we inline head into head and
119 // body into body and avoid this whole thing? 124 // body into body and avoid this whole thing?
120 void _moveHeadToBody(Document doc) { 125 void _moveHeadToBody(Document doc) {
121 var insertionPoint = doc.body.firstChild; 126 var insertionPoint = doc.body.firstChild;
122 for (var node in doc.head.nodes.toList(growable: false)) { 127 for (var node in doc.head.nodes.toList(growable: false)) {
123 if (node is! Element) continue; 128 if (node is! Element) continue;
124 var tag = node.localName; 129 var tag = node.localName;
125 var type = node.attributes['type']; 130 var type = node.attributes['type'];
126 var rel = node.attributes['rel']; 131 var rel = node.attributes['rel'];
127 if (tag == 'style' || tag == 'script' && 132 if (tag == 'style' || tag == 'script' &&
128 (type == null || type == TYPE_JS || type == TYPE_DART_APP || 133 (type == null || type == TYPE_JS || type == TYPE_DART) ||
129 type == TYPE_DART_COMPONENT) ||
130 tag == 'link' && (rel == 'stylesheet' || rel == 'import')) { 134 tag == 'link' && (rel == 'stylesheet' || rel == 'import')) {
131 // Move the node into the body, where its contents will be placed. 135 // Move the node into the body, where its contents will be placed.
132 doc.body.insertBefore(node, insertionPoint); 136 doc.body.insertBefore(node, insertionPoint);
133 } 137 }
134 } 138 }
135 } 139 }
136 140
137 /// Loads an asset identified by [id], visits its imports and collects its 141 /// Loads an asset identified by [id], visits its imports and collects its
138 /// html imports. Then inlines it into the main document. 142 /// html imports. Then inlines it into the main document.
139 Future _inlineImport(AssetId id, Element link) { 143 Future _inlineImport(AssetId id, Element link) {
(...skipping 11 matching lines...) Expand all
151 }); 155 });
152 } 156 }
153 157
154 Future _inlineStylesheet(AssetId id, Element link) { 158 Future _inlineStylesheet(AssetId id, Element link) {
155 return transform.readInputAsString(id).then((css) { 159 return transform.readInputAsString(id).then((css) {
156 css = new _UrlNormalizer(transform, id).visitCss(css); 160 css = new _UrlNormalizer(transform, id).visitCss(css);
157 link.replaceWith(new Element.tag('style')..text = css); 161 link.replaceWith(new Element.tag('style')..text = css);
158 }); 162 });
159 } 163 }
160 164
161 /// Remove "application/dart;component=1" scripts and remember their 165 /// Remove all Dart scripts and remember their [AssetId]s for later use.
162 /// [AssetId]s for later use.
163 /// 166 ///
164 /// Dartium only allows a single script tag per page, so we can't inline 167 /// Dartium only allows a single script tag per page, so we can't inline
165 /// the script tags. Instead we remove them entirely. 168 /// the script tags. Instead we remove them entirely.
166 Future<bool> _removeScripts(Document doc) { 169 Future<bool> _removeScripts(Document doc) {
167 bool changed = false; 170 bool changed = false;
168 return Future.forEach(doc.querySelectorAll('script'), (script) { 171 return Future.forEach(doc.querySelectorAll('script'), (script) {
169 if (script.attributes['type'] == TYPE_DART_COMPONENT) { 172 if (script.attributes['type'] == TYPE_DART) {
170 changed = true; 173 changed = true;
171 script.remove(); 174 script.remove();
172 var src = script.attributes['src']; 175 var src = script.attributes['src'];
173 var srcId = uriToAssetId(docId, src, logger, script.sourceSpan); 176 var srcId = uriToAssetId(docId, src, logger, script.sourceSpan);
174 177
175 // We check for extractedFiles because 'hasInput' below is only true for 178 // We check for extractedFiles because 'hasInput' below is only true for
176 // assets that existed before this transformer runs (hasInput is false 179 // assets that existed before this transformer runs (hasInput is false
177 // for files created by [_extractScripts]). 180 // for files created by [_extractScripts]).
178 if (extractedFiles.contains(srcId)) { 181 if (extractedFiles.contains(srcId)) {
179 scriptIds.add(srcId); 182 scriptIds.add(srcId);
(...skipping 10 matching lines...) Expand all
190 } 193 }
191 }).then((_) => changed); 194 }).then((_) => changed);
192 } 195 }
193 196
194 /// Split inline scripts into their own files. We need to do this for dart2js 197 /// Split inline scripts into their own files. We need to do this for dart2js
195 /// to be able to compile them. 198 /// to be able to compile them.
196 /// 199 ///
197 /// This also validates that there weren't any duplicate scripts. 200 /// This also validates that there weren't any duplicate scripts.
198 bool _extractScripts(Document doc, AssetId sourceId) { 201 bool _extractScripts(Document doc, AssetId sourceId) {
199 bool changed = false; 202 bool changed = false;
200 bool first = true;
201 for (var script in doc.querySelectorAll('script')) { 203 for (var script in doc.querySelectorAll('script')) {
202 var type = script.attributes['type']; 204 if (script.attributes['type'] != TYPE_DART) continue;
203 if (type != TYPE_DART_COMPONENT && type != TYPE_DART_APP) continue;
204
205 // only one Dart script per document is supported in Dartium.
206 if (type == TYPE_DART_APP) {
207 if (!first) logger.warning(COMPONENT_WARNING, span: script.sourceSpan);
208 first = false;
209 }
210 205
211 var src = script.attributes['src']; 206 var src = script.attributes['src'];
212 if (src != null) continue; 207 if (src != null) continue;
213 208
214 final filename = path.url.basename(docId.path); 209 final filename = path.url.basename(docId.path);
215 final count = inlineScriptCounter++; 210 final count = inlineScriptCounter++;
216 var code = script.text; 211 var code = script.text;
217 // TODO(sigmund): ensure this path is unique (dartbug.com/12618). 212 // TODO(sigmund): ensure this path is unique (dartbug.com/12618).
218 script.attributes['src'] = src = '$filename.$count.dart'; 213 script.attributes['src'] = src = '$filename.$count.dart';
219 script.text = ''; 214 script.text = '';
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 // is dropped. 262 // is dropped.
268 Future<bool> isPrimary(idOrAsset) { 263 Future<bool> isPrimary(idOrAsset) {
269 var id = idOrAsset is AssetId ? idOrAsset : idOrAsset.id; 264 var id = idOrAsset is AssetId ? idOrAsset : idOrAsset.id;
270 return new Future.value(options.isHtmlEntryPoint(id)); 265 return new Future.value(options.isHtmlEntryPoint(id));
271 } 266 }
272 267
273 Future apply(Transform transform) => 268 Future apply(Transform transform) =>
274 new _HtmlInliner(options, transform).apply(); 269 new _HtmlInliner(options, transform).apply();
275 } 270 }
276 271
277 const TYPE_DART_APP = 'application/dart'; 272 const TYPE_DART = 'application/dart';
278 const TYPE_DART_COMPONENT = 'application/dart;component=1';
279 const TYPE_JS = 'text/javascript'; 273 const TYPE_JS = 'text/javascript';
280 274
281 /// Internally adjusts urls in the html that we are about to inline. 275 /// Internally adjusts urls in the html that we are about to inline.
282 class _UrlNormalizer extends TreeVisitor { 276 class _UrlNormalizer extends TreeVisitor {
283 final Transform transform; 277 final Transform transform;
284 278
285 /// Asset where the original content (and original url) was found. 279 /// Asset where the original content (and original url) was found.
286 final AssetId sourceId; 280 final AssetId sourceId;
287 281
288 _UrlNormalizer(this.transform, this.sourceId); 282 _UrlNormalizer(this.transform, this.sourceId);
289 283
290 visitElement(Element node) { 284 visitElement(Element node) {
291 node.attributes.forEach((name, value) { 285 node.attributes.forEach((name, value) {
292 if (_urlAttributes.contains(name)) { 286 if (_urlAttributes.contains(name)) {
293 if (value != '' && !value.trim().startsWith('{{')) { 287 if (value != '' && !value.trim().startsWith('{{')) {
294 node.attributes[name] = _newUrl(value, node.sourceSpan); 288 node.attributes[name] = _newUrl(value, node.sourceSpan);
295 } 289 }
296 } 290 }
297 }); 291 });
298 if (node.localName == 'style') { 292 if (node.localName == 'style') {
299 node.text = visitCss(node.text); 293 node.text = visitCss(node.text);
300 } else if (node.localName == 'script') { 294 } else if (node.localName == 'script' &&
301 var type = node.attributes['type']; 295 node.attributes['type'] == TYPE_DART) {
302 // TODO(jmesserly): we might need to visit JS too to handle ES Harmony 296 // TODO(jmesserly): we might need to visit JS too to handle ES Harmony
303 // modules. 297 // modules.
304 if (type == TYPE_DART_APP || type == TYPE_DART_COMPONENT) { 298 node.text = visitInlineDart(node.text);
305 node.text = visitInlineDart(node.text);
306 }
307 } 299 }
308 super.visitElement(node); 300 super.visitElement(node);
309 } 301 }
310 302
311 static final _URL = new RegExp(r'url\(([^)]*)\)', multiLine: true); 303 static final _URL = new RegExp(r'url\(([^)]*)\)', multiLine: true);
312 static final _QUOTE = new RegExp('["\']', multiLine: true); 304 static final _QUOTE = new RegExp('["\']', multiLine: true);
313 305
314 /// Visit the CSS text and replace any relative URLs so we can inline it. 306 /// Visit the CSS text and replace any relative URLs so we can inline it.
315 // Ported from: 307 // Ported from:
316 // https://github.com/Polymer/vulcanize/blob/c14f63696797cda18dc3d372b78aa3378 acc691f/lib/vulcan.js#L149 308 // https://github.com/Polymer/vulcanize/blob/c14f63696797cda18dc3d372b78aa3378 acc691f/lib/vulcan.js#L149
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 'formaction', // in button, input 395 'formaction', // in button, input
404 'href', // in a, area, link, base, command 396 'href', // in a, area, link, base, command
405 'icon', // in command 397 'icon', // in command
406 'manifest', // in html 398 'manifest', // in html
407 'poster', // in video 399 'poster', // in video
408 'src', // in audio, embed, iframe, img, input, script, source, track, 400 'src', // in audio, embed, iframe, img, input, script, source, track,
409 // video 401 // video
410 ]; 402 ];
411 403
412 _getSpan(SourceFile file, AstNode node) => file.span(node.offset, node.end); 404 _getSpan(SourceFile file, AstNode node) => file.span(node.offset, node.end);
413
414 const COMPONENT_WARNING =
415 'More than one Dart script per HTML document is not supported, but in the '
416 'near future Dartium will execute each tag as a separate isolate. If this '
417 'code is meant to load definitions that are part of the same application '
418 'you should switch it to use the "application/dart;component=1" mime-type '
419 'instead.';
OLDNEW
« no previous file with comments | « pkg/polymer/lib/src/build/common.dart ('k') | pkg/polymer/lib/src/build/linter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698