Remove most of the target logic for build web, cleanup rules (#34589)

diff --git a/packages/flutter_tools/lib/src/build_runner/build_script.dart b/packages/flutter_tools/lib/src/build_runner/build_script.dart
new file mode 100644
index 0000000..f5da2d5
--- /dev/null
+++ b/packages/flutter_tools/lib/src/build_runner/build_script.dart
@@ -0,0 +1,459 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ignore_for_file: implementation_imports
+import 'dart:async';
+import 'dart:convert'; // ignore: dart_convert_import
+import 'dart:io'; // ignore: dart_io_import
+import 'dart:isolate';
+
+import 'package:analyzer/analyzer.dart'; // ignore: deprecated_member_use
+import 'package:build_runner/build_runner.dart' as build_runner;
+import 'package:build/build.dart';
+import 'package:build_config/build_config.dart';
+import 'package:build_modules/build_modules.dart';
+import 'package:build_modules/builders.dart';
+import 'package:build_modules/src/module_builder.dart';
+import 'package:build_modules/src/platform.dart';
+import 'package:build_modules/src/workers.dart';
+import 'package:build_runner_core/build_runner_core.dart' as core;
+import 'package:build_test/builder.dart';
+import 'package:build_test/src/debug_test_builder.dart';
+import 'package:build_web_compilers/build_web_compilers.dart';
+import 'package:build_web_compilers/builders.dart';
+import 'package:build_web_compilers/src/dev_compiler_bootstrap.dart';
+import 'package:crypto/crypto.dart';
+
+import 'package:path/path.dart' as path; // ignore: package_path_import
+import 'package:scratch_space/scratch_space.dart';
+import 'package:test_core/backend.dart';
+
+const String ddcBootstrapExtension = '.dart.bootstrap.js';
+const String jsEntrypointExtension = '.dart.js';
+const String jsEntrypointSourceMapExtension = '.dart.js.map';
+const String jsEntrypointArchiveExtension = '.dart.js.tar.gz';
+const String digestsEntrypointExtension = '.digests';
+const String jsModuleErrorsExtension = '.ddc.js.errors';
+const String jsModuleExtension = '.ddc.js';
+const String jsSourceMapExtension = '.ddc.js.map';
+
+final DartPlatform flutterWebPlatform =
+    DartPlatform.register('flutter_web', <String>[
+  'async',
+  'collection',
+  'convert',
+  'core',
+  'developer',
+  'html',
+  'html_common',
+  'indexed_db',
+  'js',
+  'js_util',
+  'math',
+  'svg',
+  'typed_data',
+  'web_audio',
+  'web_gl',
+  'web_sql',
+  '_internal',
+  // Flutter web specific libraries.
+  'ui',
+  '_engine',
+  'io',
+  'isolate',
+]);
+
+/// The builders required to compile a Flutter application to the web.
+final List<core.BuilderApplication> builders = <core.BuilderApplication>[
+  core.apply(
+    'flutter_tools:test_bootstrap',
+    <BuilderFactory>[
+      (BuilderOptions options) => const DebugTestBuilder(),
+      (BuilderOptions options) => const FlutterWebTestBootstrapBuilder(),
+    ],
+    core.toRoot(),
+    hideOutput: true,
+    defaultGenerateFor: const InputSet(
+      include: <String>[
+        'test/**',
+      ],
+    ),
+  ),
+  core.apply(
+    'flutter_tools:shell',
+    <BuilderFactory>[
+      (BuilderOptions options) => const FlutterWebShellBuilder(),
+    ],
+    core.toRoot(),
+    hideOutput: true,
+    defaultGenerateFor: const InputSet(
+      include: <String>[
+        'lib/**',
+        'web/**',
+      ],
+    ),
+  ),
+  core.apply(
+      'flutter_tools:module_library',
+      <Builder Function(BuilderOptions)>[moduleLibraryBuilder],
+      core.toAllPackages(),
+      isOptional: true,
+      hideOutput: true,
+      appliesBuilders: <String>['flutter_tools:module_cleanup']),
+  core.apply(
+      'flutter_tools:ddc_modules',
+      <Builder Function(BuilderOptions)>[
+        (BuilderOptions options) => MetaModuleBuilder(flutterWebPlatform),
+        (BuilderOptions options) => MetaModuleCleanBuilder(flutterWebPlatform),
+        (BuilderOptions options) => ModuleBuilder(flutterWebPlatform),
+      ],
+      core.toNoneByDefault(),
+      isOptional: true,
+      hideOutput: true,
+      appliesBuilders: <String>['flutter_tools:module_cleanup']),
+  core.apply(
+      'flutter_tools:ddc',
+      <Builder Function(BuilderOptions)>[
+        (BuilderOptions builderOptions) => KernelBuilder(
+              platformSdk: builderOptions.config['flutterWebSdk'],
+              summaryOnly: true,
+              sdkKernelPath: path.join('kernel', 'flutter_ddc_sdk.dill'),
+              outputExtension: ddcKernelExtension,
+              platform: flutterWebPlatform,
+              librariesPath: 'libraries.json',
+            ),
+        (BuilderOptions builderOptions) => DevCompilerBuilder(
+              useIncrementalCompiler: true,
+              platform: flutterWebPlatform,
+              platformSdk: builderOptions.config['flutterWebSdk'],
+              sdkKernelPath: path.join('kernel', 'flutter_ddc_sdk.dill'),
+            ),
+      ],
+      core.toAllPackages(),
+      isOptional: true,
+      hideOutput: true,
+      appliesBuilders: <String>['flutter_tools:ddc_modules']),
+  core.apply(
+    'flutter_tools:entrypoint',
+    <BuilderFactory>[
+      (BuilderOptions options) => FlutterWebEntrypointBuilder(
+          options.config['release'] ??  false,
+          options.config['flutterWebSdk'],
+      ),
+    ],
+    core.toRoot(),
+    hideOutput: true,
+    defaultGenerateFor: const InputSet(
+      include: <String>[
+        'lib/**_web_entrypoint.dart',
+      ],
+    ),
+  ),
+  core.apply(
+    'flutter_tools:test_entrypoint',
+    <BuilderFactory>[
+      (BuilderOptions options) => const FlutterWebTestEntrypointBuilder(),
+    ],
+    core.toRoot(),
+    hideOutput: true,
+    defaultGenerateFor: const InputSet(
+      include: <String>[
+        'test/**_test.dart.browser_test.dart',
+      ],
+    ),
+  ),
+  core.applyPostProcess('flutter_tools:module_cleanup', moduleCleanup,
+      defaultGenerateFor: const InputSet())
+];
+
+/// The entrypoint to this build script.
+Future<void> main(List<String> args, [SendPort sendPort]) async {
+  core.overrideGeneratedOutputDirectory('flutter_web');
+  final int result = await build_runner.run(args, builders);
+  sendPort?.send(result);
+}
+
+/// A ddc-only entrypoint builder that respects the Flutter target flag.
+class FlutterWebTestEntrypointBuilder implements Builder {
+  const FlutterWebTestEntrypointBuilder();
+
+  @override
+  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
+        '.dart': <String>[
+          ddcBootstrapExtension,
+          jsEntrypointExtension,
+          jsEntrypointSourceMapExtension,
+          jsEntrypointArchiveExtension,
+          digestsEntrypointExtension,
+        ],
+      };
+
+  @override
+  Future<void> build(BuildStep buildStep) async {
+    log.info('building for target ${buildStep.inputId.path}');
+    await bootstrapDdc(buildStep, platform: flutterWebPlatform);
+  }
+}
+
+/// A ddc-only entrypoint builder that respects the Flutter target flag.
+class FlutterWebEntrypointBuilder implements Builder {
+  const FlutterWebEntrypointBuilder(this.release, this.flutterWebSdk);
+
+  final bool release;
+  final String flutterWebSdk;
+
+  @override
+  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
+        '.dart': <String>[
+          ddcBootstrapExtension,
+          jsEntrypointExtension,
+          jsEntrypointSourceMapExtension,
+          jsEntrypointArchiveExtension,
+          digestsEntrypointExtension,
+        ],
+      };
+
+  @override
+  Future<void> build(BuildStep buildStep) async {
+    if (release) {
+      await bootstrapDart2Js(buildStep, flutterWebSdk);
+    } else {
+      await bootstrapDdc(buildStep, platform: flutterWebPlatform);
+    }
+  }
+}
+
+/// Bootstraps the test entrypoint.
+class FlutterWebTestBootstrapBuilder implements Builder {
+  const FlutterWebTestBootstrapBuilder();
+
+  @override
+  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
+    '_test.dart': <String>[
+      '_test.dart.browser_test.dart',
+    ]
+  };
+
+  @override
+  Future<void> build(BuildStep buildStep) async {
+    final AssetId id = buildStep.inputId;
+    final String contents = await buildStep.readAsString(id);
+    final String assetPath = id.pathSegments.first == 'lib'
+        ? path.url.join('packages', id.package, id.path)
+        : id.path;
+    final Metadata metadata = parseMetadata(
+        assetPath, contents, Runtime.builtIn.map((Runtime runtime) => runtime.name).toSet());
+
+    if (metadata.testOn.evaluate(SuitePlatform(Runtime.chrome))) {
+    await buildStep.writeAsString(id.addExtension('.browser_test.dart'), '''
+import 'dart:ui' as ui;
+import 'dart:html';
+import 'dart:js';
+
+import 'package:stream_channel/stream_channel.dart';
+import 'package:test_api/src/backend/stack_trace_formatter.dart'; // ignore: implementation_imports
+import 'package:test_api/src/util/stack_trace_mapper.dart'; // ignore: implementation_imports
+import 'package:test_api/src/remote_listener.dart'; // ignore: implementation_imports
+import 'package:test_api/src/suite_channel_manager.dart'; // ignore: implementation_imports
+
+import "${path.url.basename(id.path)}" as test;
+
+Future<void> main() async {
+  // Extra initialization for flutter_web.
+  // The following parameters are hard-coded in Flutter's test embedder. Since
+  // we don't have an embedder yet this is the lowest-most layer we can put
+  // this stuff in.
+  await ui.webOnlyInitializeEngine();
+  // TODO(flutterweb): remove need for dynamic cast.
+  (ui.window as dynamic).debugOverrideDevicePixelRatio(3.0);
+  (ui.window as dynamic).webOnlyDebugPhysicalSizeOverride = const ui.Size(2400, 1800);
+  internalBootstrapBrowserTest(() => test.main);
+}
+
+void internalBootstrapBrowserTest(Function getMain()) {
+  var channel =
+      serializeSuite(getMain, hidePrints: false, beforeLoad: () async {
+    var serialized =
+        await suiteChannel("test.browser.mapper").stream.first as Map;
+    if (serialized == null) return;
+  });
+  postMessageChannel().pipe(channel);
+}
+StreamChannel serializeSuite(Function getMain(),
+        {bool hidePrints = true, Future beforeLoad()}) =>
+    RemoteListener.start(getMain,
+        hidePrints: hidePrints, beforeLoad: beforeLoad);
+
+StreamChannel suiteChannel(String name) {
+  var manager = SuiteChannelManager.current;
+  if (manager == null) {
+    throw StateError('suiteChannel() may only be called within a test worker.');
+  }
+
+  return manager.connectOut(name);
+}
+
+StreamChannel postMessageChannel() {
+  var controller = StreamChannelController(sync: true);
+  window.onMessage.firstWhere((message) {
+    return message.origin == window.location.origin && message.data == "port";
+  }).then((message) {
+    var port = message.ports.first;
+    var portSubscription = port.onMessage.listen((message) {
+      controller.local.sink.add(message.data);
+    });
+
+    controller.local.stream.listen((data) {
+      port.postMessage({"data": data});
+    }, onDone: () {
+      port.postMessage({"event": "done"});
+      portSubscription.cancel();
+    });
+  });
+
+  context['parent'].callMethod('postMessage', [
+    JsObject.jsify({"href": window.location.href, "ready": true}),
+    window.location.origin,
+  ]);
+  return controller.foreign;
+}
+
+void setStackTraceMapper(StackTraceMapper mapper) {
+  var formatter = StackTraceFormatter.current;
+  if (formatter == null) {
+    throw StateError(
+        'setStackTraceMapper() may only be called within a test worker.');
+  }
+
+  formatter.configure(mapper: mapper);
+}
+''');
+    }
+  }
+}
+
+/// A shell builder which generates the web specific entrypoint.
+class FlutterWebShellBuilder implements Builder {
+  const FlutterWebShellBuilder();
+
+  @override
+  Future<void> build(BuildStep buildStep) async {
+    final AssetId dartEntrypointId = buildStep.inputId;
+    final bool isAppEntrypoint = await _isAppEntryPoint(dartEntrypointId, buildStep);
+    if (!isAppEntrypoint) {
+      return;
+    }
+    final AssetId outputId = buildStep.inputId.changeExtension('_web_entrypoint.dart');
+    await buildStep.writeAsString(outputId, '''
+import 'dart:ui' as ui;
+import "${path.url.basename(buildStep.inputId.path)}" as entrypoint;
+
+Future<void> main() async {
+  await ui.webOnlyInitializePlatform();
+  entrypoint.main();
+}
+
+''');
+  }
+
+  @override
+  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
+    '.dart': <String>['_web_entrypoint.dart'],
+  };
+}
+
+Future<void> bootstrapDart2Js(BuildStep buildStep, String flutterWebSdk) async {
+  final AssetId dartEntrypointId = buildStep.inputId;
+  final AssetId moduleId = dartEntrypointId.changeExtension(moduleExtension(flutterWebPlatform));
+  final Module module = Module.fromJson(json.decode(await buildStep.readAsString(moduleId)));
+
+  final List<Module> allDeps = await module.computeTransitiveDependencies(buildStep, throwIfUnsupported: false)..add(module);
+  final ScratchSpace scratchSpace = await buildStep.fetchResource(scratchSpaceResource);
+  final Iterable<AssetId> allSrcs = allDeps.expand((Module module) => module.sources);
+  await scratchSpace.ensureAssets(allSrcs, buildStep);
+
+  final String packageFile = await _createPackageFile(allSrcs, buildStep, scratchSpace);
+  final String dartPath = dartEntrypointId.path.startsWith('lib/')
+      ? 'package:${dartEntrypointId.package}/'
+          '${dartEntrypointId.path.substring('lib/'.length)}'
+      : dartEntrypointId.path;
+  final String jsOutputPath =
+      '${path.withoutExtension(dartPath.replaceFirst('package:', 'packages/'))}'
+      '$jsEntrypointExtension';
+  final String flutterWebSdkPath = flutterWebSdk;
+  final String librariesPath = path.join(flutterWebSdkPath, 'libraries.json');
+  final List<String> args = <String>[
+    '--libraries-spec="$librariesPath"',
+    '-O4',
+    '-o',
+    '$jsOutputPath',
+    '--packages="$packageFile"',
+    '-Ddart.vm.product=true',
+    dartPath,
+  ];
+  final Dart2JsBatchWorkerPool dart2js = await buildStep.fetchResource(dart2JsWorkerResource);
+  final Dart2JsResult result = await dart2js.compile(args);
+  final AssetId jsOutputId = dartEntrypointId.changeExtension(jsEntrypointExtension);
+  final File jsOutputFile = scratchSpace.fileFor(jsOutputId);
+  if (result.succeeded && jsOutputFile.existsSync()) {
+    log.info(result.output);
+    // Explicitly write out the original js file and sourcemap.
+    await scratchSpace.copyOutput(jsOutputId, buildStep);
+    final AssetId jsSourceMapId =
+        dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension);
+    await _copyIfExists(jsSourceMapId, scratchSpace, buildStep);
+  } else {
+    log.severe(result.output);
+  }
+}
+
+Future<void> _copyIfExists(
+    AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
+  final File file = scratchSpace.fileFor(id);
+  if (file.existsSync()) {
+    await scratchSpace.copyOutput(id, writer);
+  }
+}
+
+/// Creates a `.packages` file unique to this entrypoint at the root of the
+/// scratch space and returns it's filename.
+///
+/// Since mulitple invocations of Dart2Js will share a scratch space and we only
+/// know the set of packages involved the current entrypoint we can't construct
+/// a `.packages` file that will work for all invocations of Dart2Js so a unique
+/// file is created for every entrypoint that is run.
+///
+/// The filename is based off the MD5 hash of the asset path so that files are
+/// unique regarless of situations like `web/foo/bar.dart` vs
+/// `web/foo-bar.dart`.
+Future<String> _createPackageFile(Iterable<AssetId> inputSources, BuildStep buildStep, ScratchSpace scratchSpace) async {
+  final Uri inputUri = buildStep.inputId.uri;
+  final String packageFileName =
+      '.package-${md5.convert(inputUri.toString().codeUnits)}';
+  final File packagesFile =
+      scratchSpace.fileFor(AssetId(buildStep.inputId.package, packageFileName));
+  final Set<String> packageNames = inputSources.map((AssetId s) => s.package).toSet();
+  final String packagesFileContent =
+      packageNames.map((String name) => '$name:packages/$name/').join('\n');
+  await packagesFile
+      .writeAsString('# Generated for $inputUri\n$packagesFileContent');
+  return packageFileName;
+}
+
+/// Returns whether or not [dartId] is an app entrypoint (basically, whether
+/// or not it has a `main` function).
+Future<bool> _isAppEntryPoint(AssetId dartId, AssetReader reader) async {
+  assert(dartId.extension == '.dart');
+  // Skip reporting errors here, dartdevc will report them later with nicer
+  // formatting.
+  final CompilationUnit parsed = parseCompilationUnit(await reader.readAsString(dartId),
+      suppressErrors: true);
+  // Allow two or fewer arguments so that entrypoints intended for use with
+  // [spawnUri] get counted.
+  return parsed.declarations.any((CompilationUnitMember node) {
+    return node is FunctionDeclaration &&
+        node.name.name == 'main' &&
+        node.functionExpression.parameters.parameters.length <= 2;
+  });
+}
diff --git a/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart b/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
index faeefb2..233497a 100644
--- a/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
+++ b/packages/flutter_tools/lib/src/build_runner/web_compilation_delegate.dart
@@ -4,31 +4,16 @@
 
 // ignore_for_file: implementation_imports
 import 'dart:async';
