Use the package_resolver package.

Closes #327

R=leafp@google.com

Review URL: https://codereview.chromium.org//2184543002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a966e51..b36261f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.12.15+2
+
+* Support running without a `packages/` directory.
+
 ## 0.12.15+1
 
 * Declare support for version 1.19 of the Dart SDK.
diff --git a/lib/src/runner/browser/compiler_pool.dart b/lib/src/runner/browser/compiler_pool.dart
index 6503db5..39b32f3 100644
--- a/lib/src/runner/browser/compiler_pool.dart
+++ b/lib/src/runner/browser/compiler_pool.dart
@@ -7,6 +7,7 @@
 import 'dart:io';
 
 import 'package:async/async.dart';
+import 'package:package_resolver/package_resolver.dart';
 import 'package:path/path.dart' as p;
 import 'package:pool/pool.dart';
 
@@ -44,13 +45,11 @@
 
   /// Compile the Dart code at [dartPath] to [jsPath].
   ///
-  /// This wraps the Dart code in the standard browser-testing wrapper. If
-  /// [packageRoot] is provided, it's used as the package root for the
-  /// compilation.
+  /// This wraps the Dart code in the standard browser-testing wrapper.
   ///
   /// The returned [Future] will complete once the `dart2js` process completes
   /// *and* all its output has been printed to the command line.
-  Future compile(String dartPath, String jsPath, {String packageRoot}) {
+  Future compile(String dartPath, String jsPath) {
     return _pool.withResource(() {
       if (_closed) return null;
 
@@ -73,12 +72,12 @@
         var dart2jsPath = _config.dart2jsPath;
         if (Platform.isWindows) dart2jsPath += '.bat';
 
-        var args = ["--checked", wrapperPath, "--out=$jsPath"]
-          ..addAll(_config.dart2jsArgs);
-
-        if (packageRoot != null) {
-          args.add("--package-root=${p.toUri(p.absolute(packageRoot))}");
-        }
+        var args = [
+          "--checked",
+          wrapperPath,
+          "--out=$jsPath",
+          await PackageResolver.current.processArgument
+        ]..addAll(_config.dart2jsArgs);
 
         if (_config.color) args.add("--enable-diagnostic-colors");
 
diff --git a/lib/src/runner/browser/platform.dart b/lib/src/runner/browser/platform.dart
index e430231..0d84ccc 100644
--- a/lib/src/runner/browser/platform.dart
+++ b/lib/src/runner/browser/platform.dart
@@ -8,12 +8,14 @@
 
 import 'package:async/async.dart';
 import 'package:http_multi_server/http_multi_server.dart';
+import 'package:package_resolver/package_resolver.dart';
 import 'package:path/path.dart' as p;
 import 'package:pool/pool.dart';
 import 'package:shelf/shelf.dart' as shelf;
 import 'package:shelf/shelf_io.dart' as shelf_io;
 import 'package:shelf_static/shelf_static.dart';
 import 'package:shelf_web_socket/shelf_web_socket.dart';
+import 'package:shelf_packages_handler/shelf_packages_handler.dart';
 import 'package:stream_channel/stream_channel.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
@@ -120,7 +122,7 @@
 
     if (_config.pubServeUrl == null) {
       cascade = cascade
-          .add(_createPackagesHandler())
+          .add(packagesDirHandler())
           .add(_jsHandler.handler)
           .add(createStaticHandler(_root))
           .add(_wrapperHandler);
@@ -131,33 +133,12 @@
     }
 
     var pipeline = new shelf.Pipeline()
-      .addMiddleware(nestingMiddleware(_secret))
-      .addHandler(cascade.handler);
+        .addMiddleware(nestingMiddleware(_secret))
+        .addHandler(cascade.handler);
 
     _server.mount(pipeline);
   }
 
-  /// Returns a handler that serves the contents of the "packages/" directory
-  /// for any URL that contains "packages/".
-  ///
-  /// This is a factory so it can wrap a static handler.
-  shelf.Handler _createPackagesHandler() {
-    var staticHandler =
-      createStaticHandler(_config.packageRoot, serveFilesOutsidePath: true);
-
-    return (request) {
-      var segments = p.url.split(request.url.path);
-
-      for (var i = 0; i < segments.length; i++) {
-        if (segments[i] != "packages") continue;
-        return staticHandler(
-            request.change(path: p.url.joinAll(segments.take(i + 1))));
-      }
-
-      return new shelf.Response.notFound("Not found.");
-    };
-  }
-
   /// A handler that serves wrapper files used to bootstrap tests.
   shelf.Response _wrapperHandler(shelf.Request request) {
     var path = p.fromUri(request.url);
@@ -317,7 +298,8 @@
           _mappers[path] = new StackTraceMapper(
               await UTF8.decodeStream(response),
               mapUrl: url,
-              packageRoot: _config.pubServeUrl.resolve('packages'),
+              packageResolver: new SyncPackageResolver.root(
+                  _config.pubServeUrl.resolve('packages')),
               sdkRoot: _config.pubServeUrl.resolve('packages/\$sdk'));
           return;
         }
@@ -349,8 +331,7 @@
       var dir = new Directory(_compiledDir).createTempSync('test_').path;
       var jsPath = p.join(dir, p.basename(dartPath) + ".browser_test.dart.js");
 
-      await _compilers.compile(dartPath, jsPath,
-          packageRoot: _config.packageRoot);
+      await _compilers.compile(dartPath, jsPath);
       if (_closed) return;
 
       var jsUrl = p.toUri(p.relative(dartPath, from: _root)).path +
@@ -373,7 +354,7 @@
       _mappers[dartPath] = new StackTraceMapper(
           new File(mapPath).readAsStringSync(),
           mapUrl: p.toUri(mapPath),
-          packageRoot: p.toUri(_config.packageRoot),
+          packageResolver: await PackageResolver.current.asSync,
           sdkRoot: p.toUri(sdkDir));
     });
   }
