blob: e4295e888d9d1ede1c3bb755c04adb3789362766 [file] [log] [blame]
// 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;
this._options, this._compilerInput, this._reporter, Measurer measurer)
: initializedCompilerState = _options.kernelInitializedCompilerState,
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(;
} else {
String targetName =
_options.compileForServer ? "dart2js_server" : "dart2js";
String platform = '${targetName}_platform.dill';
initializedCompilerState = fe.initializeCompiler(
new Dart2jsTarget(targetName, new TargetFlags(strongMode: true)),
component = await fe.compile(
new CompilerFileSystem(_compilerInput),
(e) => reportFrontEndMessage(_reporter, e),
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) {
// 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';
libraries = libraries.where(seen.contains);
return new LoadedLibraries(component, rootLibraryUri, => 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}';