| // Copyright (c) 2012, 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. | |
| library dart2js.library_loader; | |
| import 'dart:async'; | |
| import 'package:front_end/src/api_unstable/dart2js.dart' as fe; | |
| import 'package:kernel/ast.dart' as ir; | |
| import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; | |
| import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator; | |
| import 'package:kernel/target/targets.dart'; | |
| import '../compiler_new.dart' as api; | |
| import 'kernel/front_end_adapter.dart'; | |
| import 'kernel/dart2js_target.dart' show Dart2jsTarget; | |
| import 'common/tasks.dart' show CompilerTask, Measurer; | |
| import 'common.dart'; | |
| import 'options.dart'; | |
| /// A loader that builds a kernel IR representation of the component. | |
| /// | |
| /// It supports loading both .dart source files or pre-compiled .dill files. | |
| /// When given .dart source files, it invokes the shared frontend | |
| /// (`package:front_end`) to produce the corresponding kernel IR representation. | |
| // TODO(sigmund): move this class to a new file under src/kernel/. | |
| class LibraryLoaderTask extends CompilerTask { | |
| final DiagnosticReporter _reporter; | |
| final api.CompilerInput _compilerInput; | |
| final CompilerOptions _options; | |
| /// Shared state between compilations. | |
| fe.InitializedCompilerState initializedCompilerState; | |
| LibraryLoaderTask( | |
| this._options, this._compilerInput, this._reporter, Measurer measurer) | |
| : initializedCompilerState = _options.kernelInitializedCompilerState, | |
| super(measurer); | |
| String get name => 'Library loader'; | |
| /// Loads an entire Kernel [Component] from a file on disk. | |
| Future<LoadedLibraries> loadLibraries(Uri resolvedUri) { | |
| return measure(() async { | |
| var isDill = resolvedUri.path.endsWith('.dill'); | |
| ir.Component component; | |
| if (isDill) { | |
| api.Input input = await _compilerInput.readFromUri(resolvedUri, | |
| inputKind: api.InputKind.binary); | |
| component = new ir.Component(); | |
| new BinaryBuilder(input.data).readComponent(component); | |
| } else { | |
| String targetName = | |
| _options.compileForServer ? "dart2js_server" : "dart2js"; | |
| String platform = '${targetName}_platform.dill'; | |
| initializedCompilerState = fe.initializeCompiler( | |
| initializedCompilerState, | |
| new Dart2jsTarget(targetName, new TargetFlags(strongMode: true)), | |
| _options.librariesSpecificationUri, | |
| _options.platformBinaries.resolve(platform), | |
| _options.packageConfig); | |
| component = await fe.compile( | |
| initializedCompilerState, | |
| _options.verbose, | |
| new CompilerFileSystem(_compilerInput), | |
| (e) => reportFrontEndMessage(_reporter, e), | |
| resolvedUri); | |
| } | |
| if (component == null) return null; | |
| return _createLoadedLibraries(component); | |
| }); | |
| } | |
| // Only visible for unit testing. | |
| LoadedLibraries _createLoadedLibraries(ir.Component component) { | |
| Uri rootLibraryUri = null; | |
| Iterable<ir.Library> libraries = component.libraries; | |
| if (component.mainMethod != null) { | |
| var root = component.mainMethod.enclosingLibrary; | |
| rootLibraryUri = root.importUri; | |
| // Filter unreachable libraries: [Component] was built by linking in the | |
| // entire SDK libraries, not all of them are used. We include anything | |
| // that is reachable from `main`. Note that all internal libraries that | |
| // the compiler relies on are reachable from `dart:core`. | |
| var seen = new Set<Library>(); | |
| search(ir.Library current) { | |
| if (!seen.add(current)) return; | |
| for (ir.LibraryDependency dep in current.dependencies) { | |
| search(dep.targetLibrary); | |
| } | |
| } | |
| search(root); | |
| // Libraries dependencies do not show implicit imports to `dart:core`. | |
| var dartCore = component.libraries.firstWhere((lib) { | |
| return lib.importUri.scheme == 'dart' && lib.importUri.path == 'core'; | |
| }); | |
| search(dartCore); | |
| libraries = libraries.where(seen.contains); | |
| } | |
| return new LoadedLibraries(component, rootLibraryUri, | |
| libraries.map((lib) => lib.importUri).toList()); | |
| } | |
| } | |
| /// Information on the set libraries loaded as a result of a call to | |
| /// [LibraryLoader.loadLibrary]. | |
| class LoadedLibraries { | |
| final ir.Component _component; | |
| final Uri _rootLibraryUri; | |
| final List<Uri> _libraries; | |
| LoadedLibraries(this._component, this._rootLibraryUri, this._libraries) { | |
| assert(rootLibraryUri != null); | |
| } | |
| /// Returns the root component for the loaded libraries. | |
| ir.Component get component => _component; | |
| /// The [Uri] of the root library. | |
| Uri get rootLibraryUri => _rootLibraryUri; | |
| /// Returns the [Uri]s of all libraries that have been loaded. | |
| Iterable<Uri> get libraries => _libraries; | |
| /// Returns `true` if a library with canonical [uri] was loaded in this bulk. | |
| bool containsLibrary(Uri uri) { | |
| return _libraries.contains(uri); | |
| } | |
| /// Applies all library [Uri]s in this bulk to [f]. | |
| void forEachLibrary(f(Uri Uri)) => _libraries.forEach(f); | |
| String toString() => 'root=$_rootLibraryUri,libraries=${_libraries}'; | |
| } |