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;
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}';
}