diff --git a/lib/src/runner/configuration.dart b/lib/src/runner/configuration.dart
index 321a406..e31b066 100644
--- a/lib/src/runner/configuration.dart
+++ b/lib/src/runner/configuration.dart
@@ -68,10 +68,6 @@
   bool get pauseAfterLoad => _pauseAfterLoad ?? false;
   final bool _pauseAfterLoad;
 
-  /// The package root for resolving "package:" URLs.
-  String get packageRoot => _packageRoot ?? p.join(p.current, 'packages');
-  final String _packageRoot;
-
   /// The path to dart2js.
   String get dart2jsPath => _dart2jsPath ?? p.join(sdkDir, 'bin', 'dart2js');
   final String _dart2jsPath;
@@ -283,7 +279,6 @@
       PlatformSelector testOn,
       bool pauseAfterLoad,
       bool color,
-      String packageRoot,
       String dart2jsPath,
       Iterable<String> dart2jsArgs,
       String precompiledPath,
@@ -315,7 +310,6 @@
         testOn: testOn,
         pauseAfterLoad: pauseAfterLoad,
         color: color,
-        packageRoot: packageRoot,
         dart2jsPath: dart2jsPath,
         dart2jsArgs: dart2jsArgs,
         precompiledPath: precompiledPath,
@@ -386,7 +380,6 @@
           PlatformSelector testOn,
           bool pauseAfterLoad,
           bool color,
-          String packageRoot,
           String dart2jsPath,
           Iterable<String> dart2jsArgs,
           this.precompiledPath,
@@ -416,7 +409,6 @@
         testOn = testOn ?? PlatformSelector.all,
         _pauseAfterLoad = pauseAfterLoad,
         _color = color,
-        _packageRoot = packageRoot,
         _dart2jsPath = dart2jsPath,
         dart2jsArgs = dart2jsArgs?.toList() ?? [],
         _reporter = reporter,
@@ -491,7 +483,6 @@
         testOn: testOn.intersection(other.testOn),
         pauseAfterLoad: other._pauseAfterLoad ?? _pauseAfterLoad,
         color: other._color ?? _color,
-        packageRoot: other._packageRoot ?? _packageRoot,
         dart2jsPath: other._dart2jsPath ?? _dart2jsPath,
         dart2jsArgs: dart2jsArgs.toList()..addAll(other.dart2jsArgs),
         precompiledPath: other.precompiledPath ?? precompiledPath,
