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

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

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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 | « web_components/lib/src/init.dart ('k') | web_components/lib/src/normalize_path.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Contains logic to initialize web_components apps during development. This
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
8 /// dartium, and the web_components transformers replace this implementation
9 /// for deployment.
10 library web_components.src.mirror_initializer;
11
12 import 'dart:async';
13 import 'dart:collection' show LinkedHashMap;
14 import 'dart:mirrors';
15 import 'dart:html';
16 import 'package:initialize/initialize.dart' as init;
17 import 'package:path/path.dart' show url;
18
19 const bool deployMode = false;
20
21 Future run({List<Type> typeFilter, init.InitializerFilter customFilter}) async {
22 var libraryUris =
23 _discoverLibrariesToLoad(document, window.location.href).map(Uri.parse);
24
25 for (var uri in libraryUris) {
26 await init.run(
27 typeFilter: typeFilter, customFilter: customFilter, from: uri);
28 }
29
30 _validatePackageImports(document);
31 return null;
32 }
33
34 /// Walks the HTML import structure to discover all script tags that are
35 /// implicitly loaded. This code is only used in Dartium and should only be
36 /// called after all HTML imports are resolved. Polymer ensures this by asking
37 /// users to put their Dart script tags after all HTML imports (this is checked
38 /// by the linter, and Dartium will otherwise show an error message).
39 Iterable<_ScriptInfo> _discoverScripts(Document doc, String baseUri,
40 [_State state]) {
41 if (state == null) state = new _State();
42 if (doc == null) {
43 print('warning: $baseUri not found.');
44 return state.scripts.values;
45 }
46 if (!state.seen.add(doc)) return state.scripts.values;
47
48 for (var node in doc.querySelectorAll('script,link[rel="import"]')) {
49 if (node is LinkElement) {
50 _discoverScripts(node.import, node.href, state);
51 } else if (node is ScriptElement && node.type == 'application/dart') {
52 var info = _scriptInfoFor(node, baseUri);
53 if (state.scripts.containsKey(info.resolvedUrl)) {
54 // TODO(jakemac): Move this to a web_components uri.
55 print('warning: Script `${info.resolvedUrl}` included more than once. '
56 'See http://goo.gl/5HPeuP#polymer_44 for more details.');
57 } else {
58 state.scripts[info.resolvedUrl] = info;
59 }
60 }
61 }
62 return state.scripts.values;
63 }
64
65 /// Internal state used in [_discoverScripts].
66 class _State {
67 /// Documents that we have visited thus far.
68 final Set<Document> seen = new Set();
69
70 /// Scripts that have been discovered, in tree order.
71 final LinkedHashMap<String, _ScriptInfo> scripts = {};
72 }
73
74 /// Holds information about a Dart script tag.
75 class _ScriptInfo {
76 /// The original URL seen in the tag fully resolved.
77 final String resolvedUrl;
78
79 /// Whether it seems to be a 'package:' URL (starts with the package-root).
80 bool get isPackage => packageUrl != null;
81
82 /// The equivalent 'package:' URL, if any.
83 final String packageUrl;
84
85 _ScriptInfo(this.resolvedUrl, {this.packageUrl});
86 }
87
88 // TODO(sigmund): explore other (cheaper) ways to resolve URIs relative to the
89 // root library (see dartbug.com/12612)
90 final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri;
91
92 /// Returns [_ScriptInfo] for [script] which was seen in [baseUri].
93 _ScriptInfo _scriptInfoFor(script, baseUri) {
94 var uriString = script.src;
95 if (uriString != '') {
96 var uri = _rootUri.resolve(uriString);
97 if (!_isHttpStylePackageUrl(uri)) return new _ScriptInfo('$uri');
98 // Use package: urls if available. This rule here is more permissive than
99 // how we translate urls in polymer-build, but we expect Dartium to limit
100 // the cases where there are differences. The polymer-build issues an error
101 // when using packages/ inside lib without properly stepping out all the way
102 // to the packages folder. If users don't create symlinks in the source
103 // tree, then Dartium will also complain because it won't find the file seen
104 // in an HTML import.
105 var packagePath = uri.path
106 .substring(uri.path.lastIndexOf('packages/') + 'packages/'.length);
107 return new _ScriptInfo('$uri', packageUrl: 'package:$packagePath');
108 }
109
110 // Even in the case of inline scripts its ok to just use the baseUri since
111 // there can only be one per page.
112 return new _ScriptInfo(baseUri);
113 }
114
115 /// Whether [uri] is an http URI that contains a 'packages' segment, and
116 /// therefore could be converted into a 'package:' URI.
117 bool _isHttpStylePackageUrl(Uri uri) {
118 var uriPath = uri.path;
119 return uri.scheme == _rootUri.scheme &&
120 // Don't process cross-domain uris.
121 uri.authority == _rootUri.authority &&
122 uriPath.endsWith('.dart') &&
123 (uriPath.contains('/packages/') || uriPath.startsWith('packages/'));
124 }
125
126 Iterable<String> _discoverLibrariesToLoad(Document doc, String baseUri) =>
127 _discoverScripts(doc, baseUri).map(
128 (info) => _packageUrlExists(info) ? info.packageUrl : info.resolvedUrl);
129
130 /// All libraries in the current isolate.
131 final _libs = currentMirrorSystem().libraries;
132
133 bool _packageUrlExists(_ScriptInfo info) =>
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 (importDoc == null || !_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 dirname = entryPath.endsWith('/') ? entryPath : url.dirname(entryPath);
171 var pathFromEntryPoint = url.relative(import.href, from: dirname);
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 | « web_components/lib/src/init.dart ('k') | web_components/lib/src/normalize_path.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698