Support defining environment constants for dart2js via the command-line.

These constants only work for dart2js because neither Dartium nor the isolate
API support defining them.

BUG= http://dartbug.com/15806
R=rnystrom@google.com

Review URL: https://codereview.chromium.org//1106713003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45416 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
nweiz@google.com 2015-04-24 21:40:49 +00:00
parent a7fa3c85c2
commit e29bab1b4d
6 changed files with 109 additions and 7 deletions

View file

@ -60,15 +60,19 @@ class AssetEnvironment {
/// entrypoints are loaded. Each entrypoint is expected to refer to a Dart
/// library.
///
/// If [environmentConstants] is passed, the constants it defines are passed
/// on to the built-in dart2js transformer.
///
/// Returns a [Future] that completes to the environment once the inputs,
/// transformers, and server are loaded and ready.
static Future<AssetEnvironment> create(Entrypoint entrypoint,
BarbackMode mode, {WatcherType watcherType, String hostname, int basePort,
Iterable<String> packages, Iterable<AssetId> entrypoints,
bool useDart2JS: true}) {
Map<String, String> environmentConstants, bool useDart2JS: true}) {
if (watcherType == null) watcherType = WatcherType.NONE;
if (hostname == null) hostname = "localhost";
if (basePort == null) basePort = 0;
if (environmentConstants == null) environmentConstants = {};
return log.progress("Loading asset environment", () async {
var graph = await entrypoint.loadPackageGraph();
@ -77,7 +81,7 @@ class AssetEnvironment {
barback.log.listen(_log);
var environment = new AssetEnvironment._(graph, barback, mode,
watcherType, hostname, basePort);
watcherType, hostname, basePort, environmentConstants);
await environment._load(entrypoints: entrypoints, useDart2JS: useDart2JS);
return environment;
@ -125,6 +129,9 @@ class AssetEnvironment {
/// The mode to run the transformers in.
final BarbackMode mode;
/// Constants to passed to the built-in dart2js transformer.
final Map<String, String> environmentConstants;
/// The [Transformer]s that should be appended by default to the root
/// package's transformer cascade. Will be empty if there are none.
final _builtInTransformers = <Transformer>[];
@ -158,7 +165,8 @@ class AssetEnvironment {
Set<AssetId> _modifiedSources;
AssetEnvironment._(this.graph, this.barback, this.mode,
this._watcherType, this._hostname, this._basePort);
this._watcherType, this._hostname, this._basePort,
this.environmentConstants);
/// Gets the built-in [Transformer]s that should be added to [package].
///

View file

@ -166,13 +166,15 @@ class Dart2JSTransformer extends Transformer implements LazyTransformer {
/// Parses and returns the "environment" configuration option.
Map<String, String> get _configEnvironment {
if (!_settings.configuration.containsKey('environment')) return null;
if (!_settings.configuration.containsKey('environment')) {
return _environment.environmentConstants;
}
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;
return mergeMaps(environment, _environment.environmentConstants);
}
throw new FormatException('Invalid value for \$dart2js.environment: '

View file

@ -35,6 +35,10 @@ class BuildCommand extends BarbackCommand {
int builtFiles = 0;
BuildCommand() {
argParser.addOption("define", abbr: "D",
help: "Defines an environment constant for dart2js.",
allowMultiple: true, splitCommas: false);
argParser.addOption("format",
help: "How output should be displayed.",
allowed: ["text", "json"], defaultsTo: "text");
@ -50,10 +54,16 @@ class BuildCommand extends BarbackCommand {
var errorsJson = [];
var logJson = [];
var environmentConstants = new Map.fromIterable(argResults["define"],
key: (pair) => pair.split("=").first,
value: (pair) => pair.split("=").last);
// Since this server will only be hit by the transformer loader and isn't
// user-facing, just use an IPv4 address to avoid a weird bug on the
// OS X buildbots.
return AssetEnvironment.create(entrypoint, mode, useDart2JS: true)
return AssetEnvironment.create(entrypoint, mode,
environmentConstants: environmentConstants,
useDart2JS: true)
.then((environment) {
// Show in-progress errors, but not results. Those get handled
// implicitly by getAllAssets().

View file

@ -59,6 +59,9 @@ class ServeCommand extends BarbackCommand {
final _completer = new Completer();
ServeCommand() {
argParser.addOption("define", abbr: "D",
help: "Defines an environment constant for dart2js.",
allowMultiple: true, splitCommas: false);
argParser.addOption('hostname', defaultsTo: 'localhost',
help: 'The hostname to listen on.');
argParser.addOption('port', defaultsTo: '8080',
@ -88,9 +91,13 @@ class ServeCommand extends BarbackCommand {
var watcherType = argResults['force-poll'] ?
WatcherType.POLLING : WatcherType.AUTO;
var environmentConstants = new Map.fromIterable(argResults["define"],
key: (pair) => pair.split("=").first,
value: (pair) => pair.split("=").last);
var environment = await AssetEnvironment.create(entrypoint, mode,
watcherType: watcherType, hostname: hostname, basePort: port,
useDart2JS: useDart2JS);
useDart2JS: useDart2JS, environmentConstants: environmentConstants);
var directoryLength = sourceDirectories.map((dir) => dir.length)
.reduce(math.max);

View file

@ -371,6 +371,16 @@ Future<Map> mapFromIterableAsync(Iterable iter, {key(element),
})).then((_) => map);
}
/// Returns a new map with all entries in both [map1] and [map2].
///
/// If there are overlapping keys, [map2]'s value wins.
Map mergeMaps(Map map1, Map map2) {
var result = {};
result.addAll(map1);
result.addAll(map2);
return result;
}
/// Returns the transitive closure of [graph].
///
/// This assumes [graph] represents a graph with a vertex for each key and an

View file

@ -0,0 +1,65 @@
// Copyright (c) 2014, 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 'package:scheduled_test/scheduled_test.dart';
import '../descriptor.dart' as d;
import '../serve/utils.dart';
import '../test_pub.dart';
main() {
initConfig();
group("passes environment constants to dart2js", () {
setUp(() {
// Dart2js can take a long time to compile dart code, so we increase the
// timeout to cope with that.
currentSchedule.timeout *= 3;
d.dir(appPath, [
d.appPubspec(),
d.dir('web', [
d.file('file.dart',
'void main() => print(const String.fromEnvironment("name"));')
])
]).create();
});
integration('from "pub build"', () {
schedulePub(args: ["build", "--define", "name=fblthp"],
output: new RegExp(r'Built 1 file to "build".'));
d.dir(appPath, [
d.dir('build', [
d.dir('web', [
d.matcherFile('file.dart.js', contains('fblthp')),
])
])
]).validate();
});
integration('from "pub serve"', () {
pubServe(args: ["--define", "name=fblthp"]);
requestShouldSucceed("file.dart.js", contains("fblthp"));
endPubServe();
});
integration('which takes precedence over the pubspec', () {
d.dir(appPath, [
d.pubspec({
"name": "myapp",
"transformers": [
{"\$dart2js": {"environment": {"name": "slartibartfast"}}}
]
})
]).create();
pubServe(args: ["--define", "name=fblthp"]);
requestShouldSucceed("file.dart.js", allOf([
contains("fblthp"),
isNot(contains("slartibartfast"))
]));
endPubServe();
});
});
}