-import 'dart:io' as io; // ignore: dart_io_import
 
 import 'package:build/build.dart';
-import 'package:build_config/build_config.dart';
-import 'package:build_modules/build_modules.dart';
-import 'package:build_modules/builders.dart';
-import 'package:build_modules/src/module_builder.dart';
-import 'package:build_modules/src/platform.dart';
-import 'package:build_modules/src/workers.dart';
 import 'package:build_runner_core/build_runner_core.dart' as core;
 import 'package:build_runner_core/src/asset_graph/graph.dart';
 import 'package:build_runner_core/src/asset_graph/node.dart';
 import 'package:build_runner_core/src/generate/build_impl.dart';
 import 'package:build_runner_core/src/generate/options.dart';
-import 'package:build_test/builder.dart';
-import 'package:build_test/src/debug_test_builder.dart';
-import 'package:build_web_compilers/build_web_compilers.dart';
-import 'package:build_web_compilers/builders.dart';
-import 'package:build_web_compilers/src/dev_compiler_bootstrap.dart';
-import 'package:crypto/crypto.dart';
 import 'package:logging/logging.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
-import 'package:scratch_space/scratch_space.dart';
-import 'package:test_core/backend.dart';
 import 'package:watcher/watcher.dart';
 
 import '../artifacts.dart';
