diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 588b150..b5a3097 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -504,6 +504,10 @@
   /// The list of changed file paths.
   final List<String> _changedPaths = [];
 
+  /// While processing [_changedPaths] we accumulate libraries here.
+  /// Then we process all of them at once, and reset to the empty set.
+  Set<_File> _invalidatedLibraries = {};
+
   /// The list of files scheduled for processing.  It may include parts and
   /// libraries, but parts are ignored when we detect them.
   final List<_ScheduledFile> _scheduledFiles = [];
@@ -529,7 +533,9 @@
       _whenKnownFilesPulled = now;
       pullKnownFiles();
     }
-    return _changedPaths.isNotEmpty || _scheduledFiles.isNotEmpty;
+    return _changedPaths.isNotEmpty ||
+        _invalidatedLibraries.isNotEmpty ||
+        _scheduledFiles.isNotEmpty;
   }
 
   /// Add the [analysisContext], so that its libraries are reported via the
@@ -595,6 +601,13 @@
       return;
     }
 
+    // There are no more changes as far as we know.
+    // So, recompute exported declarations for all invalidated libraries.
+    if (_invalidatedLibraries.isNotEmpty) {
+      _processInvalidatedLibraries(_invalidatedLibraries);
+      _invalidatedLibraries = {};
+    }
+
     if (_scheduledFiles.isNotEmpty) {
       var scheduledFile = _scheduledFiles.removeLast();
       var file = _getFileByPath(scheduledFile.context, [], scheduledFile.path)!;
@@ -794,11 +807,33 @@
         _invalidateExportedDeclarations(invalidatedLibraries, newLibrary);
       }
     }
-    _computeExportedDeclarations(invalidatedLibraries);
 
-    var changedLibraries = <Library>[];
+    // Don't compute exported declarations now, there might be more changes.
+    // Instead, accumulate invalidated libraries, and recompute all later.
+    _invalidatedLibraries.addAll(invalidatedLibraries);
+
     var removedLibraries = <int>[];
     for (var libraryFile in invalidatedLibraries) {
+      if (!libraryFile.exists) {
+        _idToLibrary.remove(libraryFile.id);
+        removedLibraries.add(libraryFile.id);
+      }
+    }
+    for (var file in notLibraries) {
+      _idToLibrary.remove(file.id);
+      removedLibraries.add(file.id);
+    }
+    if (removedLibraries.isNotEmpty) {
+      _changesController.add(
+        LibraryChange._([], removedLibraries),
+      );
+    }
+  }
+
+  void _processInvalidatedLibraries(Set<_File> invalidatedLibraries) {
+    _computeExportedDeclarations(invalidatedLibraries);
+    var changedLibraries = <Library>[];
+    for (var libraryFile in invalidatedLibraries) {
       if (libraryFile.exists) {
         var library = Library._(
           libraryFile.id,
@@ -809,17 +844,10 @@
         );
         _idToLibrary[library.id] = library;
         changedLibraries.add(library);
-      } else {
-        _idToLibrary.remove(libraryFile.id);
-        removedLibraries.add(libraryFile.id);
       }
     }
-    for (var file in notLibraries) {
-      _idToLibrary.remove(file.id);
-      removedLibraries.add(file.id);
-    }
     _changesController.add(
-      LibraryChange._(changedLibraries, removedLibraries),
+      LibraryChange._(changedLibraries, []),
     );
   }
 
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 17908dd..357ca89 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -914,6 +914,75 @@
     ]);
   }
 
