|  | // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | import 'common.dart'; | 
|  | import 'elements/elements.dart' show LibraryElement; | 
|  | import 'util/emptyset.dart'; | 
|  |  | 
|  | /// API used by the library loader to translate internal SDK URIs into file | 
|  | /// system readable URIs. | 
|  | abstract class ResolvedUriTranslator { | 
|  | factory ResolvedUriTranslator( | 
|  | Map<String, Uri> sdkLibraries, DiagnosticReporter reporter) = | 
|  | _ResolvedUriTranslator; | 
|  |  | 
|  | /// The set of platform libraries reported as unsupported. | 
|  | /// | 
|  | /// For instance when importing 'dart:io' without '--categories=Server'. | 
|  | Set<Uri> get disallowedLibraryUris; | 
|  |  | 
|  | /// Whether or not a mockable library has been translated. | 
|  | bool get mockableLibraryUsed; | 
|  |  | 
|  | /// A mapping from dart: library names to their location. | 
|  | Map<String, Uri> get sdkLibraries; | 
|  |  | 
|  | /// Translates the resolved [uri] into a readable URI. | 
|  | /// | 
|  | /// The [importingLibrary] holds the library importing [uri] or `null` if | 
|  | /// [uri] is loaded as the main library. The [importingLibrary] is used to | 
|  | /// grant access to internal libraries from platform libraries and patch | 
|  | /// libraries. | 
|  | /// | 
|  | /// If the [uri] is not accessible from [importingLibrary], this method is | 
|  | /// responsible for reporting errors. | 
|  | /// | 
|  | /// See [LibraryLoader] for terminology on URIs. | 
|  | Uri translate(LibraryElement importingLibrary, Uri uri, | 
|  | [Spannable spannable]); | 
|  | } | 
|  |  | 
|  | /// A translator that forwards all methods to an internal | 
|  | /// [ResolvedUriTranslator]. | 
|  | /// | 
|  | /// The translator to forward to may be set after the instance is constructed. | 
|  | /// This is useful for the compiler because some tasks that are instantiated at | 
|  | /// compiler construction time need a [ResolvedUriTranslator], but the data | 
|  | /// required to instantiate it cannot be obtained at construction time. So a | 
|  | /// [ForwardingResolvedUriTranslator] may be passed instead, and the translator | 
|  | /// to forward to can be set once the required data has been retrieved. | 
|  | class ForwardingResolvedUriTranslator implements ResolvedUriTranslator { | 
|  | ResolvedUriTranslator resolvedUriTranslator; | 
|  |  | 
|  | /// Returns `true` if [resolvedUriTranslator] is not `null`. | 
|  | bool get isSet => resolvedUriTranslator != null; | 
|  |  | 
|  | /// The opposite of [isSet]. | 
|  | bool get isNotSet => resolvedUriTranslator == null; | 
|  |  | 
|  | @override | 
|  | Uri translate(LibraryElement importingLibrary, Uri resolvedUri, | 
|  | [Spannable spannable]) => | 
|  | resolvedUriTranslator.translate(importingLibrary, resolvedUri, spannable); | 
|  |  | 
|  | @override | 
|  | Set<Uri> get disallowedLibraryUris => | 
|  | resolvedUriTranslator?.disallowedLibraryUris ?? | 
|  | const ImmutableEmptySet<Uri>(); | 
|  |  | 
|  | @override | 
|  | bool get mockableLibraryUsed => resolvedUriTranslator.mockableLibraryUsed; | 
|  |  | 
|  | @override | 
|  | Map<String, Uri> get sdkLibraries => resolvedUriTranslator.sdkLibraries; | 
|  | } | 
|  |  | 
|  | class _ResolvedUriTranslator implements ResolvedUriTranslator { | 
|  | final Map<String, Uri> _sdkLibraries; | 
|  | final DiagnosticReporter _reporter; | 
|  |  | 
|  | Set<Uri> disallowedLibraryUris = new Set<Uri>(); | 
|  | bool mockableLibraryUsed = false; | 
|  |  | 
|  | _ResolvedUriTranslator(this._sdkLibraries, this._reporter); | 
|  |  | 
|  | Map<String, Uri> get sdkLibraries => _sdkLibraries; | 
|  |  | 
|  | @override | 
|  | Uri translate(LibraryElement importingLibrary, Uri uri, | 
|  | [Spannable spannable]) { | 
|  | if (uri.scheme == 'dart') { | 
|  | return translateDartUri(importingLibrary, uri, spannable); | 
|  | } | 
|  | return uri; | 
|  | } | 
|  |  | 
|  | /// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative | 
|  | /// to `options.platformConfigUri` according to the information in the file at | 
|  | /// `options.platformConfigUri`. | 
|  | /// | 
|  | /// Returns `null` and emits an error if the library could not be found or | 
|  | /// imported into [importingLibrary]. | 
|  | /// | 
|  | /// Internal libraries (whose name starts with '_') can be only resolved if | 
|  | /// [importingLibrary] is a platform or patch library. | 
|  | Uri translateDartUri( | 
|  | LibraryElement importingLibrary, Uri resolvedUri, Spannable spannable) { | 
|  | Uri location = lookupLibraryUri(resolvedUri.path); | 
|  |  | 
|  | if (location == null) { | 
|  | _reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_FOUND, | 
|  | {'resolvedUri': resolvedUri}); | 
|  | return null; | 
|  | } | 
|  |  | 
|  | if (resolvedUri.path.startsWith('_')) { | 
|  | bool allowInternalLibraryAccess = importingLibrary != null && | 
|  | (importingLibrary.isPlatformLibrary || | 
|  | importingLibrary.isPatch || | 
|  | importingLibrary.canonicalUri.path | 
|  | .contains('sdk/tests/compiler/dart2js_native')); | 
|  |  | 
|  | if (!allowInternalLibraryAccess) { | 
|  | if (importingLibrary != null) { | 
|  | _reporter.reportErrorMessage( | 
|  | spannable, MessageKind.INTERNAL_LIBRARY_FROM, { | 
|  | 'resolvedUri': resolvedUri, | 
|  | 'importingUri': importingLibrary.canonicalUri | 
|  | }); | 
|  | } else { | 
|  | _reporter.reportErrorMessage(spannable, MessageKind.INTERNAL_LIBRARY, | 
|  | {'resolvedUri': resolvedUri}); | 
|  | registerDisallowedLibraryUse(resolvedUri); | 
|  | } | 
|  | return null; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (location.scheme == "unsupported") { | 
|  | _reporter.reportErrorMessage(spannable, MessageKind.LIBRARY_NOT_SUPPORTED, | 
|  | {'resolvedUri': resolvedUri}); | 
|  | registerDisallowedLibraryUse(resolvedUri); | 
|  | return null; | 
|  | } | 
|  |  | 
|  | if (resolvedUri.path == 'html' || resolvedUri.path == 'io') { | 
|  | // TODO(ahe): Get rid of mockableLibraryUsed when test.dart | 
|  | // supports this use case better. | 
|  | mockableLibraryUsed = true; | 
|  | } | 
|  | return location; | 
|  | } | 
|  |  | 
|  | void registerDisallowedLibraryUse(Uri uri) { | 
|  | disallowedLibraryUris.add(uri); | 
|  | } | 
|  |  | 
|  | Uri lookupLibraryUri(String libraryName) { | 
|  | return _sdkLibraries[libraryName]; | 
|  | } | 
|  | } |