@@ -36,152 +21,10 @@
 import '../base/logger.dart';
 import '../base/platform.dart';
 import '../compile.dart';
-import '../convert.dart';
 import '../dart/package_map.dart';
 import '../globals.dart';
 import '../web/compile.dart';
-
-const String ddcBootstrapExtension = '.dart.bootstrap.js';
-const String jsEntrypointExtension = '.dart.js';
-const String jsEntrypointSourceMapExtension = '.dart.js.map';
-const String jsEntrypointArchiveExtension = '.dart.js.tar.gz';
-const String digestsEntrypointExtension = '.digests';
-const String jsModuleErrorsExtension = '.ddc.js.errors';
-const String jsModuleExtension = '.ddc.js';
-const String jsSourceMapExtension = '.ddc.js.map';
-
-final DartPlatform flutterWebPlatform =
-    DartPlatform.register('flutter_web', <String>[
-  'async',
-  'collection',
-  'convert',
-  'core',
-  'developer',
-  'html',
-  'html_common',
-  'indexed_db',
-  'js',
-  'js_util',
-  'math',
-  'svg',
-  'typed_data',
-  'web_audio',
-  'web_gl',
-  'web_sql',
-  '_internal',
-  // Flutter web specific libraries.
-  'ui',
-  '_engine',
-  'io',
-  'isolate',
-]);
-
-/// The build application to compile a flutter application to the web.
-final List<core.BuilderApplication> builders = <core.BuilderApplication>[
-  core.apply(
-    'flutter_tools|test_bootstrap',
-    <BuilderFactory>[
-      (BuilderOptions options) => const DebugTestBuilder(),
-      (BuilderOptions options) => const FlutterWebTestBootstrapBuilder(),
-    ],
-    core.toRoot(),
-    hideOutput: true,
-    defaultGenerateFor: const InputSet(
-      include: <String>[
-        'test/**',
-      ],
-    ),
-  ),
-  core.apply(
-    'flutter_tools|shell',
-    <BuilderFactory>[
-      (BuilderOptions options) => FlutterWebShellBuilder(
-        options.config['targets'] ?? <String>['lib/main.dart']
-      ),
-    ],
-    core.toRoot(),
-    hideOutput: true,
-    defaultGenerateFor: const InputSet(
-      include: <String>[
-        'lib/**',
-        'web/**',
-      ],
-    ),
-  ),
-  core.apply(
-      'flutter_tools|module_library',
-      <Builder Function(BuilderOptions)>[moduleLibraryBuilder],
-      core.toAllPackages(),
-      isOptional: true,
-      hideOutput: true,
-      appliesBuilders: <String>['flutter_tools|module_cleanup']),
-  core.apply(
-      'flutter_tools|ddc_modules',
-      <Builder Function(BuilderOptions)>[
-        (BuilderOptions options) => MetaModuleBuilder(flutterWebPlatform),
-        (BuilderOptions options) => MetaModuleCleanBuilder(flutterWebPlatform),
-        (BuilderOptions options) => ModuleBuilder(flutterWebPlatform),
-      ],
-      core.toNoneByDefault(),
-      isOptional: true,
-      hideOutput: true,
-      appliesBuilders: <String>['flutter_tools|module_cleanup']),
-  core.apply(
-      'flutter_tools|ddc',
-      <Builder Function(BuilderOptions)>[
-        (BuilderOptions builderOptions) => KernelBuilder(
-              platformSdk: artifacts.getArtifactPath(Artifact.flutterWebSdk),
-              summaryOnly: true,
-              sdkKernelPath: path.join('kernel', 'flutter_ddc_sdk.dill'),
-              outputExtension: ddcKernelExtension,
-              platform: flutterWebPlatform,
-              librariesPath: 'libraries.json',
-            ),
-        (BuilderOptions builderOptions) => DevCompilerBuilder(
-              useIncrementalCompiler: false,
-              platform: flutterWebPlatform,
-              platformSdk: artifacts.getArtifactPath(Artifact.flutterWebSdk),
-              sdkKernelPath: path.join('kernel', 'flutter_ddc_sdk.dill'),
-            ),
-      ],
-      core.toAllPackages(),
-      isOptional: true,
-      hideOutput: true,
-      appliesBuilders: <String>['flutter_tools|ddc_modules']),
-  core.apply(
-    'flutter_tools|entrypoint',
-    <BuilderFactory>[
-      (BuilderOptions options) => FlutterWebEntrypointBuilder(
-          options.config['targets'] ?? <String>['lib/main.dart'],
-          options.config['release'],
-      ),
-    ],
-    core.toRoot(),
-    hideOutput: true,
-    defaultGenerateFor: const InputSet(
-      include: <String>[
-        'lib/**',
-      ],
-    ),
-  ),
-  core.apply(
-    'flutter_tools|test_entrypoint',
-    <BuilderFactory>[
-      (BuilderOptions options) => FlutterWebTestEntrypointBuilder(
-        options.config['targets'] ?? const <String>[]
-      ),
-    ],
-    core.toRoot(),
-    hideOutput: true,
-    defaultGenerateFor: const InputSet(
-      include: <String>[
-        'test/**_test.dart.browser_test.dart',
-      ],
-    ),
-  ),
-  core.applyPostProcess('flutter_tools|module_cleanup', moduleCleanup,
-      defaultGenerateFor: const InputSet())
-];
+import 'build_script.dart';
 
 /// A build_runner specific implementation of the [WebCompilationProxy].
 class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
