Chromium Code Reviews| Index: lib/src/mirror_initializer.dart |
| diff --git a/lib/src/mirror_initializer.dart b/lib/src/mirror_initializer.dart |
| index 5f874f8858382435f2a4e483aa028b671f1b5637..3191cab7e79433056f94bfc03c27b1ef0b3622e9 100644 |
| --- a/lib/src/mirror_initializer.dart |
| +++ b/lib/src/mirror_initializer.dart |
| @@ -14,17 +14,20 @@ import 'dart:collection' show LinkedHashMap; |
| import 'dart:mirrors'; |
| import 'dart:html'; |
| import 'package:initialize/initialize.dart' as init; |
| +import 'package:path/path.dart' show url; |
| const bool deployMode = false; |
| Future run({List<Type> typeFilter, init.InitializerFilter customFilter}) async { |
| - var libraryUris = _discoverLibrariesToLoad(document, window.location.href) |
| - .map(Uri.parse); |
| + var libraryUris = |
| + _discoverLibrariesToLoad(document, window.location.href).map(Uri.parse); |
| for (var uri in libraryUris) { |
| await init.run( |
| typeFilter: typeFilter, customFilter: customFilter, from: uri); |
| } |
| + |
| + _validatePackageImports(document); |
| return null; |
| } |
| @@ -33,8 +36,8 @@ Future run({List<Type> typeFilter, init.InitializerFilter customFilter}) async { |
| /// called after all HTML imports are resolved. Polymer ensures this by asking |
| /// users to put their Dart script tags after all HTML imports (this is checked |
| /// by the linter, and Dartium will otherwise show an error message). |
| -Iterable<_ScriptInfo> _discoverScripts( |
| - Document doc, String baseUri, [_State state]) { |
| +Iterable<_ScriptInfo> _discoverScripts(Document doc, String baseUri, |
| + [_State state]) { |
| if (state == null) state = new _State(); |
| if (doc == null) { |
| print('warning: $baseUri not found.'); |
| @@ -82,7 +85,6 @@ class _ScriptInfo { |
| _ScriptInfo(this.resolvedUrl, {this.packageUrl}); |
| } |
| - |
| // TODO(sigmund): explore other (cheaper) ways to resolve URIs relative to the |
| // root library (see dartbug.com/12612) |
| final _rootUri = currentMirrorSystem().isolate.rootLibrary.uri; |
| @@ -100,8 +102,8 @@ _ScriptInfo _scriptInfoFor(script, baseUri) { |
| // to the packages folder. If users don't create symlinks in the source |
| // tree, then Dartium will also complain because it won't find the file seen |
| // in an HTML import. |
| - var packagePath = uri.path.substring( |
| - uri.path.lastIndexOf('packages/') + 'packages/'.length); |
| + var packagePath = uri.path |
| + .substring(uri.path.lastIndexOf('packages/') + 'packages/'.length); |
| return new _ScriptInfo('$uri', packageUrl: 'package:$packagePath'); |
| } |
| @@ -130,3 +132,67 @@ final _libs = currentMirrorSystem().libraries; |
| bool _packageUrlExists(_ScriptInfo info) => |
| info.isPackage && _libs[Uri.parse(info.packageUrl)] != null; |
| + |
| +/// All the imports that we have checked for package path validation. |
| +final _importsSeen = new Set<LinkElement>(); |
| + |
| +/// All the documents that we have crawled for import validation. |
| +final _documentsSeen = new Set<Document>(); |
| + |
| +/// Validates that all html imports to packages urls point to the right packages |
| +/// symlink (the one next to the entry point). |
| +void _validatePackageImports(Document doc) { |
| + var imports = doc.querySelectorAll('link[rel="import"]'); |
| + for (LinkElement import in imports) { |
| + // Don't re-validate imports. |
| + if (!_importsSeen.add(import)) continue; |
| + |
| + // Check that the href points to the right packages path. If it doesn't we |
| + // don't continue checking as it will print extraneous errors. |
| + if (import.href.contains('packages/') && !_checkPackagePath(import)) { |
| + continue; |
| + } |
| + |
| + // Validate any imports contained in this import, if the document hasn't yet |
| + // been seen. |
| + var importDoc = import.import; |
| + if (!_documentsSeen.add(importDoc)) continue; |
| + _validatePackageImports(importDoc); |
| + } |
| +} |
| + |
| +/// The path to the entry document. |
| +final entryPath = document.baseUri; |
| + |
| +/// Checks that the relative path from the entry point to all packages imports |
| +/// starts with `packages/`. |
| +bool _checkPackagePath(LinkElement import) { |
| + var pathFromEntryPoint = |
| + url.relative(import.href, from: url.dirname(entryPath)); |
|
Siggi Cherem (dart-lang)
2015/04/01 21:37:05
just to double check, is import.href resolved to b
jakemac
2015/04/02 14:34:06
Yes its the absolute url
|
| + if (pathFromEntryPoint.startsWith('packages/')) return true; |
| + |
| + LinkElement correctedImport = import.clone(false); |
| + |
| + var pathToEntryPoint = '../' * |
| + (url.split(url.relative(import.ownerDocument.baseUri, |
| + from: url.dirname(entryPath))).length - |
| + 1); |
|
Siggi Cherem (dart-lang)
2015/04/01 21:37:05
the format here looks really strange. formatter bu
jakemac
2015/04/02 14:34:06
done
|
| + var packagePath = import.href.substring(import.href.indexOf('packages/')); |
| + correctedImport.href = '$pathToEntryPoint$packagePath'; |
| + |
| + // TODO(jakemac): Throw an exception here at the next breaking change, and add |
| + // a test at that point (no easy way to test console.error). |
| + window.console.error(''' |
| +Found bad packages uri in html import. All packages uris should point to the |
| +packages symlink in the same folder as the entry point. |
| + |
| +Entry point: $entryPath |
| +Owner document: ${import.ownerDocument.baseUri} |
| +Current import: ${import.outerHtml} |
| +Corrected import: ${correctedImport.outerHtml} |
| + |
| +For more information, please see: |
| +https://www.dartlang.org/polymer/app-directories.html#into-a-non-dart-non-entry-point |
| +'''); |
| + return false; |
| +} |