@@ -534,7 +525,6 @@
       PlatformSelector testOn,
       bool pauseAfterLoad,
       bool color,
-      String packageRoot,
       String dart2jsPath,
       Iterable<String> dart2jsArgs,
       String precompiledPath,
@@ -566,7 +556,6 @@
         testOn: testOn ?? this.testOn,
         pauseAfterLoad: pauseAfterLoad ?? _pauseAfterLoad,
         color: color ?? _color,
-        packageRoot: packageRoot ?? _packageRoot,
         dart2jsPath: dart2jsPath ?? _dart2jsPath,
         dart2jsArgs: dart2jsArgs?.toList() ?? this.dart2jsArgs,
         precompiledPath: precompiledPath ?? this.precompiledPath,
diff --git a/lib/src/runner/configuration/args.dart b/lib/src/runner/configuration/args.dart
index 84f59b6..b7ac949 100644
--- a/lib/src/runner/configuration/args.dart
+++ b/lib/src/runner/configuration/args.dart
@@ -24,7 +24,6 @@
       help: "Shows this usage information.");
   parser.addFlag("version", negatable: false,
       help: "Shows the package's version.");
-  parser.addOption("package-root", hide: true);
 
   // Note that defaultsTo declarations here are only for documentation purposes.
   // We pass null values rather than defaults to [new Configuration] so that it
@@ -192,7 +191,6 @@
         jsTrace: _ifParsed('js-trace'),
         pauseAfterLoad: _ifParsed('pause-after-load'),
         color: _ifParsed('color'),
-        packageRoot: _ifParsed('package-root'),
         dart2jsPath: _ifParsed('dart2js-path'),
         dart2jsArgs: _ifParsed('dart2js-args') as List<String>,
         precompiledPath: _ifParsed('precompiled'),
diff --git a/lib/src/runner/vm/platform.dart b/lib/src/runner/vm/platform.dart
index 41ffd41..78ce654 100644
--- a/lib/src/runner/vm/platform.dart
+++ b/lib/src/runner/vm/platform.dart
@@ -69,7 +69,7 @@
           });
           new IsolateChannel.connectSend(message).pipe(channel);
         }