@@ -193,8 +36,7 @@
 
   @override
   Future<bool> initialize({
-    @required Directory projectDirectory,
-    @required List<String> targets,
+    Directory projectDirectory,
     String testOutputDir,
     bool release = false,
   }) async {
@@ -238,14 +80,11 @@
           ),
       ),
     };
-    final Status status =
-        logger.startProgress('Compiling ${targets.first} for the Web...', timeout: null);
     core.BuildResult result;
     try {
       result = await _runBuilder(
         buildEnvironment,
         buildOptions,
-        targets,
         release,
         buildDirs,
       );
@@ -255,7 +94,6 @@
       result = await _runBuilder(
         buildEnvironment,
         buildOptions,
-        targets,
         release,
         buildDirs,
       );
@@ -265,13 +103,10 @@
       result = await _runBuilder(
         buildEnvironment,
         buildOptions,
-        targets,
         release,
         buildDirs,
       );
       return result.status == core.BuildStatus.success;
-    } finally {
-      status.stop();
     }
   }
 
@@ -293,24 +128,22 @@
     return result.status == core.BuildStatus.success;
   }
 
-
-  Future<core.BuildResult> _runBuilder(core.BuildEnvironment buildEnvironment, BuildOptions buildOptions, List<String> targets, bool release, Set<core.BuildDirectory> buildDirs) async {
+  Future<core.BuildResult> _runBuilder(core.BuildEnvironment buildEnvironment, BuildOptions buildOptions, bool release, Set<core.BuildDirectory> buildDirs) async {
     _builder = await BuildImpl.create(
       buildOptions,
       buildEnvironment,
       builders,
       <String, Map<String, dynamic>>{
-        'flutter_tools|entrypoint': <String, dynamic>{
-          'targets': targets,
+        'flutter_tools:ddc': <String, dynamic>{
+          'flutterWebSdk': artifacts.getArtifactPath(Artifact.flutterWebSdk),
+        },
+        'flutter_tools:entrypoint': <String, dynamic>{
+          'release': release,
+          'flutterWebSdk': artifacts.getArtifactPath(Artifact.flutterWebSdk),
+        },
+        'flutter_tools:test_entrypoint': <String, dynamic>{
           'release': release,
         },
-        'flutter_tools|test_entrypoint': <String, dynamic>{
-          'targets': targets,
-          'release': release,
-        },
-        'flutter_tools|shell': <String, dynamic>{
-          'targets': targets,
-        }
       },
       isReleaseBuild: false,
     );
@@ -364,301 +197,3 @@
     }
   }
 }
