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

Side by Side Diff: lib/src/mirror_initializer.dart

Issue 1052523004: add console error about bad packages paths in html imports (Closed) Base URL: git@github.com:dart-lang/web-components.git@master
Patch Set: fix version in changelog to match pubspec Created 5 years, 8 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
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 /// Contains logic to initialize web_components apps during development. This 5 /// Contains logic to initialize web_components apps during development. This
6 /// implementation uses dart:mirrors to load each library as they are discovered 6 /// implementation uses dart:mirrors to load each library as they are discovered
7 /// through HTML imports. This is only meant to be used during development in 7 /// through HTML imports. This is only meant to be used during development in
8 /// dartium, and the web_components transformers replace this implementation 8 /// dartium, and the web_components transformers replace this implementation
9 /// for deployment. 9 /// for deployment.
10 library web_components.src.mirror_initializer; 10 library web_components.src.mirror_initializer;
11 11
12 import 'dart:async'; 12 import 'dart:async';
13 import 'dart:collection' show LinkedHashMap; 13 import 'dart:collection' show LinkedHashMap;
14 import 'dart:mirrors'; 14 import 'dart:mirrors';
15 import 'dart:html'; 15 import 'dart:html';
16 import 'package:initialize/initialize.dart' as init; 16 import 'package:initialize/initialize.dart' as init;
17 import 'package:path/path.dart' show url;
17 18
18 const bool deployMode = false; 19 const bool deployMode = false;
19 20
20 Future run({List<Type> typeFilter, init.InitializerFilter customFilter}) async { 21 Future run({List<Type> typeFilter, init.InitializerFilter customFilter}) async {
21 var libraryUris = _discoverLibrariesToLoad(document, window.location.href) 22 var libraryUris =
22 .map(Uri.parse); 23 _discoverLibrariesToLoad(document, window.location.href).map(Uri.parse);
23 24
24 for (var uri in libraryUris) { 25 for (var uri in libraryUris) {
25 await init.run( 26 await init.run(
26 typeFilter: typeFilter, customFilter: customFilter, from: uri); 27 typeFilter: typeFilter, customFilter: customFilter, from: uri);
27 } 28 }
29
30 _validatePackageImports(document);
28 return null; 31 return null;
29 } 32 }
30 33
31 /// Walks the HTML import structure to discover all script tags that are 34 /// Walks the HTML import structure to discover all script tags that are
32 /// implicitly loaded. This code is only used in Dartium and should only be 35 /// implicitly loaded. This code is only used in Dartium and should only be
33 /// called after all HTML imports are resolved. Polymer ensures this by asking 36 /// called after all HTML imports are resolved. Polymer ensures this by asking
34 /// users to put their Dart script tags after all HTML imports (this is checked 37 /// users to put their Dart script tags after all HTML imports (this is checked
35 /// by the linter, and Dartium will otherwise show an error message). 38 /// by the linter, and Dartium will otherwise show an error message).
36 Iterable<_ScriptInfo> _discoverScripts( 39 Iterable<_ScriptInfo> _discoverScripts(Document doc, String baseUri,
37 Document doc, String baseUri, [_State state]) { 40 [_State state]) {
38 if (state == null) state = new _State(); 41 if (state == null) state = new _State();
39 if (doc == null) { 42 if (doc == null) {
40 print('warning: $baseUri not found.'); 43 print('warning: $baseUri not found.');
41 return state.scripts.values; 44 return state.scripts.values;
42 } 45 }
43 if (!state.seen.add(doc)) return state.scripts.values; 46 if (!state.seen.add(doc)) return state.scripts.values;
44 47
45 for (var node in doc.querySelectorAll('script,link[rel="import"]')) { 48 for (var node in doc.querySelectorAll('script,link[rel="import"]')) {
46 if (node is LinkElement) { 49 if (node is LinkElement) {
47 _discoverScripts(node.import, node.href, state); 50 _discoverScripts(node.import, node.href, state);
(...skipping 27 matching lines...) Expand all
75 78
76 /// Whether it seems to be a 'package:' URL (starts with the package-root). 79 /// Whether it seems to be a 'package:' URL (starts with the package-root).
77 bool get isPackage => packageUrl != null; 80 bool get isPackage => packageUrl != null;
78 81
79 /// The equivalent 'package:' URL, if any. 82 /// The equivalent 'package:' URL, if any.
80 final String packageUrl; 83 final String packageUrl;
81 84
82 _ScriptInfo(this.resolvedUrl, {this.packageUrl}); 85 _ScriptInfo(this.resolvedUrl, {this.packageUrl});
83 } 86 }
84 87
85
86 // TODO(sigmund): explore other (cheaper) ways to resolve URIs relative to the 88 // TODO(sigmund): explore other (cheaper) ways to resolve URIs relative to the
87 // root library (see dartbug.com/12612) 89 // root library (see dartbug.com/12612)
88 final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri; 90 final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
89 91
90 /// Returns [_ScriptInfo] for [script] which was seen in [baseUri]. 92 /// Returns [_ScriptInfo] for [script] which was seen in [baseUri].
91 _ScriptInfo _scriptInfoFor(script, baseUri) { 93 _ScriptInfo _scriptInfoFor(script, baseUri) {
92 var uriString = script.src; 94 var uriString = script.src;
93 if (uriString != '') { 95 if (uriString != '') {
94 var uri = _rootUri.resolve(uriString); 96 var uri = _rootUri.resolve(uriString);
95 if (!_isHttpStylePackageUrl(uri)) return new _ScriptInfo('$uri'); 97 if (!_isHttpStylePackageUrl(uri)) return new _ScriptInfo('$uri');
96 // Use package: urls if available. This rule here is more permissive than 98 // Use package: urls if available. This rule here is more permissive than
97 // how we translate urls in polymer-build, but we expect Dartium to limit 99 // how we translate urls in polymer-build, but we expect Dartium to limit
98 // the cases where there are differences. The polymer-build issues an error 100 // the cases where there are differences. The polymer-build issues an error
99 // when using packages/ inside lib without properly stepping out all the way 101 // when using packages/ inside lib without properly stepping out all the way
100 // to the packages folder. If users don't create symlinks in the source 102 // to the packages folder. If users don't create symlinks in the source
101 // tree, then Dartium will also complain because it won't find the file seen 103 // tree, then Dartium will also complain because it won't find the file seen
102 // in an HTML import. 104 // in an HTML import.
103 var packagePath = uri.path.substring( 105 var packagePath = uri.path
104 uri.path.lastIndexOf('packages/') + 'packages/'.length); 106 .substring(uri.path.lastIndexOf('packages/') + 'packages/'.length);
105 return new _ScriptInfo('$uri', packageUrl: 'package:$packagePath'); 107 return new _ScriptInfo('$uri', packageUrl: 'package:$packagePath');
106 } 108 }
107 109
108 // Even in the case of inline scripts its ok to just use the baseUri since 110 // Even in the case of inline scripts its ok to just use the baseUri since
109 // there can only be one per page. 111 // there can only be one per page.
110 return new _ScriptInfo(baseUri); 112 return new _ScriptInfo(baseUri);
111 } 113 }
112 114
113 /// Whether [uri] is an http URI that contains a 'packages' segment, and 115 /// Whether [uri] is an http URI that contains a 'packages' segment, and
114 /// therefore could be converted into a 'package:' URI. 116 /// therefore could be converted into a 'package:' URI.
115 bool _isHttpStylePackageUrl(Uri uri) { 117 bool _isHttpStylePackageUrl(Uri uri) {
116 var uriPath = uri.path; 118 var uriPath = uri.path;
117 return uri.scheme == _rootUri.scheme && 119 return uri.scheme == _rootUri.scheme &&
118 // Don't process cross-domain uris. 120 // Don't process cross-domain uris.
119 uri.authority == _rootUri.authority && 121 uri.authority == _rootUri.authority &&
120 uriPath.endsWith('.dart') && 122 uriPath.endsWith('.dart') &&
121 (uriPath.contains('/packages/') || uriPath.startsWith('packages/')); 123 (uriPath.contains('/packages/') || uriPath.startsWith('packages/'));
122 } 124 }
123 125
124 Iterable<String> _discoverLibrariesToLoad(Document doc, String baseUri) => 126 Iterable<String> _discoverLibrariesToLoad(Document doc, String baseUri) =>
125 _discoverScripts(doc, baseUri).map( 127 _discoverScripts(doc, baseUri).map(
126 (info) => _packageUrlExists(info) ? info.packageUrl : info.resolvedUrl); 128 (info) => _packageUrlExists(info) ? info.packageUrl : info.resolvedUrl);
127 129
128 /// All libraries in the current isolate. 130 /// All libraries in the current isolate.
129 final _libs = currentMirrorSystem().libraries; 131 final _libs = currentMirrorSystem().libraries;
130 132
131 bool _packageUrlExists(_ScriptInfo info) => 133 bool _packageUrlExists(_ScriptInfo info) =>
132 info.isPackage && _libs[Uri.parse(info.packageUrl)] != null; 134 info.isPackage && _libs[Uri.parse(info.packageUrl)] != null;
135
136 /// All the imports that we have checked for package path validation.
137 final _importsSeen = new Set<LinkElement>();
138
139 /// All the documents that we have crawled for import validation.
140 final _documentsSeen = new Set<Document>();
141
142 /// Validates that all html imports to packages urls point to the right packages
143 /// symlink (the one next to the entry point).
144 void _validatePackageImports(Document doc) {
145 var imports = doc.querySelectorAll('link[rel="import"]');
146 for (LinkElement import in imports) {
147 // Don't re-validate imports.
148 if (!_importsSeen.add(import)) continue;
149
150 // Check that the href points to the right packages path. If it doesn't we
151 // don't continue checking as it will print extraneous errors.
152 if (import.href.contains('packages/') && !_checkPackagePath(import)) {
153 continue;
154 }
155
156 // Validate any imports contained in this import, if the document hasn't yet
157 // been seen.
158 var importDoc = import.import;
159 if (!_documentsSeen.add(importDoc)) continue;
160 _validatePackageImports(importDoc);
161 }
162 }
163
164 /// The path to the entry document.
165 final entryPath = document.baseUri;
166
167 /// Checks that the relative path from the entry point to all packages imports
168 /// starts with `packages/`.
169 bool _checkPackagePath(LinkElement import) {
170 var pathFromEntryPoint =
171 url.relative(import.href, from: url.dirname(entryPath));
172 if (pathFromEntryPoint.startsWith('packages/')) return true;
173
174 LinkElement correctedImport = import.clone(false);
175
176 var relativeUriParts = url.split(
177 url.relative(import.ownerDocument.baseUri, from: url.dirname(entryPath)));
178 var pathToEntryPoint = '../' * (relativeUriParts.length - 1);
179 var packagePath = import.href.substring(import.href.indexOf('packages/'));
180 correctedImport.href = '$pathToEntryPoint$packagePath';
181
182 // TODO(jakemac): Throw an exception here at the next breaking change, and add
183 // a test at that point (no easy way to test console.error).
184 window.console.error('''
185 Found bad packages uri in html import. All packages uris should point to the
186 packages symlink in the same folder as the entry point.
187
188 Entry point: $entryPath
189 Owner document: ${import.ownerDocument.baseUri}
190 Current import: ${import.outerHtml}
191 Corrected import: ${correctedImport.outerHtml}
192
193 For more information, please see:
194 https://www.dartlang.org/polymer/app-directories.html#into-a-non-dart-non-entry- point
195 ''');
196 return false;
197 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698