-      ''', message, packageRoot: p.toUri(_config.packageRoot), checked: true);
+      ''', message, checked: true);
     }
 
     var url = _config.pubServeUrl.resolveUri(
diff --git a/lib/src/util/dart.dart b/lib/src/util/dart.dart
index f6ddff0..05cd260 100644
--- a/lib/src/util/dart.dart
+++ b/lib/src/util/dart.dart
@@ -16,18 +16,13 @@
 /// they will be resolved in the same context as the host isolate. [message] is
 /// passed to the [main] method of the code being run; the caller is responsible
 /// for using this to establish communication with the isolate.
-///
-/// [packageRoot] controls the package root of the isolate. It may be either a
-/// [String] or a [Uri].
-Future<Isolate> runInIsolate(String code, message, {packageRoot,
-    bool checked}) async {
-  if (packageRoot is String) packageRoot = Uri.parse(packageRoot);
-
+Future<Isolate> runInIsolate(String code, message, {bool checked}) async {
   return await Isolate.spawnUri(
       Uri.parse('data:application/dart;charset=utf-8,' + Uri.encodeFull(code)),
       [],
       message,
-      packageRoot: packageRoot,
+      packageRoot: await Isolate.packageRoot,
+      packageConfig: await Isolate.packageConfig,
       checked: checked);
 }
 
diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart
index 4ede604..3f7f13a 100644
--- a/lib/src/util/io.dart
+++ b/lib/src/util/io.dart
@@ -4,13 +4,11 @@
 
 import 'dart:async';
 import 'dart:io';
-import 'dart:mirrors';
 
 import 'package:path/path.dart' as p;
 import 'package:pub_semver/pub_semver.dart';
 
 import '../backend/operating_system.dart';
-import '../runner/application_exception.dart';
 import '../util/stream_queue.dart';
 import '../utils.dart';
 
@@ -52,12 +50,6 @@
     ? Platform.environment["_UNITTEST_TEMP_DIR"]
     : Directory.systemTemp.path;
 
-/// The path to the `lib` directory of the `test` package.
-String libDir({String packageRoot}) {
-  var pathToIo = libraryPath(#test.util.io, packageRoot: packageRoot);
-  return p.dirname(p.dirname(p.dirname(pathToIo)));
-}
-
 // TODO(nweiz): Make this check [stdioType] once that works within "pub run".
 /// Whether "special" strings such as Unicode characters or color escapes are
 /// safe to use.
@@ -124,34 +116,6 @@
   stderr.writeln(wordWrap("$header $message\n"));
 }
 
-/// Returns the package root at [root].
-///
-/// If [override] is passed, that's used. If the package root doesn't exist, an
-/// [ApplicationException] is thrown.
-String packageRootFor(String root, [String override]) {
-  if (root == null) root = p.current;
-  var packageRoot = override == null ? p.join(root, 'packages') : override;
-
-  if (!new Directory(packageRoot).existsSync()) {
-    throw new ApplicationException(
-        "Directory ${p.prettyUri(p.toUri(packageRoot))} does not exist.");
-  }
-
-  return packageRoot;
-}
-
-/// The library name must be globally unique, or the wrong library path may be
-/// returned.
-String libraryPath(Symbol libraryName, {String packageRoot}) {
-  var lib = currentMirrorSystem().findLibrary(libraryName);
-  if (lib.uri.scheme != 'package') return p.fromUri(lib.uri);
-
-  // TODO(nweiz): is there a way to avoid assuming this is being run next to a
-  // packages directory?.
-  if (packageRoot == null) packageRoot = p.absolute('packages');
-  return p.join(packageRoot, p.fromUri(lib.uri.path));
-}
-
 /// Repeatedly finds a probably-unused port on localhost and passes it to
 /// [tryPort] until it binds successfully.
 ///
diff --git a/lib/src/util/stack_trace_mapper.dart b/lib/src/util/stack_trace_mapper.dart
index a50c75e..04390fa 100644
--- a/lib/src/util/stack_trace_mapper.dart
+++ b/lib/src/util/stack_trace_mapper.dart
@@ -2,6 +2,7 @@
 // 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:package_resolver/package_resolver.dart';
 import 'package:source_map_stack_trace/source_map_stack_trace.dart' as mapper;
 import 'package:source_maps/source_maps.dart';
 
@@ -10,19 +11,20 @@
   /// The parsed source map.
   final Mapping _mapping;
 
-  /// The URI of the package root, as passed to dart2js.
-  final Uri _packageRoot;
+  /// The package resolution information passed to dart2js.
+  final SyncPackageResolver _packageResolver;
 
   /// The URI of the SDK root from which dart2js loaded its sources.
   final Uri _sdkRoot;
 
-  StackTraceMapper(String contents, {Uri mapUrl, Uri packageRoot, Uri sdkRoot})
+  StackTraceMapper(String contents, {Uri mapUrl,
+        SyncPackageResolver packageResolver, Uri sdkRoot})
     : _mapping = parse(contents, mapUrl: mapUrl),
-      _packageRoot = packageRoot,
+      _packageResolver = packageResolver,
       _sdkRoot = sdkRoot;
 
   /// Converts [trace] into a Dart stack trace.
   StackTrace mapStackTrace(StackTrace trace) =>
       mapper.mapStackTrace(_mapping, trace,
-          packageRoot: _packageRoot, sdkRoot: _sdkRoot);
+          packageResolver: _packageResolver, sdkRoot: _sdkRoot);
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index 6a4d8e5..c67e91d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
 name: test
-version: 0.12.15+1
+version: 0.12.15+2
 author: Dart Team <misc@dartlang.org>
 description: A library for writing dart unit tests.
 homepage: https://github.com/dart-lang/test
 environment:
-  sdk: '>=1.13.0 <1.20.0'
+  sdk: '>=1.14.0 <2.0.0'
 dependencies:
   analyzer: '>=0.23.0 <0.28.0'
   args: '^0.13.1'
@@ -14,13 +14,15 @@
   collection: '^1.8.0'
   glob: '^1.0.0'
   http_multi_server: '>=1.0.0 <3.0.0'
+  package_resolver: '^1.0.0'
   path: '^1.2.0'
   pool: '^1.2.0'
   pub_semver: '^1.0.0'
   shelf: '>=0.6.5 <0.8.0'
+  shelf_packages_handler: '^1.0.0'
   shelf_static: '^0.2.0'
   shelf_web_socket: '^0.2.0'
-  source_map_stack_trace: '^1.0.0'
+  source_map_stack_trace: '^1.1.0'
   source_maps: '^0.10.1'
   source_span: '^1.0.0'
   stack_trace: '^1.2.1'
diff --git a/test/io.dart b/test/io.dart
index b89e40c..331a220 100644
--- a/test/io.dart
+++ b/test/io.dart
@@ -8,7 +8,9 @@
 
 import 'dart:async';
 import 'dart:io';
+import 'dart:isolate';
 
+import 'package:package_resolver/package_resolver.dart';
 import 'package:path/path.dart' as p;
 import 'package:scheduled_test/descriptor.dart' as d;
 import 'package:scheduled_test/scheduled_process.dart';
@@ -17,7 +19,7 @@
 import 'package:test/src/util/io.dart';
 
 /// The path to the root directory of the `test` package.
-final String packageDir = p.dirname(p.dirname(libraryPath(#test.test.io)));
+final Future<String> packageDir = PackageResolver.current.packagePath('test');
 
 /// The path to the `pub` executable in the current Dart SDK.
 final _pubPath = p.absolute(p.join(
@@ -108,8 +110,7 @@
   concurrency ??= 1;
 
   var allArgs = [
-    p.absolute(p.join(packageDir, 'bin/test.dart')),
-    "--package-root=${p.join(packageDir, 'packages')}",
+    packageDir.then((dir) => p.absolute(p.join(dir, 'bin/test.dart'))),
     "--concurrency=$concurrency"
   ];
   if (reporter != null) allArgs.add("--reporter=$reporter");
@@ -133,13 +134,12 @@
 /// Runs Dart.
 ScheduledProcess runDart(List<String> args, {Map<String, String> environment,
     String description}) {
-  var allArgs = Platform.executableArguments.map((arg) {
-    // The package root might be relative, so we need to make it absolute if
-    // we're going to run in a different working directory.
-    if (!arg.startsWith("--package-root=")) return arg;
-    return "--package-root=" +
-        p.absolute(p.fromUri(arg.substring("--package-root=".length)));
-  }).toList()..addAll(args);
+  var allArgs = Platform.executableArguments
+      .where((arg) =>
+          !arg.startsWith("--package-root=") && !arg.startsWith("--packages="))
+      .toList()
+      ..add(PackageResolver.current.processArgument)
+      ..addAll(args);
 
   return new ScheduledProcess.start(
       p.absolute(Platform.resolvedExecutable), allArgs,
diff --git a/test/runner/browser/loader_test.dart b/test/runner/browser/loader_test.dart
index 1c924d3..4eae04b 100644
--- a/test/runner/browser/loader_test.dart
+++ b/test/runner/browser/loader_test.dart
@@ -34,11 +34,9 @@
 """;
 
 void main() {
-  setUp(() {
+  setUp(() async {
     _sandbox = createTempDir();
-    _loader = new Loader(new Configuration(
-            platforms: [TestPlatform.chrome],
-            packageRoot: p.join(packageDir, 'packages')),
+    _loader = new Loader(new Configuration(platforms: [TestPlatform.chrome]),
         root: _sandbox);
     /// TODO(nweiz): Use scheduled_test for this once it's compatible with this
     /// version of test.
@@ -127,9 +125,7 @@
 
   test("loads a suite both in the browser and the VM", () async {
     var loader = new Loader(
-        new Configuration(
-            platforms: [TestPlatform.vm, TestPlatform.chrome],
-            packageRoot: p.join(packageDir, 'packages')),
+        new Configuration(platforms: [TestPlatform.vm, TestPlatform.chrome]),
         root: _sandbox);
     var path = p.join(_sandbox, 'a_test.dart');
 
diff --git a/test/runner/configuration/configuration_test.dart b/test/runner/configuration/configuration_test.dart
index 2a4a2e0..92c824d 100644
--- a/test/runner/configuration/configuration_test.dart
+++ b/test/runner/configuration/configuration_test.dart
@@ -30,7 +30,6 @@
         expect(merged.color, equals(canUseSpecialChars));
         expect(merged.shardIndex, isNull);
         expect(merged.totalShards, isNull);
-        expect(merged.packageRoot, equals(p.join(p.current, 'packages')));
         expect(merged.dart2jsPath, equals(p.join(sdkDir, 'bin', 'dart2js')));
         expect(merged.precompiledPath, isNull);
         expect(merged.reporter, equals(defaultReporter));
@@ -52,7 +51,6 @@
                 color: true,
                 shardIndex: 3,
                 totalShards: 10,
-                packageRoot: "root",
                 dart2jsPath: "/tmp/dart2js",
                 precompiledPath: "/tmp/js",
                 reporter: "json",
@@ -72,7 +70,6 @@
         expect(merged.color, isTrue);
         expect(merged.shardIndex, equals(3));
         expect(merged.totalShards, equals(10));
-        expect(merged.packageRoot, equals("root"));
         expect(merged.dart2jsPath, equals("/tmp/dart2js"));
         expect(merged.precompiledPath, equals("/tmp/js"));
         expect(merged.reporter, equals("json"));
@@ -94,7 +91,6 @@
             color: true,
             shardIndex: 3,
             totalShards: 10,
-            packageRoot: "root",
             dart2jsPath: "/tmp/dart2js",
             precompiledPath: "/tmp/js",
             reporter: "json",
@@ -113,7 +109,6 @@
         expect(merged.color, isTrue);
         expect(merged.shardIndex, equals(3));
         expect(merged.totalShards, equals(10));
-        expect(merged.packageRoot, equals("root"));
         expect(merged.dart2jsPath, equals("/tmp/dart2js"));
         expect(merged.precompiledPath, equals("/tmp/js"));
         expect(merged.reporter, equals("json"));
@@ -136,7 +131,6 @@
             color: false,
             shardIndex: 2,
             totalShards: 4,
-            packageRoot: "root",
             dart2jsPath: "/tmp/dart2js",
             precompiledPath: "/tmp/js",
             reporter: "json",
@@ -155,7 +149,6 @@
             color: true,
             shardIndex: 3,
             totalShards: 10,
-            packageRoot: "boot",
             dart2jsPath: "../dart2js",
             precompiledPath: "../js",
             reporter: "compact",
@@ -174,7 +167,6 @@
         expect(merged.color, isTrue);
         expect(merged.shardIndex, equals(3));
         expect(merged.totalShards, equals(10));
-        expect(merged.packageRoot, equals("boot"));
         expect(merged.dart2jsPath, equals("../dart2js"));
         expect(merged.precompiledPath, equals("../js"));
         expect(merged.reporter, equals("compact"));
diff --git a/test/runner/loader_test.dart b/test/runner/loader_test.dart
index f93bae9..182d2e2 100644
--- a/test/runner/loader_test.dart
+++ b/test/runner/loader_test.dart
@@ -33,10 +33,10 @@
 """;
 
 void main() {
-  setUp(() {
+  setUp(() async {
     _sandbox = createTempDir();
     _loader = new Loader(
-        new Configuration(packageRoot: p.join(packageDir, 'packages')),
+        new Configuration(),
         root: _sandbox);
   });
 
diff --git a/test/runner/precompiled_paths_test.dart b/test/runner/precompiled_paths_test.dart
index a60a0c8..a5763da 100644
--- a/test/runner/precompiled_paths_test.dart
+++ b/test/runner/precompiled_paths_test.dart
@@ -7,6 +7,7 @@
 
 import 'dart:io';
 
+import 'package:package_resolver/package_resolver.dart';
 import 'package:path/path.dart' as p;
 import 'package:scheduled_test/descriptor.dart' as d;
 import 'package:scheduled_test/scheduled_process.dart';
@@ -39,7 +40,7 @@
     d.dir("precompiled", []).create();
 
     var dart2js = new ScheduledProcess.start(p.join(sdkDir, 'bin', 'dart2js'), [
-      "--package-root=${p.join(p.current, 'packages')}",
+      PackageResolver.current.processArgument,
       "to_precompile.dart",
       "--out=precompiled/test.dart.browser_test.dart.js"
     ], workingDirectory: sandbox);