-
-/// A ddc-only entrypoint builder that respects the Flutter target flag.
-class FlutterWebTestEntrypointBuilder implements Builder {
-  const FlutterWebTestEntrypointBuilder(this.targets);
-
-  final List<String> targets;
-
-  @override
-  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
-        '.dart': <String>[
-          ddcBootstrapExtension,
-          jsEntrypointExtension,
-          jsEntrypointSourceMapExtension,
-          jsEntrypointArchiveExtension,
-          digestsEntrypointExtension,
-        ],
-      };
-
-  @override
-  Future<void> build(BuildStep buildStep) async {
-    bool matches = false;
-    for (String target in targets) {
-      if (buildStep.inputId.path.contains(target)) {
-        matches = true;
-        break;
-      }
-    }
-    if (!matches) {
-      return;
-    }
-    log.info('building for target ${buildStep.inputId.path}');
-    await bootstrapDdc(buildStep, platform: flutterWebPlatform);
-  }
-}
-
-/// A ddc-only entrypoint builder that respects the Flutter target flag.
-class FlutterWebEntrypointBuilder implements Builder {
-  const FlutterWebEntrypointBuilder(this.targets, this.release);
-
-  final List<String> targets;
-  final bool release;
-
-  @override
-  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
-        '.dart': <String>[
-          ddcBootstrapExtension,
-          jsEntrypointExtension,
-          jsEntrypointSourceMapExtension,
-          jsEntrypointArchiveExtension,
-          digestsEntrypointExtension,
-        ],
-      };
-
-  @override
-  Future<void> build(BuildStep buildStep) async {
-    bool matches = false;
-    for (String target in targets) {
-      if (buildStep.inputId.path.contains(fs.path.setExtension(target, '_web_entrypoint.dart'))) {
-        matches = true;
-        break;
-      }
-    }
-    if (!matches) {
-      return;
-    }
-    log.info('building for target ${buildStep.inputId.path}');
-    if (release) {
-      await bootstrapDart2Js(buildStep);
-    } else {
-      await bootstrapDdc(buildStep, platform: flutterWebPlatform);
-    }
-  }
-}
-
-/// Bootstraps the test entrypoint.
-class FlutterWebTestBootstrapBuilder implements Builder {
-  const FlutterWebTestBootstrapBuilder();
-
-  @override
-  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
-    '_test.dart': <String>[
-      '_test.dart.browser_test.dart',
-    ]
-  };
-
-  @override
-  Future<void> build(BuildStep buildStep) async {
-    final AssetId id = buildStep.inputId;
-    final String contents = await buildStep.readAsString(id);
-    final String assetPath = id.pathSegments.first == 'lib'
-        ? path.url.join('packages', id.package, id.path)
-        : id.path;
-    final Metadata metadata = parseMetadata(
-        assetPath, contents, Runtime.builtIn.map((Runtime runtime) => runtime.name).toSet());
-
-    if (metadata.testOn.evaluate(SuitePlatform(Runtime.chrome))) {
-    await buildStep.writeAsString(id.addExtension('.browser_test.dart'), '''
-import 'dart:ui' as ui;
-import 'dart:html';
-import 'dart:js';
-
-import 'package:stream_channel/stream_channel.dart';
-import 'package:test_api/src/backend/stack_trace_formatter.dart'; // ignore: implementation_imports
-import 'package:test_api/src/util/stack_trace_mapper.dart'; // ignore: implementation_imports
-import 'package:test_api/src/remote_listener.dart'; // ignore: implementation_imports
-import 'package:test_api/src/suite_channel_manager.dart'; // ignore: implementation_imports
-
-import "${path.url.basename(id.path)}" as test;
-
-Future<void> main() async {
-  // Extra initialization for flutter_web.
-  // The following parameters are hard-coded in Flutter's test embedder. Since
-  // we don't have an embedder yet this is the lowest-most layer we can put
-  // this stuff in.
-  await ui.webOnlyInitializeEngine();
-  // TODO(flutterweb): remove need for dynamic cast.
-  (ui.window as dynamic).debugOverrideDevicePixelRatio(3.0);
-  (ui.window as dynamic).webOnlyDebugPhysicalSizeOverride = const ui.Size(2400, 1800);
-  internalBootstrapBrowserTest(() => test.main);
-}
-
-void internalBootstrapBrowserTest(Function getMain()) {
-  var channel =
-      serializeSuite(getMain, hidePrints: false, beforeLoad: () async {
-    var serialized =
-        await suiteChannel("test.browser.mapper").stream.first as Map;
-    if (serialized == null) return;
-  });
-  postMessageChannel().pipe(channel);
-}
-StreamChannel serializeSuite(Function getMain(),
-        {bool hidePrints = true, Future beforeLoad()}) =>
-    RemoteListener.start(getMain,
-        hidePrints: hidePrints, beforeLoad: beforeLoad);
-
-StreamChannel suiteChannel(String name) {
-  var manager = SuiteChannelManager.current;
-  if (manager == null) {
-    throw StateError('suiteChannel() may only be called within a test worker.');
-  }
-
-  return manager.connectOut(name);
-}
-
-StreamChannel postMessageChannel() {
-  var controller = StreamChannelController(sync: true);
-  window.onMessage.firstWhere((message) {
-    return message.origin == window.location.origin && message.data == "port";
-  }).then((message) {
-    var port = message.ports.first;
-    var portSubscription = port.onMessage.listen((message) {
-      controller.local.sink.add(message.data);
-    });
-
-    controller.local.stream.listen((data) {
-      port.postMessage({"data": data});
-    }, onDone: () {
-      port.postMessage({"event": "done"});
-      portSubscription.cancel();
-    });
-  });
-
-  context['parent'].callMethod('postMessage', [
-    JsObject.jsify({"href": window.location.href, "ready": true}),
-    window.location.origin,
-  ]);
-  return controller.foreign;
-}
-
-void setStackTraceMapper(StackTraceMapper mapper) {
-  var formatter = StackTraceFormatter.current;
-  if (formatter == null) {
-    throw StateError(
-        'setStackTraceMapper() may only be called within a test worker.');
-  }
-
-  formatter.configure(mapper: mapper);
-}
-''');
-    }
-  }
-}
-
-/// A shell builder which generates the web specific entrypoint.
-class FlutterWebShellBuilder implements Builder {
-  const FlutterWebShellBuilder(this.targets);
-
-  final List<String> targets;
-
-  @override
-  FutureOr<void> build(BuildStep buildStep) async {
-    bool matches = false;
-    for (String target in targets) {
-      if (buildStep.inputId.path.contains(target)) {
-        matches = true;
-        break;
-      }
-    }
-    if (!matches) {
-      return;
-    }
-    final AssetId outputId = buildStep.inputId.changeExtension('_web_entrypoint.dart');
-    await buildStep.writeAsString(outputId, '''
-import 'dart:ui' as ui;
-import "${path.url.basename(buildStep.inputId.path)}" as entrypoint;
-
-Future<void> main() async {
-  await ui.webOnlyInitializePlatform();
-  entrypoint.main();
-}
-
-''');
-  }
-
-  @override
-  Map<String, List<String>> get buildExtensions => const <String, List<String>>{
-    '.dart': <String>['_web_entrypoint.dart'],
-  };
-}
-
-Future<void> bootstrapDart2Js(BuildStep buildStep) async {
-  final AssetId dartEntrypointId = buildStep.inputId;
-  final AssetId moduleId = dartEntrypointId.changeExtension(moduleExtension(flutterWebPlatform));
-  final Module module = Module.fromJson(json.decode(await buildStep.readAsString(moduleId)));
-
-  final List<Module> allDeps = await module.computeTransitiveDependencies(buildStep, throwIfUnsupported: false)..add(module);
-  final ScratchSpace scratchSpace = await buildStep.fetchResource(scratchSpaceResource);
-  final Iterable<AssetId> allSrcs = allDeps.expand((Module module) => module.sources);
-  await scratchSpace.ensureAssets(allSrcs, buildStep);
-
-  final String packageFile = await _createPackageFile(allSrcs, buildStep, scratchSpace);
-  final String dartPath = dartEntrypointId.path.startsWith('lib/')
-      ? 'package:${dartEntrypointId.package}/'
-          '${dartEntrypointId.path.substring('lib/'.length)}'
-      : dartEntrypointId.path;
-  final String jsOutputPath =
-      '${fs.path.withoutExtension(dartPath.replaceFirst('package:', 'packages/'))}'
-      '$jsEntrypointExtension';
-  final String flutterWebSdkPath = artifacts.getArtifactPath(Artifact.flutterWebSdk);
-  final String librariesPath = fs.path.join(flutterWebSdkPath, 'libraries.json');
-  final List<String> args = <String>[
-    '--libraries-spec="$librariesPath"',
-    '-m',
-    '-o4',
-    '-o',
-    '$jsOutputPath',
-    '--packages="$packageFile"',
-    '-Ddart.vm.product=true',
-    dartPath,
-  ];
-  final Dart2JsBatchWorkerPool dart2js = await buildStep.fetchResource(dart2JsWorkerResource);
-  final Dart2JsResult result = await dart2js.compile(args);
-  final AssetId jsOutputId = dartEntrypointId.changeExtension(jsEntrypointExtension);
-  final io.File jsOutputFile = scratchSpace.fileFor(jsOutputId);
-  if (result.succeeded && jsOutputFile.existsSync()) {
-    log.info(result.output);
-    // Explicitly write out the original js file and sourcemap.
-    await scratchSpace.copyOutput(jsOutputId, buildStep);
-    final AssetId jsSourceMapId =
-        dartEntrypointId.changeExtension(jsEntrypointSourceMapExtension);
-    await _copyIfExists(jsSourceMapId, scratchSpace, buildStep);
-  } else {
-    log.severe(result.output);
-  }
-}
-
-Future<void> _copyIfExists(
-    AssetId id, ScratchSpace scratchSpace, AssetWriter writer) async {
-  final io.File file = scratchSpace.fileFor(id);
-  if (file.existsSync()) {
-    await scratchSpace.copyOutput(id, writer);
-  }
-}
-
-/// Creates a `.packages` file unique to this entrypoint at the root of the
-/// scratch space and returns it's filename.
-///
-/// Since mulitple invocations of Dart2Js will share a scratch space and we only
-/// know the set of packages involved the current entrypoint we can't construct
-/// a `.packages` file that will work for all invocations of Dart2Js so a unique
-/// file is created for every entrypoint that is run.
-///
-/// The filename is based off the MD5 hash of the asset path so that files are
-/// unique regarless of situations like `web/foo/bar.dart` vs
-/// `web/foo-bar.dart`.
-Future<String> _createPackageFile(Iterable<AssetId> inputSources, BuildStep buildStep, ScratchSpace scratchSpace) async {
-  final Uri inputUri = buildStep.inputId.uri;
-  final String packageFileName =
-      '.package-${md5.convert(inputUri.toString().codeUnits)}';
-  final io.File packagesFile =
-      scratchSpace.fileFor(AssetId(buildStep.inputId.package, packageFileName));
-  final Set<String> packageNames = inputSources.map((AssetId s) => s.package).toSet();
-  final String packagesFileContent =
-      packageNames.map((String name) => '$name:packages/$name/').join('\n');
-  await packagesFile
-      .writeAsString('# Generated for $inputUri\n$packagesFileContent');
-  return packageFileName;
-}
diff --git a/packages/flutter_tools/lib/src/resident_web_runner.dart b/packages/flutter_tools/lib/src/resident_web_runner.dart
index f774153..396409e 100644
--- a/packages/flutter_tools/lib/src/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_web_runner.dart
@@ -131,8 +131,7 @@
     }
     // Start the web compiler and build the assets.
     await webCompilationProxy.initialize(
-      projectDirectory: FlutterProject.current().directory,
-      targets: <String>[target],
+      projectDirectory: flutterProject.directory,
     );
     _lastCompiled = DateTime.now();
     final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart
index f9df159..925bc27 100644
--- a/packages/flutter_tools/lib/src/test/runner.dart
+++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -76,9 +76,6 @@
     final bool result = await webCompilationProxy.initialize(
       projectDirectory: flutterProject.directory,
       testOutputDir: tempBuildDir,
-      targets: testFiles.map((String testFile) {
-        return fs.path.relative(testFile, from: flutterProject.directory.path);
-      }).toList(),
     );
     if (!result) {
       throwToolExit('Failed to compile tests');
diff --git a/packages/flutter_tools/lib/src/web/compile.dart b/packages/flutter_tools/lib/src/web/compile.dart
index 42d6ff2..5f4b515 100644
--- a/packages/flutter_tools/lib/src/web/compile.dart
+++ b/packages/flutter_tools/lib/src/web/compile.dart
@@ -30,7 +30,6 @@
   try {
     result = await webCompilationProxy.initialize(
       projectDirectory: FlutterProject.current().directory,
-      targets: <String>[target],
       release: buildInfo.isRelease,
     );
     if (result) {
@@ -79,11 +78,8 @@
   ///
   /// `release` controls whether we build the bundle for dartdevc or only
   /// the entrypoints for dart2js to later take over.
-  ///
-  /// `targets` controls the specific compiler targets.
   Future<bool> initialize({
     @required Directory projectDirectory,
-    @required List<String> targets,
     String testOutputDir,
     bool release,
   }) async {
diff --git a/packages/flutter_tools/test/commands/build_web_test.dart b/packages/flutter_tools/test/commands/build_web_test.dart
index f76c405..5f5df71 100644
--- a/packages/flutter_tools/test/commands/build_web_test.dart
+++ b/packages/flutter_tools/test/commands/build_web_test.dart
@@ -38,7 +38,6 @@
       fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
       when(mockWebCompilationProxy.initialize(
         projectDirectory: anyNamed('projectDirectory'),
-        targets: anyNamed('targets'),
         release: anyNamed('release')
       )).thenAnswer((Invocation invocation) {
         final String path = fs.path.join('.dart_tool', 'build', 'flutter_web', 'foo', 'lib', 'main_web_entrypoint.dart.js');