+  /// https://github.com/dart-lang/sdk/issues/47804
+  test_updated_exported2() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+    var c = convertPath('/home/test/lib/c.dart');
+
+    newFile(a, content: r'''
+class A {}
+''');
+    newFile(b, content: r'''
+class B {}
+''');
+    newFile(c, content: r'''
+export 'a.dart';
+export 'b.dart';
+class C {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/c.dart', declarations: [
+      _ExpectedDeclaration.class_('A', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('C', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+
+    changes.clear();
+
+    newFile(a, content: r'''
+class A2 {}
+''');
+    newFile(b, content: r'''
+class B2 {}
+''');
+    tracker.changeFile(a);
+    tracker.changeFile(b);
+    await _doAllTrackerWork();
+
+    // In general it is OK to get duplicate libraries.
+    // But here we notified about both `a.dart` and `b.dart` changes before
+    // performing any work. So, there is no reason do handle `c.dart` twice.
+    var uniquePathSet = <String>{};
+    for (var change in changes) {
+      for (var library in change.changed) {
+        if (!uniquePathSet.add(library.path)) {
+          fail('Not unique path: ${library.path}');
+        }
+      }
+    }
+
+    _assertHasLibrary('package:test/c.dart', declarations: [
+      _ExpectedDeclaration.class_('A2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('B2', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+      _ExpectedDeclaration.class_('C', [
+        _ExpectedDeclaration.constructor(''),
+      ]),
+    ]);
+  }
+
   test_updated_library() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
diff --git a/pkg/compiler/tool/modular_test_suite.dart b/pkg/compiler/tool/modular_test_suite.dart
index 9257730..7a20a67 100644
--- a/pkg/compiler/tool/modular_test_suite.dart
+++ b/pkg/compiler/tool/modular_test_suite.dart
@@ -5,44 +5,25 @@
 /// Test the modular compilation pipeline of dart2js.
 ///
 /// This is a shell that runs multiple tests, one per folder under `data/`.
-import 'dart:io';
 import 'dart:async';
 
-import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/kernel/dart2js_target.dart';
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
 import 'package:modular_test/src/io_pipeline.dart';
-import 'package:modular_test/src/pipeline.dart';
-import 'package:modular_test/src/suite.dart';
 import 'package:modular_test/src/runner.dart';
-import 'package:package_config/package_config.dart';
+import 'modular_test_suite_helper.dart';
 
-String packageConfigJsonPath = ".dart_tool/package_config.json";
-Uri sdkRoot = Platform.script.resolve("../../../");
-Uri packageConfigUri = sdkRoot.resolve(packageConfigJsonPath);
-Options _options;
-String _dart2jsScript;
-String _kernelWorkerScript;
-
-// TODO(joshualitt): Figure out a way to support package configs in
-// tests/modular.
-PackageConfig _packageConfig;
 main(List<String> args) async {
-  _options = Options.parse(args);
-  _packageConfig = await loadPackageConfigUri(packageConfigUri);
-  await _resolveScripts();
+  var options = Options.parse(args);
+  await resolveScripts(options);
   await Future.wait([
-    // TODO(joshualitt): Factor modular steps into a library so we can test
-    // modular analysis alongside the existing pipeline.
     runSuite(
         sdkRoot.resolve('tests/modular/'),
         'tests/modular',
-        _options,
+        options,
         IOPipeline([
           OutlineDillCompilationStep(),
           FullDillCompilationStep(),
-          ComputeClosedWorldStep(useModularAnalysis: false),
+          ModularAnalysisStep(),
+          ComputeClosedWorldStep(useModularAnalysis: true),
           GlobalAnalysisStep(),
           Dart2jsCodegenStep(codeId0),
           Dart2jsCodegenStep(codeId1),
@@ -51,631 +32,3 @@
         ], cacheSharedModules: true)),
   ]);
 }
-
-const dillSummaryId = DataId("sdill");
-const dillId = DataId("dill");
-const modularUpdatedDillId = DataId("mdill");
-const modularDataId = DataId("mdata");
-const closedWorldId = DataId("world");
-const globalUpdatedDillId = DataId("gdill");
-const globalDataId = DataId("gdata");
-const codeId = ShardsDataId("code", 2);
-const codeId0 = ShardDataId(codeId, 0);
-const codeId1 = ShardDataId(codeId, 1);
-const jsId = DataId("js");
-const txtId = DataId("txt");
-const fakeRoot = 'dev-dart-app:/';
-
-String _packageConfigEntry(String name, Uri root,
-    {Uri packageRoot, LanguageVersion version}) {
-  var fields = [
-    '"name": "${name}"',
-    '"rootUri": "$root"',
-    if (packageRoot != null) '"packageUri": "$packageRoot"',
-    if (version != null) '"languageVersion": "$version"'
-  ];
-  return '{${fields.join(',')}}';
-}
-
-abstract class CFEStep implements IOModularStep {
-  final String stepName;
-
-  CFEStep(this.stepName);
-
-  @override
-  bool get needsSources => true;
-
-  @override
-  bool get onlyOnMain => false;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("\nstep: $stepName on $module");
-
-    // We use non file-URI schemes for representeing source locations in a
-    // root-agnostic way. This allows us to refer to file across modules and
-    // across steps without exposing the underlying temporary folders that are
-    // created by the framework. In build systems like bazel this is especially
-    // important because each step may be run on a different machine.
-    //
-    // Files in packages are defined in terms of `package:` URIs, while
-    // non-package URIs are defined using the `dart-dev-app` scheme.
-    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
-    String sourceToImportUri(Uri relativeUri) {
-      if (module.isPackage) {
-        var basePath = module.packageBase.path;
-        var packageRelativePath = basePath == "./"
-            ? relativeUri.path
-            : relativeUri.path.substring(basePath.length);
-        return 'package:${module.name}/$packageRelativePath';
-      } else {
-        return '$rootScheme:/$relativeUri';
-      }
-    }
-
-    // We create both a .packages and package_config.json file which defines
-    // the location of this module if it is a package.  The CFE requires that
-    // if a `package:` URI of a dependency is used in an import, then we need
-    // that package entry in the associated file. However, after it checks that
-    // the definition exists, the CFE will not actually use the resolved URI if
-    // a library for the import URI is already found in one of the provide
-    // .dill files of the dependencies. For that reason, and to ensure that
-    // a step only has access to the files provided in a module, we generate a
-    // config file with invalid folders for other packages.
-    // TODO(sigmund): follow up with the CFE to see if we can remove the need
-    // for these dummy entries..
-    // TODO(joshualitt): Generate just the json file.
-    var packagesJson = [];
-    var packagesContents = StringBuffer();
-    if (module.isPackage) {
-      packagesContents.write('${module.name}:${module.packageBase}\n');
-      packagesJson.add(_packageConfigEntry(
-          module.name, Uri.parse('../${module.packageBase}')));
-    }
-
-    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
-    int unusedNum = 0;
-    for (Module dependency in transitiveDependencies) {
-      if (dependency.isPackage) {
-        // rootUri should be ignored for dependent modules, so we pass in a
-        // bogus value.
-        var rootUri = Uri.parse('unused$unusedNum');
-        unusedNum++;
-
-        var dependentPackage = _packageConfig[dependency.name];
-        var packageJson = dependentPackage == null
-            ? _packageConfigEntry(dependency.name, rootUri)
-            : _packageConfigEntry(dependentPackage.name, rootUri,
-                version: dependentPackage.languageVersion);
-        packagesJson.add(packageJson);
-        packagesContents.write('${dependency.name}:$rootUri\n');
-      }
-    }
-
-    if (module.isPackage) {
-      await File.fromUri(root.resolve(packageConfigJsonPath))
-          .create(recursive: true);
-      await File.fromUri(root.resolve(packageConfigJsonPath)).writeAsString('{'
-          '  "configVersion": ${_packageConfig.version},'
-          '  "packages": [ ${packagesJson.join(',')} ]'
-          '}');
-    }
-
-    await File.fromUri(root.resolve('.packages'))
-        .writeAsString('$packagesContents');
-
-    List<String> sources;
-    List<String> extraArgs = ['--packages-file', '$rootScheme:/.packages'];
-    if (module.isSdk) {
-      // When no flags are passed, we can skip compilation and reuse the
-      // platform.dill created by build.py.
-      if (flags.isEmpty) {
-        var platform = computePlatformBinariesLocation()
-            .resolve("dart2js_platform_unsound.dill");
-        var destination = root.resolveUri(toUri(module, outputData));
-        if (_options.verbose) {
-          print('command:\ncp $platform $destination');
-        }
-        await File.fromUri(platform).copy(destination.toFilePath());
-        return;
-      }
-      sources = requiredLibraries['dart2js'] + ['dart:core'];
-      extraArgs += [
-        '--libraries-file',
-        '$rootScheme:///sdk/lib/libraries.json'
-      ];
-      assert(transitiveDependencies.isEmpty);
-    } else {
-      sources = module.sources.map(sourceToImportUri).toList();
-    }
-
-    // TODO(joshualitt): Ensure the kernel worker has some way to specify
-    // --no-sound-null-safety
-    List<String> args = [
-      _kernelWorkerScript,
-      ...stepArguments,
-      '--exclude-non-sources',
-      '--multi-root',
-      '$root',
-      '--multi-root-scheme',
-      rootScheme,
-      ...extraArgs,
-      '--output',
-      '${toUri(module, outputData)}',
-      ...(transitiveDependencies
-          .expand((m) => ['--input-summary', '${toUri(m, inputData)}'])),
-      ...(sources.expand((String uri) => ['--source', uri])),
-      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
-    ];
-
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-    _checkExitCode(result, this, module);
-  }
-
-  List<String> get stepArguments;
-
-  DataId get inputData;
-
-  DataId get outputData;
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose) print("\ncached step: $stepName on $module");
-  }
-}
-
-// Step that compiles sources in a module to a summary .dill file.
-class OutlineDillCompilationStep extends CFEStep {
-  @override
-  List<DataId> get resultData => const [dillSummaryId];
-
-  @override
-  bool get needsSources => true;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [dillSummaryId];
-
-  @override
-  List<DataId> get moduleDataNeeded => const [];
-
-  @override
-  List<String> get stepArguments =>
-      ['--target', 'dart2js_summary', '--summary-only'];
-
-  @override
-  DataId get inputData => dillSummaryId;
-
-  @override
-  DataId get outputData => dillSummaryId;
-
-  OutlineDillCompilationStep() : super('outline-dill-compilation');
-}
-
-// Step that compiles sources in a module to a .dill file.
-class FullDillCompilationStep extends CFEStep {
-  @override
-  List<DataId> get resultData => const [dillId];
-
-  @override
-  bool get needsSources => true;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [dillSummaryId];
-
-  @override
-  List<DataId> get moduleDataNeeded => const [];
-
-  @override
-  List<String> get stepArguments =>
-      ['--target', 'dart2js', '--no-summary', '--no-summary-only'];
-
-  @override
-  DataId get inputData => dillSummaryId;
-
-  @override
-  DataId get outputData => dillId;
-
-  FullDillCompilationStep() : super('full-dill-compilation');
-}
-
-class ModularAnalysisStep implements IOModularStep {
-  @override
-  List<DataId> get resultData => const [modularDataId, modularUpdatedDillId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [dillId];
-
-  @override
-  List<DataId> get moduleDataNeeded => const [dillId];
-
-  @override
-  bool get onlyOnMain => false;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("\nstep: modular analysis on $module");
-    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
-    Iterable<String> dillDependencies =
-        transitiveDependencies.map((m) => '${toUri(m, dillId)}');
-    List<String> args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
-      _dart2jsScript,
-      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${Flags.inputDill}=${toUri(module, dillId)}',
-      if (dillDependencies.isNotEmpty)
-        '--dill-dependencies=${dillDependencies.join(',')}',
-      '--out=${toUri(module, modularUpdatedDillId)}',
-      '${Flags.writeModularAnalysis}=${toUri(module, modularDataId)}',
-      for (String flag in flags) '--enable-experiment=$flag',
-    ];
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose) {
-      print("cached step: dart2js modular analysis on $module");
-    }
-  }
-}
-
-DataId idForDill({bool useModularAnalysis}) =>
-    useModularAnalysis ? modularUpdatedDillId : dillId;
-
-List<DataId> inputFromAnalysis({bool useModularAnalysis = false}) => [
-      idForDill(useModularAnalysis: useModularAnalysis),
-      if (useModularAnalysis) modularDataId,
-    ];
-
-// Step that invokes the dart2js closed world computation.
-class ComputeClosedWorldStep implements IOModularStep {
-  final bool useModularAnalysis;
-
-  ComputeClosedWorldStep({this.useModularAnalysis});
-
-  @override
-  List<DataId> get resultData => const [closedWorldId, globalUpdatedDillId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded =>
-      inputFromAnalysis(useModularAnalysis: useModularAnalysis);
-
-  @override
-  List<DataId> get moduleDataNeeded =>
-      inputFromAnalysis(useModularAnalysis: useModularAnalysis);
-
-  @override
-  bool get onlyOnMain => true;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose)
-      print("\nstep: dart2js compute closed world on $module");
-    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
-    DataId dillId = idForDill(useModularAnalysis: useModularAnalysis);
-    Iterable<String> dillDependencies =
-        transitiveDependencies.map((m) => '${toUri(m, dillId)}');
-    List<String> dataDependencies = transitiveDependencies
-        .map((m) => '${toUri(m, modularDataId)}')
-        .toList();
-    dataDependencies.add('${toUri(module, modularDataId)}');
-    List<String> args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
-      _dart2jsScript,
-      // TODO(sigmund): remove this dependency on libraries.json
-      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
-      '${Flags.inputDill}=${toUri(module, dillId)}',
-      for (String flag in flags) '--enable-experiment=$flag',
-      '${Flags.dillDependencies}=${dillDependencies.join(',')}',
-      if (useModularAnalysis)
-        '${Flags.readModularAnalysis}=${dataDependencies.join(',')}',
-      '${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}',
-      '--out=${toUri(module, globalUpdatedDillId)}',
-    ];
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose)
-      print("\ncached step: dart2js compute closed world on $module");
-  }
-}
-
-// Step that runs the dart2js modular analysis.
-class GlobalAnalysisStep implements IOModularStep {
-  @override
-  List<DataId> get resultData => const [globalDataId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [globalUpdatedDillId];
-
-  @override
-  List<DataId> get moduleDataNeeded =>
-      const [closedWorldId, globalUpdatedDillId];
-
-  @override
-  bool get onlyOnMain => true;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("\nstep: dart2js global analysis on $module");
-    List<String> args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
-      _dart2jsScript,
-      // TODO(sigmund): remove this dependency on libraries.json
-      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
-      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
-      for (String flag in flags) '--enable-experiment=$flag',
-      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
-      '${Flags.writeData}=${toUri(module, globalDataId)}',
-    ];
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose)
-      print("\ncached step: dart2js global analysis on $module");
-  }
-}
-
-// Step that invokes the dart2js code generation on the main module given the
-// results of the global analysis step and produces one shard of the codegen
-// output.
-class Dart2jsCodegenStep implements IOModularStep {
-  final ShardDataId codeId;
-
-  Dart2jsCodegenStep(this.codeId);
-
-  @override
-  List<DataId> get resultData => [codeId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [];
-
-  @override
-  List<DataId> get moduleDataNeeded =>
-      const [globalUpdatedDillId, closedWorldId, globalDataId];
-
-  @override
-  bool get onlyOnMain => true;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("\nstep: dart2js backend on $module");
-    List<String> args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
-      _dart2jsScript,
-      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
-      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
-      for (String flag in flags) '--enable-experiment=$flag',
-      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
-      '${Flags.readData}=${toUri(module, globalDataId)}',
-      '${Flags.writeCodegen}=${toUri(module, codeId.dataId)}',
-      '${Flags.codegenShard}=${codeId.shard}',
-      '${Flags.codegenShards}=${codeId.dataId.shards}',
-    ];
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose) print("cached step: dart2js backend on $module");
-  }
-}
-
-// Step that invokes the dart2js codegen enqueuer and emitter on the main module
-// given the results of the global analysis step and codegen shards.
-class Dart2jsEmissionStep implements IOModularStep {
-  @override
-  List<DataId> get resultData => const [jsId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [];
-
-  @override
-  List<DataId> get moduleDataNeeded => const [
-        globalUpdatedDillId,
-        closedWorldId,
-        globalDataId,
-        codeId0,
-        codeId1
-      ];
-
-  @override
-  bool get onlyOnMain => true;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("step: dart2js backend on $module");
-    List<String> args = [
-      '--packages=${sdkRoot.toFilePath()}/.packages',
-      _dart2jsScript,
-      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
-      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
-      for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
-      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
-      '${Flags.readData}=${toUri(module, globalDataId)}',
-      '${Flags.readCodegen}=${toUri(module, codeId)}',
-      '${Flags.codegenShards}=${codeId.shards}',
-      '--out=${toUri(module, jsId)}',
-    ];
-    var result =
-        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose) print("\ncached step: dart2js backend on $module");
-  }
-}
-
-/// Step that runs the output of dart2js in d8 and saves the output.
-class RunD8 implements IOModularStep {
-  @override
-  List<DataId> get resultData => const [txtId];
-
-  @override
-  bool get needsSources => false;
-
-  @override
-  List<DataId> get dependencyDataNeeded => const [];
-
-  @override
-  List<DataId> get moduleDataNeeded => const [jsId];
-
-  @override
-  bool get onlyOnMain => true;
-
-  @override
-  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
-      List<String> flags) async {
-    if (_options.verbose) print("\nstep: d8 on $module");
-    List<String> d8Args = [
-      sdkRoot
-          .resolve('sdk/lib/_internal/js_runtime/lib/preambles/d8.js')
-          .toFilePath(),
-      root.resolveUri(toUri(module, jsId)).toFilePath(),
-    ];
-    var result = await _runProcess(
-        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
-
-    _checkExitCode(result, this, module);
-
-    await File.fromUri(root.resolveUri(toUri(module, txtId)))
-        .writeAsString(result.stdout);
-  }
-
-  @override
-  void notifyCached(Module module) {
-    if (_options.verbose) print("\ncached step: d8 on $module");
-  }
-}
-
-void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
-  if (result.exitCode != 0 || _options.verbose) {
-    stdout.write(result.stdout);
-    stderr.write(result.stderr);
-  }
-  if (result.exitCode != 0) {
-    throw "${step.runtimeType} failed on $module:\n\n"
-        "stdout:\n${result.stdout}\n\n"
-        "stderr:\n${result.stderr}";
-  }
-}
-
-Future<ProcessResult> _runProcess(
-    String command, List<String> arguments, String workingDirectory) {
-  if (_options.verbose) {
-    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
-  }
-  return Process.run(command, arguments, workingDirectory: workingDirectory);
-}
-
-String get _d8executable {
-  if (Platform.isWindows) {
-    return 'third_party/d8/windows/d8.exe';
-  } else if (Platform.isLinux) {
-    return 'third_party/d8/linux/d8';
-  } else if (Platform.isMacOS) {
-    return 'third_party/d8/macos/d8';
-  }
-  throw UnsupportedError('Unsupported platform.');
-}
-
-class ShardsDataId implements DataId {
-  @override
-  final String name;
-  final int shards;
-
-  const ShardsDataId(this.name, this.shards);
-
-  @override
-  String toString() => name;
-}
-
-class ShardDataId implements DataId {
-  final ShardsDataId dataId;
-  final int _shard;
-
-  const ShardDataId(this.dataId, this._shard);
-
-  int get shard {
-    assert(0 <= _shard && _shard < dataId.shards);
-    return _shard;
-  }
-
-  @override
-  String get name => '${dataId.name}${shard}';
-
-  @override
-  String toString() => name;
-}
-
-Future<void> _resolveScripts() async {
-  Future<String> resolve(
-      String sourceUriOrPath, String relativeSnapshotPath) async {
-    Uri sourceUri = sdkRoot.resolve(sourceUriOrPath);
-    String result =
-        sourceUri.scheme == 'file' ? sourceUri.toFilePath() : sourceUriOrPath;
-    if (_options.useSdk) {
-      String snapshot = Uri.file(Platform.resolvedExecutable)
-          .resolve(relativeSnapshotPath)
-          .toFilePath();
-      if (await File(snapshot).exists()) {
-        return snapshot;
-      }
-    }
-    return result;
-  }
-
-  _dart2jsScript = await resolve(
-      'package:compiler/src/dart2js.dart', 'snapshots/dart2js.dart.snapshot');
-  _kernelWorkerScript = await resolve('utils/bazel/kernel_worker.dart',
-      'snapshots/kernel_worker.dart.snapshot');
-}
-
-String _librarySpecForSnapshot = Uri.file(Platform.resolvedExecutable)
-    .resolve('../lib/libraries.json')
-    .toFilePath();
diff --git a/pkg/compiler/tool/modular_test_suite_helper.dart b/pkg/compiler/tool/modular_test_suite_helper.dart
new file mode 100644
index 0000000..cd583ad
--- /dev/null
+++ b/pkg/compiler/tool/modular_test_suite_helper.dart
@@ -0,0 +1,662 @@
+// Copyright (c) 2019, 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.
+
+/// Test the modular compilation pipeline of dart2js.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+import 'dart:async';
+
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/kernel/dart2js_target.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+import 'package:package_config/package_config.dart';
+
+String packageConfigJsonPath = ".dart_tool/package_config.json";
+Uri sdkRoot = Platform.script.resolve("../../../");
+Uri packageConfigUri = sdkRoot.resolve(packageConfigJsonPath);
+Options _options;
+String _dart2jsScript;
+String _kernelWorkerScript;
+
+const dillSummaryId = DataId("sdill");
+const dillId = DataId("dill");
+const modularUpdatedDillId = DataId("mdill");
+const modularDataId = DataId("mdata");
+const closedWorldId = DataId("world");
+const globalUpdatedDillId = DataId("gdill");
+const globalDataId = DataId("gdata");
+const codeId = ShardsDataId("code", 2);
+const codeId0 = ShardDataId(codeId, 0);
+const codeId1 = ShardDataId(codeId, 1);
+const jsId = DataId("js");
+const txtId = DataId("txt");
+const fakeRoot = 'dev-dart-app:/';
+
+String _packageConfigEntry(String name, Uri root,
+    {Uri packageRoot, LanguageVersion version}) {
+  var fields = [
+    '"name": "${name}"',
+    '"rootUri": "$root"',
+    if (packageRoot != null) '"packageUri": "$packageRoot"',
+    if (version != null) '"languageVersion": "$version"'
+  ];
+  return '{${fields.join(',')}}';
+}
+
+abstract class CFEStep implements IOModularStep {
+  final String stepName;
+
+  CFEStep(this.stepName);
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: $stepName on $module");
+
+    // TODO(joshualitt): Figure out a way to support package configs in
+    // tests/modular.
+    var packageConfig = await loadPackageConfigUri(packageConfigUri);
+
+    // We use non file-URI schemes for representeing source locations in a
+    // root-agnostic way. This allows us to refer to file across modules and
+    // across steps without exposing the underlying temporary folders that are
+    // created by the framework. In build systems like bazel this is especially
+    // important because each step may be run on a different machine.
+    //
+    // Files in packages are defined in terms of `package:` URIs, while
+    // non-package URIs are defined using the `dart-dev-app` scheme.
+    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
+    String sourceToImportUri(Uri relativeUri) {
+      if (module.isPackage) {
+        var basePath = module.packageBase.path;
+        var packageRelativePath = basePath == "./"
+            ? relativeUri.path
+            : relativeUri.path.substring(basePath.length);
+        return 'package:${module.name}/$packageRelativePath';
+      } else {
+        return '$rootScheme:/$relativeUri';
+      }
+    }
+
+    // We create both a .packages and package_config.json file which defines
+    // the location of this module if it is a package.  The CFE requires that
+    // if a `package:` URI of a dependency is used in an import, then we need
+    // that package entry in the associated file. However, after it checks that
+    // the definition exists, the CFE will not actually use the resolved URI if
+    // a library for the import URI is already found in one of the provide
+    // .dill files of the dependencies. For that reason, and to ensure that
+    // a step only has access to the files provided in a module, we generate a
+    // config file with invalid folders for other packages.
+    // TODO(sigmund): follow up with the CFE to see if we can remove the need
+    // for these dummy entries..
+    // TODO(joshualitt): Generate just the json file.
+    var packagesJson = [];
+    var packagesContents = StringBuffer();
+    if (module.isPackage) {
+      packagesContents.write('${module.name}:${module.packageBase}\n');
+      packagesJson.add(_packageConfigEntry(
+          module.name, Uri.parse('../${module.packageBase}')));
+    }
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    int unusedNum = 0;
+    for (Module dependency in transitiveDependencies) {
+      if (dependency.isPackage) {
+        // rootUri should be ignored for dependent modules, so we pass in a
+        // bogus value.
+        var rootUri = Uri.parse('unused$unusedNum');
+        unusedNum++;
+
+        var dependentPackage = packageConfig[dependency.name];
+        var packageJson = dependentPackage == null
+            ? _packageConfigEntry(dependency.name, rootUri)
+            : _packageConfigEntry(dependentPackage.name, rootUri,
+                version: dependentPackage.languageVersion);
+        packagesJson.add(packageJson);
+        packagesContents.write('${dependency.name}:$rootUri\n');
+      }
+    }
+
+    if (module.isPackage) {
+      await File.fromUri(root.resolve(packageConfigJsonPath))
+          .create(recursive: true);
+      await File.fromUri(root.resolve(packageConfigJsonPath)).writeAsString('{'
+          '  "configVersion": ${packageConfig.version},'
+          '  "packages": [ ${packagesJson.join(',')} ]'
+          '}');
+    }
+
+    await File.fromUri(root.resolve('.packages'))
+        .writeAsString('$packagesContents');
+
+    List<String> sources;
+    List<String> extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    if (module.isSdk) {
+      // When no flags are passed, we can skip compilation and reuse the
+      // platform.dill created by build.py.
+      if (flags.isEmpty) {
+        var platform = computePlatformBinariesLocation()
+            .resolve("dart2js_platform_unsound.dill");
+        var destination = root.resolveUri(toUri(module, outputData));
+        if (_options.verbose) {
+          print('command:\ncp $platform $destination');
+        }
+        await File.fromUri(platform).copy(destination.toFilePath());
+        return;
+      }
+      sources = requiredLibraries['dart2js'] + ['dart:core'];
+      extraArgs += [
+        '--libraries-file',
+        '$rootScheme:///sdk/lib/libraries.json'
+      ];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+    }
+
+    // TODO(joshualitt): Ensure the kernel worker has some way to specify
+    // --no-sound-null-safety
+    List<String> args = [
+      _kernelWorkerScript,
+      ...stepArguments,
+      '--exclude-non-sources',
+      '--multi-root',
+      '$root',
+      '--multi-root-scheme',
+      rootScheme,
+      ...extraArgs,
+      '--output',
+      '${toUri(module, outputData)}',
+      ...(transitiveDependencies
+          .expand((m) => ['--input-summary', '${toUri(m, inputData)}'])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+    ];
+
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  List<String> get stepArguments;
+
+  DataId get inputData;
+
+  DataId get outputData;
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: $stepName on $module");
+  }
+}
+
+// Step that compiles sources in a module to a summary .dill file.
+class OutlineDillCompilationStep extends CFEStep {
+  @override
+  List<DataId> get resultData => const [dillSummaryId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillSummaryId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  List<String> get stepArguments =>
+      ['--target', 'dart2js_summary', '--summary-only'];
+
+  @override
+  DataId get inputData => dillSummaryId;
+
+  @override
+  DataId get outputData => dillSummaryId;
+
+  OutlineDillCompilationStep() : super('outline-dill-compilation');
+}
+
+// Step that compiles sources in a module to a .dill file.
+class FullDillCompilationStep extends CFEStep {
+  @override
+  List<DataId> get resultData => const [dillId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillSummaryId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  List<String> get stepArguments =>
+      ['--target', 'dart2js', '--no-summary', '--no-summary-only'];
+
+  @override
+  DataId get inputData => dillSummaryId;
+
+  @override
+  DataId get outputData => dillId;
+
+  FullDillCompilationStep() : super('full-dill-compilation');
+}
+
+class ModularAnalysisStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [modularDataId, modularUpdatedDillId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [dillId];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: modular analysis on $module");
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    Iterable<String> dillDependencies =
+        transitiveDependencies.map((m) => '${toUri(m, dillId)}');
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.inputDill}=${toUri(module, dillId)}',
+      if (dillDependencies.isNotEmpty)
+        '--dill-dependencies=${dillDependencies.join(',')}',
+      '--out=${toUri(module, modularUpdatedDillId)}',
+      '${Flags.writeModularAnalysis}=${toUri(module, modularDataId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) {
+      print("cached step: dart2js modular analysis on $module");
+    }
+  }
+}
+
+DataId idForDill({bool useModularAnalysis}) =>
+    useModularAnalysis ? modularUpdatedDillId : dillId;
+
+List<DataId> inputFromAnalysis({bool useModularAnalysis = false}) => [
+      idForDill(useModularAnalysis: useModularAnalysis),
+      if (useModularAnalysis) modularDataId,
+    ];
+
+// Step that invokes the dart2js closed world computation.
+class ComputeClosedWorldStep implements IOModularStep {
+  final bool useModularAnalysis;
+
+  ComputeClosedWorldStep({this.useModularAnalysis});
+
+  @override
+  List<DataId> get resultData => const [closedWorldId, globalUpdatedDillId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded =>
+      inputFromAnalysis(useModularAnalysis: useModularAnalysis);
+
+  @override
+  List<DataId> get moduleDataNeeded =>
+      inputFromAnalysis(useModularAnalysis: useModularAnalysis);
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose)
+      print("\nstep: dart2js compute closed world on $module");
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    DataId dillId = idForDill(useModularAnalysis: useModularAnalysis);
+    Iterable<String> dillDependencies =
+        transitiveDependencies.map((m) => '${toUri(m, dillId)}');
+    List<String> dataDependencies = transitiveDependencies
+        .map((m) => '${toUri(m, modularDataId)}')
+        .toList();
+    dataDependencies.add('${toUri(module, modularDataId)}');
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      // TODO(sigmund): remove this dependency on libraries.json
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
+      '${Flags.inputDill}=${toUri(module, dillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.dillDependencies}=${dillDependencies.join(',')}',
+      if (useModularAnalysis)
+        '${Flags.readModularAnalysis}=${dataDependencies.join(',')}',
+      '${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}',
+      Flags.noClosedWorldInData,
+      '--out=${toUri(module, globalUpdatedDillId)}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose)
+      print("\ncached step: dart2js compute closed world on $module");
+  }
+}
+
+// Step that runs the dart2js modular analysis.
+class GlobalAnalysisStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [globalDataId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [globalUpdatedDillId];
+
+  @override
+  List<DataId> get moduleDataNeeded =>
+      const [closedWorldId, globalUpdatedDillId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js global analysis on $module");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      // TODO(sigmund): remove this dependency on libraries.json
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
+      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
+      '${Flags.writeData}=${toUri(module, globalDataId)}',
+      // TODO(joshualitt): delete this flag after google3 roll
+      '${Flags.noClosedWorldInData}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose)
+      print("\ncached step: dart2js global analysis on $module");
+  }
+}
+
+// Step that invokes the dart2js code generation on the main module given the
+// results of the global analysis step and produces one shard of the codegen
+// output.
+class Dart2jsCodegenStep implements IOModularStep {
+  final ShardDataId codeId;
+
+  Dart2jsCodegenStep(this.codeId);
+
+  @override
+  List<DataId> get resultData => [codeId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded =>
+      const [globalUpdatedDillId, closedWorldId, globalDataId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: dart2js backend on $module");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
+      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
+      for (String flag in flags) '--enable-experiment=$flag',
+      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.writeCodegen}=${toUri(module, codeId.dataId)}',
+      '${Flags.codegenShard}=${codeId.shard}',
+      '${Flags.codegenShards}=${codeId.dataId.shards}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("cached step: dart2js backend on $module");
+  }
+}
+
+// Step that invokes the dart2js codegen enqueuer and emitter on the main module
+// given the results of the global analysis step and codegen shards.
+class Dart2jsEmissionStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [
+        globalUpdatedDillId,
+        closedWorldId,
+        globalDataId,
+        codeId0,
+        codeId1
+      ];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("step: dart2js backend on $module");
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dart2jsScript,
+      if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
+      '${Flags.inputDill}=${toUri(module, globalUpdatedDillId)}',
+      for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
+      '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
+      '${Flags.readData}=${toUri(module, globalDataId)}',
+      '${Flags.readCodegen}=${toUri(module, codeId)}',
+      '${Flags.codegenShards}=${codeId.shards}',
+      '--out=${toUri(module, jsId)}',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: dart2js backend on $module");
+  }
+}
+
+/// Step that runs the output of dart2js in d8 and saves the output.
+class RunD8 implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [txtId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [jsId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
+    List<String> d8Args = [
+      sdkRoot
+          .resolve('sdk/lib/_internal/js_runtime/lib/preambles/d8.js')
+          .toFilePath(),
+      root.resolveUri(toUri(module, jsId)).toFilePath(),
+    ];
+    var result = await _runProcess(
+        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+
+    await File.fromUri(root.resolveUri(toUri(module, txtId)))
+        .writeAsString(result.stdout);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+  if (result.exitCode != 0 || _options.verbose) {
+    stdout.write(result.stdout);
+    stderr.write(result.stderr);
+  }
+  if (result.exitCode != 0) {
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
+  }
+}
+
+Future<ProcessResult> _runProcess(
+    String command, List<String> arguments, String workingDirectory) {
+  if (_options.verbose) {
+    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+  }
+  return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return 'third_party/d8/windows/d8.exe';
+  } else if (Platform.isLinux) {
+    return 'third_party/d8/linux/d8';
+  } else if (Platform.isMacOS) {
+    return 'third_party/d8/macos/d8';
+  }
+  throw UnsupportedError('Unsupported platform.');
+}
+
+class ShardsDataId implements DataId {
+  @override
+  final String name;
+  final int shards;
+
+  const ShardsDataId(this.name, this.shards);
+
+  @override
+  String toString() => name;
+}
+
+class ShardDataId implements DataId {
+  final ShardsDataId dataId;
+  final int _shard;
+
+  const ShardDataId(this.dataId, this._shard);
+
+  int get shard {
+    assert(0 <= _shard && _shard < dataId.shards);
+    return _shard;
+  }
+
+  @override
+  String get name => '${dataId.name}${shard}';
+
+  @override
+  String toString() => name;
+}
+
+Future<void> resolveScripts(Options options) async {
+  Future<String> resolve(
+      String sourceUriOrPath, String relativeSnapshotPath) async {
+    Uri sourceUri = sdkRoot.resolve(sourceUriOrPath);
+    String result =
+        sourceUri.scheme == 'file' ? sourceUri.toFilePath() : sourceUriOrPath;
+    if (_options.useSdk) {
+      String snapshot = Uri.file(Platform.resolvedExecutable)
+          .resolve(relativeSnapshotPath)
+          .toFilePath();
+      if (await File(snapshot).exists()) {
+        return snapshot;
+      }
+    }
+    return result;
+  }
+
+  _options = options;
+  _dart2jsScript = await resolve(
+      'package:compiler/src/dart2js.dart', 'snapshots/dart2js.dart.snapshot');
+  _kernelWorkerScript = await resolve('utils/bazel/kernel_worker.dart',
+      'snapshots/kernel_worker.dart.snapshot');
+}
+
+String _librarySpecForSnapshot = Uri.file(Platform.resolvedExecutable)
+    .resolve('../lib/libraries.json')
+    .toFilePath();
diff --git a/pkg/compiler/tool/modular_test_suite_legacy.dart b/pkg/compiler/tool/modular_test_suite_legacy.dart
new file mode 100644
index 0000000..875a64a
--- /dev/null
+++ b/pkg/compiler/tool/modular_test_suite_legacy.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2019, 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.
+
+/// Test the modular compilation pipeline of dart2js.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:async';
+
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/runner.dart';
+import 'modular_test_suite_helper.dart';
+
+main(List<String> args) async {
+  var options = Options.parse(args);
+  await resolveScripts(options);
+  await Future.wait([
+    runSuite(
+        sdkRoot.resolve('tests/modular/'),
+        'tests/modular',
+        options,
+        IOPipeline([
+          OutlineDillCompilationStep(),
+          FullDillCompilationStep(),
+          ComputeClosedWorldStep(useModularAnalysis: false),
+          GlobalAnalysisStep(),
+          Dart2jsCodegenStep(codeId0),
+          Dart2jsCodegenStep(codeId1),
+          Dart2jsEmissionStep(),
+          RunD8(),
+        ], cacheSharedModules: true)),
+  ]);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 64cee58..30279d0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 59
+PRERELEASE 60
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 2396b82..c060e70 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -424,6 +424,17 @@
         "use-sdk": true
       }
     },
+    "web-unittest-asserts-legacy-(linux|mac|win)": {
+      "options": {
+        "builder-tag": "web-legacy",
+        "compiler": "dartk",
+        "enable-asserts": true,
+        "mode": "release",
+        "runtime": "vm",
+        "timeout": 240,
+        "use-sdk": true
+      }
+    },
     "unittest-asserts-(debug|product|release)-(linux|mac|win)": {
       "options": {
         "compiler": "dartk",
@@ -2401,6 +2412,17 @@
           ]
         },
         {
+          "name": "dart2js legacy modular tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/compiler/tool/modular_test_suite_legacy.dart",
+            "-nweb-unittest-asserts-legacy-linux",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
           "name": "dart2js modular tests",
           "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "testRunner": true,
