| Index: sdk/lib/_internal/pub_generated/lib/src/barback/dart2js_transformer.dart
|
| diff --git a/sdk/lib/_internal/pub_generated/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub_generated/lib/src/barback/dart2js_transformer.dart
|
| index 4f3cfa6e2f2604abe4b5a9c102b33de0a1c0fa23..7878c4590b51a46f8140fa070f2aac20f4a8ccd3 100644
|
| --- a/sdk/lib/_internal/pub_generated/lib/src/barback/dart2js_transformer.dart
|
| +++ b/sdk/lib/_internal/pub_generated/lib/src/barback/dart2js_transformer.dart
|
| @@ -1,10 +1,17 @@
|
| +// Copyright (c) 2013, 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 pub.dart2js_transformer;
|
| +
|
| import 'dart:async';
|
| import 'dart:convert';
|
| +
|
| import 'package:analyzer/analyzer.dart';
|
| import 'package:barback/barback.dart';
|
| import 'package:path/path.dart' as path;
|
| import 'package:pool/pool.dart';
|
| +
|
| import '../../../../compiler/compiler.dart' as compiler;
|
| import '../../../../compiler/implementation/dart2js.dart' show AbortLeg;
|
| import '../../../../compiler/implementation/source_file.dart';
|
| @@ -12,6 +19,8 @@ import '../barback.dart';
|
| import '../dart.dart' as dart;
|
| import '../utils.dart';
|
| import 'asset_environment.dart';
|
| +
|
| +/// The set of all valid configuration options for this transformer.
|
| final _validOptions = new Set<String>.from(
|
| [
|
| 'commandLineOptions',
|
| @@ -25,28 +34,53 @@ final _validOptions = new Set<String>.from(
|
| 'suppressHints',
|
| 'suppressPackageWarnings',
|
| 'terse']);
|
| +
|
| +/// A [Transformer] that uses dart2js's library API to transform Dart
|
| +/// entrypoints in "web" to JavaScript.
|
| class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| + /// We use this to ensure that only one compilation is in progress at a time.
|
| + ///
|
| + /// Dart2js uses lots of memory, so if we try to actually run compiles in
|
| + /// parallel, it takes down the VM. The tracking bug to do something better
|
| + /// is here: https://code.google.com/p/dart/issues/detail?id=14730.
|
| static final _pool = new Pool(1);
|
| +
|
| final AssetEnvironment _environment;
|
| final BarbackSettings _settings;
|
| +
|
| + /// Whether source maps should be generated for the compiled JS.
|
| bool get _generateSourceMaps => _settings.mode != BarbackMode.RELEASE;
|
| +
|
| Dart2JSTransformer.withSettings(this._environment, this._settings) {
|
| var invalidOptions =
|
| _settings.configuration.keys.toSet().difference(_validOptions);
|
| if (invalidOptions.isEmpty) return;
|
| +
|
| throw new FormatException(
|
| "Unrecognized dart2js " "${pluralize('option', invalidOptions.length)} "
|
| "${toSentence(invalidOptions.map((option) => '"$option"'))}.");
|
| }
|
| +
|
| Dart2JSTransformer(AssetEnvironment environment, BarbackMode mode)
|
| : this.withSettings(environment, new BarbackSettings({}, mode));
|
| +
|
| + /// Only ".dart" entrypoint files within a buildable directory are processed.
|
| bool isPrimary(AssetId id) {
|
| if (id.extension != ".dart") return false;
|
| +
|
| + // "lib" should only contain libraries. For efficiency's sake, we don't
|
| + // look for entrypoints in there.
|
| return !id.path.startsWith("lib/");
|
| }
|
| +
|
| Future apply(Transform transform) {
|
| + // TODO(nweiz): If/when barback starts reporting what assets were modified,
|
| + // don't re-run the entrypoint detection logic unless the primary input was
|
| + // actually modified. See issue 16817.
|
| return _isEntrypoint(transform.primaryInput).then((isEntrypoint) {
|
| if (!isEntrypoint) return null;
|
| +
|
| + // Wait for any ongoing apply to finish first.
|
| return _pool.withResource(() {
|
| transform.logger.info("Compiling ${transform.primaryInput.id}...");
|
| var stopwatch = new Stopwatch()..start();
|
| @@ -58,6 +92,7 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| });
|
| });
|
| }
|
| +
|
| void declareOutputs(DeclaringTransform transform) {
|
| var primaryId = transform.primaryId;
|
| transform.declareOutput(primaryId.addExtension(".js"));
|
| @@ -66,6 +101,8 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| transform.declareOutput(primaryId.addExtension(".js.map"));
|
| }
|
| }
|
| +
|
| + /// Returns whether or not [asset] might be an entrypoint.
|
| Future<bool> _isEntrypoint(Asset asset) {
|
| return asset.readAsString().then((code) {
|
| try {
|
| @@ -73,20 +110,35 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| if (asset.id.package != _environment.rootPackage.name) {
|
| name += " in ${asset.id.package}";
|
| }
|
| +
|
| var parsed = parseCompilationUnit(code, name: name);
|
| return dart.isEntrypoint(parsed);
|
| } on AnalyzerErrorGroup catch (e) {
|
| + // If we get a parse error, consider the asset primary so we report
|
| + // dart2js's more detailed error message instead.
|
| return true;
|
| }
|
| });
|
| }
|
| +
|
| + /// Run the dart2js compiler.
|
| Future _doCompilation(Transform transform) {
|
| var provider = new _BarbackCompilerProvider(
|
| _environment,
|
| transform,
|
| generateSourceMaps: _generateSourceMaps);
|
| +
|
| + // Create a "path" to the entrypoint script. The entrypoint may not actually
|
| + // be on disk, but this gives dart2js a root to resolve relative paths
|
| + // against.
|
| var id = transform.primaryInput.id;
|
| +
|
| var entrypoint = _environment.graph.packages[id.package].path(id.path);
|
| +
|
| + // TODO(rnystrom): Should have more sophisticated error-handling here. Need
|
| + // to report compile errors to the user in an easily visible way. Need to
|
| + // make sure paths in errors are mapped to the original source path so they
|
| + // can understand them.
|
| return dart.compile(
|
| entrypoint,
|
| provider,
|
| @@ -108,29 +160,41 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| terse: _configBool('terse'),
|
| includeSourceMapUrls: _settings.mode != BarbackMode.RELEASE);
|
| }
|
| +
|
| + /// Parses and returns the "commandLineOptions" configuration option.
|
| List<String> get _configCommandLineOptions {
|
| if (!_settings.configuration.containsKey('commandLineOptions')) return null;
|
| +
|
| var options = _settings.configuration['commandLineOptions'];
|
| if (options is List && options.every((option) => option is String)) {
|
| return options;
|
| }
|
| +
|
| throw new FormatException(
|
| 'Invalid value for '
|
| '\$dart2js.commandLineOptions: ${JSON.encode(options)} (expected list '
|
| 'of strings).');
|
| }
|
| +
|
| + /// Parses and returns the "environment" configuration option.
|
| Map<String, String> get _configEnvironment {
|
| if (!_settings.configuration.containsKey('environment')) return null;
|
| +
|
| var environment = _settings.configuration['environment'];
|
| if (environment is Map &&
|
| environment.keys.every((key) => key is String) &&
|
| environment.values.every((key) => key is String)) {
|
| return environment;
|
| }
|
| +
|
| throw new FormatException(
|
| 'Invalid value for \$dart2js.environment: '
|
| '${JSON.encode(environment)} (expected map from strings to strings).');
|
| }
|
| +
|
| + /// Parses and returns a boolean configuration option.
|
| + ///
|
| + /// [defaultsTo] is the default value of the option.
|
| bool _configBool(String name, {bool defaultsTo: false}) {
|
| if (!_settings.configuration.containsKey(name)) return defaultsTo;
|
| var value = _settings.configuration[name];
|
| @@ -140,35 +204,85 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
|
| '${JSON.encode(value)} (expected true or false).');
|
| }
|
| }
|
| +
|
| +/// Defines an interface for dart2js to communicate with barback and pub.
|
| +///
|
| +/// Note that most of the implementation of diagnostic handling here was
|
| +/// copied from [FormattingDiagnosticHandler] in dart2js. The primary
|
| +/// difference is that it uses barback's logging code and, more importantly, it
|
| +/// handles missing source files more gracefully.
|
| class _BarbackCompilerProvider implements dart.CompilerProvider {
|
| Uri get libraryRoot => Uri.parse("${path.toUri(_libraryRootPath)}/");
|
| +
|
| final AssetEnvironment _environment;
|
| final Transform _transform;
|
| String _libraryRootPath;
|
| +
|
| + /// The map of previously loaded files.
|
| + ///
|
| + /// Used to show where an error occurred in a source file.
|
| final _sourceFiles = new Map<String, SourceFile>();
|
| +
|
| + // TODO(rnystrom): Make these configurable.
|
| + /// Whether or not warnings should be logged.
|
| var _showWarnings = true;
|
| +
|
| + /// Whether or not hints should be logged.
|
| var _showHints = true;
|
| +
|
| + /// Whether or not verbose info messages should be logged.
|
| var _verbose = false;
|
| +
|
| + /// Whether an exception should be thrown on an error to stop compilation.
|
| var _throwOnError = false;
|
| +
|
| + /// This gets set after a fatal error is reported to quash any subsequent
|
| + /// errors.
|
| var _isAborting = false;
|
| +
|
| final bool generateSourceMaps;
|
| +
|
| compiler.Diagnostic _lastKind = null;
|
| +
|
| static final int _FATAL =
|
| compiler.Diagnostic.CRASH.ordinal |
|
| compiler.Diagnostic.ERROR.ordinal;
|
| static final int _INFO =
|
| compiler.Diagnostic.INFO.ordinal |
|
| compiler.Diagnostic.VERBOSE_INFO.ordinal;
|
| +
|
| _BarbackCompilerProvider(this._environment, this._transform,
|
| {this.generateSourceMaps: true}) {
|
| + // Dart2js outputs source maps that reference the Dart SDK sources. For
|
| + // that to work, those sources need to be inside the build environment. We
|
| + // do that by placing them in a special "$sdk" pseudo-package. In order for
|
| + // dart2js to generate the right URLs to point to that package, we give it
|
| + // a library root that corresponds to where that package can be found
|
| + // relative to the public source directory containing that entrypoint.
|
| + //
|
| + // For example, say the package being compiled is "/dev/myapp", the
|
| + // entrypoint is "web/sub/foo/bar.dart", and the source directory is
|
| + // "web/sub". This means the SDK sources will be (conceptually) at:
|
| + //
|
| + // /dev/myapp/web/sub/packages/$sdk/lib/
|
| + //
|
| + // This implies that the asset path for a file in the SDK is:
|
| + //
|
| + // $sdk|lib/lib/...
|
| + //
|
| + // TODO(rnystrom): Fix this if #17751 is fixed.
|
| var buildDir =
|
| _environment.getSourceDirectoryContaining(_transform.primaryInput.id.path);
|
| _libraryRootPath =
|
| _environment.rootPackage.path(buildDir, "packages", r"$sdk");
|
| }
|
| +
|
| + /// A [CompilerInputProvider] for dart2js.
|
| Future<String> provideInput(Uri resourceUri) {
|
| + // We only expect to get absolute "file:" URLs from dart2js.
|
| assert(resourceUri.isAbsolute);
|
| assert(resourceUri.scheme == "file");
|
| +
|
| var sourcePath = path.fromUri(resourceUri);
|
| return _readResource(resourceUri).then((source) {
|
| _sourceFiles[resourceUri.toString()] =
|
| @@ -176,11 +290,18 @@ class _BarbackCompilerProvider implements dart.CompilerProvider {
|
| return source;
|
| });
|
| }
|
| +
|
| + /// A [CompilerOutputProvider] for dart2js.
|
| EventSink<String> provideOutput(String name, String extension) {
|
| + // TODO(rnystrom): Do this more cleanly. See: #17403.
|
| if (!generateSourceMaps && extension.endsWith(".map")) {
|
| return new NullSink<String>();
|
| }
|
| +
|
| var primaryId = _transform.primaryInput.id;
|
| +
|
| + // Dart2js uses an empty string for the name of the entrypoint library.
|
| + // Otherwise, it's the name of a deferred library.
|
| var outPath;
|
| if (name == "") {
|
| outPath = _transform.primaryInput.id.path;
|
| @@ -188,24 +309,43 @@ class _BarbackCompilerProvider implements dart.CompilerProvider {
|
| var dirname = path.url.dirname(_transform.primaryInput.id.path);
|
| outPath = path.url.join(dirname, name);
|
| }
|
| +
|
| var id = new AssetId(primaryId.package, "$outPath.$extension");
|
| +
|
| + // Make a sink that dart2js can write to.
|
| var sink = new StreamController<String>();
|
| +
|
| + // dart2js gives us strings, but stream assets expect byte lists.
|
| var stream = UTF8.encoder.bind(sink.stream);
|
| +
|
| + // And give it to barback as a stream it can read from.
|
| _transform.addOutput(new Asset.fromStream(id, stream));
|
| +
|
| return sink;
|
| }
|
| +
|
| + /// A [DiagnosticHandler] for dart2js, loosely based on
|
| + /// [FormattingDiagnosticHandler].
|
| void handleDiagnostic(Uri uri, int begin, int end, String message,
|
| compiler.Diagnostic kind) {
|
| + // TODO(ahe): Remove this when source map is handled differently.
|
| if (kind.name == "source map") return;
|
| +
|
| if (_isAborting) return;
|
| _isAborting = (kind == compiler.Diagnostic.CRASH);
|
| +
|
| var isInfo = (kind.ordinal & _INFO) != 0;
|
| if (isInfo && uri == null && kind != compiler.Diagnostic.INFO) {
|
| if (!_verbose && kind == compiler.Diagnostic.VERBOSE_INFO) return;
|
| _transform.logger.info(message);
|
| return;
|
| }
|
| +
|
| + // [_lastKind] records the previous non-INFO kind we saw.
|
| + // This is used to suppress info about a warning when warnings are
|
| + // suppressed, and similar for hints.
|
| if (kind != compiler.Diagnostic.INFO) _lastKind = kind;
|
| +
|
| var logFn;
|
| if (kind == compiler.Diagnostic.ERROR) {
|
| logFn = _transform.logger.error;
|
| @@ -224,42 +364,62 @@ class _BarbackCompilerProvider implements dart.CompilerProvider {
|
| } else {
|
| throw new Exception('Unknown kind: $kind (${kind.ordinal})');
|
| }
|
| +
|
| var fatal = (kind.ordinal & _FATAL) != 0;
|
| if (uri == null) {
|
| logFn(message);
|
| } else {
|
| SourceFile file = _sourceFiles[uri.toString()];
|
| if (file == null) {
|
| + // We got a message before loading the file, so just report the message
|
| + // itself.
|
| logFn('$uri: $message');
|
| } else {
|
| logFn(file.getLocationMessage(message, begin, end));
|
| }
|
| }
|
| +
|
| if (fatal && _throwOnError) {
|
| _isAborting = true;
|
| throw new AbortLeg(message);
|
| }
|
| }
|
| +
|
| Future<String> _readResource(Uri url) {
|
| return new Future.sync(() {
|
| + // Find the corresponding asset in barback.
|
| var id = _sourceUrlToId(url);
|
| if (id != null) return _transform.readInputAsString(id);
|
| +
|
| + // Don't allow arbitrary file paths that point to things not in packages.
|
| + // Doing so won't work in Dartium.
|
| throw new Exception(
|
| "Cannot read $url because it is outside of the build environment.");
|
| });
|
| }
|
| +
|
| AssetId _sourceUrlToId(Uri url) {
|
| + // See if it's a package path.
|
| var id = packagesUrlToId(url);
|
| if (id != null) return id;
|
| +
|
| + // See if it's a path to a "public" asset within the root package. All
|
| + // other files in the root package are not visible to transformers, so
|
| + // should be loaded directly from disk.
|
| var sourcePath = path.fromUri(url);
|
| if (_environment.containsPath(sourcePath)) {
|
| var relative =
|
| path.toUri(_environment.rootPackage.relative(sourcePath)).toString();
|
| +
|
| return new AssetId(_environment.rootPackage.name, relative);
|
| }
|
| +
|
| return null;
|
| }
|
| }
|
| +
|
| +/// An [EventSink] that discards all data. Provided to dart2js when we don't
|
| +/// want an actual output.
|
| class NullSink<T> implements EventSink<T> {
|
| void add(T event) {}
|
| void addError(errorEvent, [StackTrace stackTrace]) {}
|
|
|