Version 2.15.0-227.0.dev

Merge commit '1aaed6385f0f3c6e63accff7e28d521b3b4cae50' into 'dev'
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 276e872..41cb540 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -418,7 +418,6 @@
         .then((value) => value is ResolvedUnitResult ? value : null)
         .catchError((e, st) {
       instrumentationService.logException(e, st);
-      // ignore: invalid_return_type_for_catch_error
       return null;
     });
   }
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index cf8cad0..a1b1989 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -57,9 +57,8 @@
   bool get inConstantContext;
 
   /// Return the library element which contains the unit in which the completion
-  /// is occurring. This may return `null` if the library cannot be determined
-  /// (e.g. unlinked part file).
-  LibraryElement? get libraryElement;
+  /// is occurring.
+  LibraryElement get libraryElement;
 
   /// The source for the library containing the completion request.
   /// This may be different from the source in which the completion is requested
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index d635651..476125a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -20,12 +20,6 @@
   Future<void> computeSuggestions(
       DartCompletionRequest request, SuggestionBuilder builder) async {
     var containingLibrary = request.libraryElement;
-    // Gracefully degrade if the library could not be determined, such as with a
-    // detached part file or source change.
-    if (containingLibrary == null) {
-      return;
-    }
-
     memberBuilder = MemberSuggestionBuilder(request, builder);
 
     var defaultKind = request.target.isFunctionalArgument()
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index 4f7d07c..e2a6c60 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -17,12 +17,8 @@
       return;
     }
 
-    var imports = request.libraryElement?.imports;
-    if (imports == null) {
-      return;
-    }
-
     // Traverse imports including dart:core
+    var imports = request.libraryElement.imports;
     for (var importElement in imports) {
       var libraryElement = importElement.importedLibrary;
       if (libraryElement != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index 975d96c..75ae6b50 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -22,13 +22,8 @@
     if (targetId is SimpleIdentifier && !request.target.isCascade) {
       var elem = targetId.staticElement;
       if (elem is PrefixElement && !elem.isSynthetic) {
-        var containingLibrary = request.libraryElement;
-        // Gracefully degrade if the library or directives could not be
-        // determined (e.g. detached part file or source change).
-        if (containingLibrary != null) {
-          var imports = containingLibrary.imports;
-          _buildSuggestions(request, builder, elem, imports);
-        }
+        var imports = request.libraryElement.imports;
+        _buildSuggestions(request, builder, elem, imports);
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index d8a09fb..0e0a8a4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -15,11 +15,7 @@
       return;
     }
 
-    var imports = request.libraryElement?.imports;
-    if (imports == null) {
-      return;
-    }
-
+    var imports = request.libraryElement.imports;
     for (var element in imports) {
       var prefix = element.prefix?.name;
       if (prefix != null && prefix.isNotEmpty) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index e00de9c..0632487 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -18,9 +18,6 @@
     var node = request.target.containingNode;
     if (node is ConstructorName) {
       var libraryElement = request.libraryElement;
-      if (libraryElement == null) {
-        return;
-      }
       var namedType = node.type2;
       var type = namedType.type;
       if (type != null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
index 8934ed9..3db1549 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
@@ -59,7 +59,7 @@
             parent.thisOrAncestorOfType<ClassOrMixinDeclaration>();
         var classElement = containingClass?.declaredElement;
         var libraryElement = request.libraryElement;
-        if (classElement == null || libraryElement == null) {
+        if (classElement == null) {
           return;
         }
         var typeSystem = libraryElement.typeSystem;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 08bf0df..15b6c33 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -16,13 +16,6 @@
   Future<void> computeSuggestions(
       DartCompletionRequest request, SuggestionBuilder builder) async {
     var library = request.libraryElement;
-    if (library == null) {
-      // Gracefully degrade if the library could not be determined, such as a
-      // detached part file or source change.
-      // TODO(brianwilkerson) Consider testing for this before invoking _any_ of
-      //  the contributors.
-      return;
-    }
     bool isVisible(Element element) => element.isAccessibleIn(library);
     var targetId = request.dotTarget;
     if (targetId is Identifier && !request.target.isCascade) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 979ab11..5d85616 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -214,7 +214,7 @@
   }
 
   bool get _isNonNullableByDefault =>
-      request.libraryElement?.isNonNullableByDefault ?? false;
+      request.libraryElement.isNonNullableByDefault;
 
   /// Add a suggestion for an [accessor] declared within a class or extension.
   /// If the accessor is being invoked with a target of `super`, then the
@@ -1135,7 +1135,7 @@
     var typeParameters = element.typeParameters;
     var typeArguments = const <DartType>[];
     if (typeParameters.isNotEmpty) {
-      var neverType = request.libraryElement!.typeProvider.neverType;
+      var neverType = request.libraryElement.typeProvider.neverType;
       typeArguments = List.filled(typeParameters.length, neverType);
     }
 
@@ -1153,7 +1153,7 @@
     var typeParameters = element.typeParameters;
     var typeArguments = const <DartType>[];
     if (typeParameters.isNotEmpty) {
-      var neverType = request.libraryElement!.typeProvider.neverType;
+      var neverType = request.libraryElement.typeProvider.neverType;
       typeArguments = List.filled(typeParameters.length, neverType);
     }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
index 179e35a..d0452f2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
@@ -122,7 +122,6 @@
   /// Add a fix whose edits were built by the [builder] that has the given
   /// [kind]. If [args] are provided, they will be used to fill in the message
   /// for the fix.
-  // ignore: unused_element
   void _addFixFromBuilder(ChangeBuilder builder, FixKind kind, {List? args}) {
     var change = builder.sourceChange;
     if (change.edits.isEmpty) {
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 257fb5b..8ebde10 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -65,7 +65,7 @@
 
     var directives = request.target.unit.directives;
 
-    var imports = request.libraryElement!.imports;
+    var imports = request.libraryElement.imports;
     expect(imports, hasLength(directives.length + 1));
 
     ImportElement importNamed(String expectedUri) {
diff --git a/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart b/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
index 206d8fe..d4bf8fd 100644
--- a/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
+++ b/pkg/analysis_server/test/src/utilities/extensions/range_factory_test.dart
@@ -22,10 +22,7 @@
   /// Assuming that the test code starts with a function whose block body starts
   /// with a method invocation, return the list of arguments in that invocation.
   NodeList<Expression> get _argumentList {
-    var f = testUnit.declarations[0] as FunctionDeclaration;
-    var body = f.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var invocation = statement.expression as MethodInvocation;
+    var invocation = findNode.methodInvocations.single;
     return invocation.argumentList.arguments;
   }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 575fe79..f07b84c 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
 
 class FindNode {
   final String content;
@@ -16,6 +17,16 @@
         as LibraryDirective;
   }
 
+  List<MethodInvocation> get methodInvocations {
+    var result = <MethodInvocation>[];
+    unit.accept(
+      FunctionAstVisitor(
+        methodInvocation: result.add,
+      ),
+    );
+    return result;
+  }
+
   Annotation annotation(String search) {
     return _node(search, (n) => n is Annotation);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
index 126dd97..bb1476c 100644
--- a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
+++ b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
@@ -12,6 +12,7 @@
       functionDeclarationStatement;
   final void Function(FunctionExpression, bool)? functionExpression;
   final void Function(Label)? label;
+  final void Function(MethodInvocation)? methodInvocation;
   final void Function(SimpleIdentifier)? simpleIdentifier;
   final void Function(VariableDeclaration)? variableDeclaration;
 
@@ -20,6 +21,7 @@
     this.functionDeclarationStatement,
     this.functionExpression,
     this.label,
+    this.methodInvocation,
     this.simpleIdentifier,
     this.variableDeclaration,
   });
@@ -59,6 +61,14 @@
   }
 
   @override
+  void visitMethodInvocation(MethodInvocation node) {
+    if (methodInvocation != null) {
+      methodInvocation!(node);
+    }
+    super.visitMethodInvocation(node);
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     if (simpleIdentifier != null) {
       simpleIdentifier!(node);
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index fb0093f..c8d4d0e 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -786,7 +786,6 @@
       // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
       // TODO(scheglov) Remove it when we stop providing it everywhere.
       if (aliasedType is FunctionType) {
-        // ignore: deprecated_member_use_from_same_package
         expect(aliasedType.element, isNull);
       }
 
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 63cad0a..b3e8552 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -97,7 +97,7 @@
     Uri packageConfig]) {
   CompilerOptions compilerOptions = CompilerOptions.parse(options,
       librariesSpecificationUri: librariesSpecificationUri)
-    ..entryPoint = script
+    ..entryUri = script
     ..packageConfig = packageConfig
     ..environment = environment;
 
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index 77e4a0c..4b1d89f 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -190,7 +190,7 @@
 
   CompilerImpl compiler = new CompilerImpl(
       compilerInput, compilerOutput, compilerDiagnostics, compilerOptions);
-  return compiler.run(compilerOptions.entryPoint).then((bool success) {
+  return compiler.run().then((bool success) {
     return new CompilationResult(compiler,
         isSuccess: success,
         kernelInitializedCompilerState:
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index e5dbb72..c8aba18 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -89,11 +89,11 @@
   }
 
   @override
-  Future<bool> run(Uri uri) {
+  Future<bool> run() {
     Duration setupDuration = measurer.elapsedWallClock;
     return selfTask.measureSubtask("impl.run", () {
       return setupSdk().then((_) {
-        return super.run(uri);
+        return super.run();
       }).then((bool success) {
         if (options.verbose) {
           StringBuffer timings = StringBuffer();
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 09293fc..04ae01e 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -8,6 +8,12 @@
 
 /// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
 class Flags {
+  // The uri of the main script file.
+  static const String entryUri = '--entry-uri';
+
+  // The uri of the main input dill.
+  static const String inputDill = '--input-dill';
+
   static const String allowMockCompilation = '--allow-mock-compilation';
   static const String allowNativeExtensions = '--allow-native-extensions';
   static const String disableInlining = '--disable-inlining';
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index bc87f29..5a67b84 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -218,16 +218,16 @@
   bool get disableTypeInference =>
       options.disableTypeInference || compilationFailed;
 
-  // Compiles the dart script at [uri].
+  // Compiles the dart program as specified in [options].
   //
   // The resulting future will complete with true if the compilation
   // succeeded.
-  Future<bool> run(Uri uri) => selfTask.measureSubtask("run", () {
+  Future<bool> run() => selfTask.measureSubtask("run", () {
         measurer.startWallClock();
 
-        return Future.sync(() => runInternal(uri))
+        return Future.sync(() => runInternal())
             .catchError((error, StackTrace stackTrace) =>
-                _reporter.onError(uri, error, stackTrace))
+                _reporter.onError(options.compilationTarget, error, stackTrace))
             .whenComplete(() {
           measurer.stopWallClock();
         }).then((_) {
@@ -245,10 +245,11 @@
     return options.readClosedWorldUri != null && options.readDataUri != null;
   }
 
-  Future runInternal(Uri uri) async {
+  Future runInternal() async {
     clearState();
-    assert(uri != null);
-    reporter.log('Compiling $uri (${options.buildId})');
+    var compilationTarget = options.compilationTarget;
+    assert(compilationTarget != null);
+    reporter.log('Compiling $compilationTarget (${options.buildId})');
 
     if (options.readProgramSplit != null) {
       var constraintParser = psc.Parser();
@@ -302,7 +303,7 @@
               environment, abstractValueStrategy);
       await generateJavaScriptCode(globalTypeInferenceResults);
     } else {
-      KernelResult result = await kernelLoader.load(uri);
+      KernelResult result = await kernelLoader.load();
       reporter.log("Kernel load complete");
       if (result == null) return;
       if (compilationFailed) {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 139ebfe..bd60c69 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -101,6 +101,8 @@
     {fe.InitializedCompilerState kernelInitializedCompilerState}) {
   Stopwatch wallclock = Stopwatch()..start();
   stackTraceFilePrefix = '${Uri.base}';
+  Uri entryUri;
+  Uri inputDillUri;
   Uri librariesSpecificationUri = Uri.base.resolve('lib/libraries.json');
   bool outputSpecified = false;
   Uri out;
@@ -145,13 +147,24 @@
     passThrough("--build-id=$BUILD_ID");
   }
 
+  Uri extractResolvedFileUri(String argument) {
+    return Uri.base.resolve(extractPath(argument, isDirectory: false));
+  }
+
+  void setEntryUri(String argument) {
+    entryUri = extractResolvedFileUri(argument);
+  }
+
+  void setInputDillUri(String argument) {
+    inputDillUri = extractResolvedFileUri(argument);
+  }
+
   void setLibrarySpecificationUri(String argument) {
-    librariesSpecificationUri =
-        Uri.base.resolve(extractPath(argument, isDirectory: false));
+    librariesSpecificationUri = extractResolvedFileUri(argument);
   }
 
   void setPackageConfig(String argument) {
-    packageConfig = Uri.base.resolve(extractPath(argument, isDirectory: false));
+    packageConfig = extractResolvedFileUri(argument);
   }
 
   void setOutput(Iterator<String> arguments) {
@@ -501,6 +514,8 @@
 
   List<String> arguments = <String>[];
   List<OptionHandler> handlers = <OptionHandler>[
+    OptionHandler('${Flags.entryUri}=.+', setEntryUri),
+    OptionHandler('${Flags.inputDill}=.+', setInputDillUri),
     OptionHandler('-[chvm?]+', handleShortOptions),
     OptionHandler('--throw-on-error(?:=[0-9]+)?', handleThrowOnError),
     OptionHandler(Flags.suppressWarnings, (String argument) {
@@ -725,9 +740,10 @@
     helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
   }
 
-  if (arguments.isEmpty) {
+  if (arguments.isEmpty && entryUri == null && inputDillUri == null) {
     helpAndFail('No Dart file specified.');
   }
+
   if (arguments.length > 1) {
     var extra = arguments.sublist(1);
     helpAndFail('Extra arguments: ${extra.join(" ")}');
@@ -738,7 +754,20 @@
         "checked mode.");
   }
 
-  String scriptName = arguments[0];
+  if (arguments.isNotEmpty) {
+    String sourceOrDill = arguments[0];
+    Uri file = Uri.base.resolve(fe.nativeToUriPath(sourceOrDill));
+    if (sourceOrDill.endsWith('.dart')) {
+      entryUri = file;
+    } else {
+      assert(sourceOrDill.endsWith('.dill'));
+      inputDillUri = file;
+    }
+  }
+
+  // Make [scriptName] a relative path..
+  String scriptName =
+      fe.relativizeUri(Uri.base, inputDillUri ?? entryUri, Platform.isWindows);
 
   switch (writeStrategy) {
     case WriteStrategy.toJs:
@@ -888,7 +917,7 @@
     writeString(
         Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
 
-    String input = fe.uriPathToNative(scriptName);
+    String input = scriptName;
     int inputSize;
     String processName;
     String inputName;
@@ -1037,8 +1066,6 @@
     return result;
   }
 
-  Uri script = Uri.base.resolve(scriptName);
-
   diagnosticHandler.autoReadFileUri = true;
   CompilerOptions compilerOptions = CompilerOptions.parse(options,
       featureOptions: features,
@@ -1046,7 +1073,8 @@
       platformBinaries: platformBinaries,
       onError: (String message) => fail(message),
       onWarning: (String message) => print(message))
-    ..entryPoint = script
+    ..entryUri = entryUri
+    ..inputDillUri = inputDillUri
     ..packageConfig = packageConfig
     ..environment = environment
     ..kernelInitializedCompilerState = kernelInitializedCompilerState
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 3278416..30e4d8e 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -55,8 +55,34 @@
   @override
   String get name => 'kernel loader';
 
+  ir.Reference findMainMethod(Component component, Uri entryUri) {
+    var entryLibrary = component.libraries
+        .firstWhere((l) => l.fileUri == entryUri, orElse: () => null);
+    if (entryLibrary == null) {
+      throw ArgumentError('Entry uri $entryUri not found in dill.');
+    }
+    var mainMethod = entryLibrary.procedures
+        .firstWhere((p) => p.name.text == 'main', orElse: () => null);
+
+    // In some cases, a main method is defined in another file, and then
+    // exported. In these cases, we search for the main method in
+    // [additionalExports].
+    ir.Reference mainMethodReference;
+    if (mainMethod == null) {
+      mainMethodReference = entryLibrary.additionalExports.firstWhere(
+          (p) => p.canonicalName.name == 'main',
+          orElse: () => null);
+    } else {
+      mainMethodReference = mainMethod.reference;
+    }
+    if (mainMethodReference == null) {
+      throw ArgumentError('Entry uri $entryUri has no main method.');
+    }
+    return mainMethodReference;
+  }
+
   /// Loads an entire Kernel [Component] from a file on disk.
-  Future<KernelResult> load(Uri resolvedUri) {
+  Future<KernelResult> load() {
     return measure(() async {
       String targetName =
           _options.compileForServer ? "dart2js_server" : "dart2js";
@@ -72,6 +98,7 @@
         return platform;
       }
 
+      var resolvedUri = _options.compilationTarget;
       ir.Component component;
       List<Uri> moduleLibraries = const [];
       var isDill = resolvedUri.path.endsWith('.dill') ||
@@ -98,6 +125,14 @@
         }
 
         await read(resolvedUri);
+
+        // If an entryUri is supplied, we use it to manually select the main
+        // method.
+        if (_options.entryUri != null) {
+          var mainMethod = findMainMethod(component, _options.entryUri);
+          component.setMainMethodAndMode(mainMethod, true, component.mode);
+        }
+
         if (_options.modularMode) {
           moduleLibraries =
               component.libraries.map((lib) => lib.importUri).toList();
@@ -129,11 +164,16 @@
           // brittle.
           if (platformUri != resolvedUri) await read(platformUri);
         }
+
+        // Concatenate dills and then reset main method.
+        var mainMethod = component.mainMethodName;
+        var mainMode = component.mode;
         if (_options.dillDependencies != null) {
           for (Uri dependency in _options.dillDependencies) {
             await read(dependency);
           }
         }
+        component.setMainMethodAndMode(mainMethod, true, mainMode);
 
         // This is not expected to be null when creating a whole-program .dill
         // file, but needs to be checked for modular inputs.
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 5f7b288..38609ea 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -139,7 +139,13 @@
 /// as few as possible.
 class CompilerOptions implements DiagnosticOptions {
   /// The entry point of the application that is being compiled.
-  Uri? entryPoint;
+  Uri? entryUri;
+
+  /// The input dill to compile.
+  Uri? inputDillUri;
+
+  /// Returns the compilation target specified by these options.
+  Uri? get compilationTarget => inputDillUri ?? entryUri;
 
   /// Location of the package configuration file.
   ///
@@ -168,7 +174,7 @@
 
   /// Location from which serialized inference data is read.
   ///
-  /// If this is set, the [entryPoint] is expected to be a .dill file and the
+  /// If this is set, the [entryUri] is expected to be a .dill file and the
   /// frontend work is skipped.
   Uri? readDataUri;
 
@@ -184,7 +190,7 @@
 
   /// Location from which the serialized closed world is read.
   ///
-  /// If this is set, the [entryPoint] is expected to be a .dill file and the
+  /// If this is set, the [entryUri] is expected to be a .dill file and the
   /// frontend work is skipped.
   Uri? readClosedWorldUri;
 
@@ -559,6 +565,8 @@
     // sdk with the correct flags.
     platformBinaries ??= fe.computePlatformBinariesLocation();
     return CompilerOptions()
+      ..entryUri = _extractUriOption(options, '${Flags.entryUri}=')
+      ..inputDillUri = _extractUriOption(options, '${Flags.inputDill}=')
       ..librariesSpecificationUri = librariesSpecificationUri
       ..allowMockCompilation = _hasOption(options, Flags.allowMockCompilation)
       ..benchmarkingProduction =
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 071727d..27d75ae 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -156,9 +156,9 @@
 
   Future<ir.Component> deserializeComponent() async {
     return measureIoSubtask('deserialize dill', () async {
-      _reporter.log('Reading dill from ${_options.entryPoint}');
+      _reporter.log('Reading dill from ${_options.inputDillUri}');
       api.Input<List<int>> dillInput = await _provider
-          .readFromUri(_options.entryPoint, inputKind: api.InputKind.binary);
+          .readFromUri(_options.inputDillUri, inputKind: api.InputKind.binary);
       ir.Component component = ir.Component();
       // Not using growable lists saves memory.
       ir.BinaryBuilder(dillInput.data,
@@ -177,8 +177,9 @@
       var dillMode = isStrongDill ? 'sound' : 'unsound';
       var option =
           isStrongDill ? Flags.noSoundNullSafety : Flags.soundNullSafety;
-      throw ArgumentError("${_options.entryPoint} was compiled with $dillMode "
-          "null safety and is incompatible with the '$option' option");
+      throw ArgumentError("${_options.inputDillUri} was compiled with "
+          "$dillMode null safety and is incompatible with the '$option' "
+          "option");
     }
 
     _options.nullSafetyMode =
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index 329a825..559d972 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -59,8 +59,9 @@
         memorySourceFiles: memorySourceFiles,
         librariesSpecificationUri: librariesSpecificationUri,
         packageConfig: packageConfig,
+        entryPoint: entryPoint,
         options: options);
-    KernelResult result = await compiler.kernelLoader.load(entryPoint);
+    KernelResult result = await compiler.kernelLoader.load();
     new DynamicVisitor(compiler.reporter, result.component, allowedListPath,
             analyzedUrisFilter)
         .run(verbose: verbose, generate: generate);
diff --git a/pkg/compiler/test/analyses/static_type_visitor_test.dart b/pkg/compiler/test/analyses/static_type_visitor_test.dart
index 72b7143..4ec5093 100644
--- a/pkg/compiler/test/analyses/static_type_visitor_test.dart
+++ b/pkg/compiler/test/analyses/static_type_visitor_test.dart
@@ -23,10 +23,10 @@
 
 main() {
   asyncTest(() async {
-    Compiler compiler =
-        await compilerFor(memorySourceFiles: {'main.dart': source});
-    KernelResult result =
-        await compiler.kernelLoader.load(Uri.parse('memory:main.dart'));
+    Compiler compiler = await compilerFor(
+        memorySourceFiles: {'main.dart': source},
+        entryPoint: Uri.parse('memory:main.dart'));
+    KernelResult result = await compiler.kernelLoader.load();
     ir.Component component = result.component;
     StaticTypeVisitor visitor = new Visitor(component);
     component.accept(visitor);
diff --git a/pkg/compiler/test/end_to_end/command_line_test.dart b/pkg/compiler/test/end_to_end/command_line_test.dart
index 5f0b7e9..ec0a78a 100644
--- a/pkg/compiler/test/end_to_end/command_line_test.dart
+++ b/pkg/compiler/test/end_to_end/command_line_test.dart
@@ -73,10 +73,10 @@
         out: 'out.js', readClosedWorld: 'foo.dill.world');
     await test([Flags.readClosedWorld, 'foo.dill', '--out=foo.js'],
         out: 'foo.js', readClosedWorld: 'foo.dill.world');
-    await test(['${Flags.readClosedWorld}=out.world', 'foo.world'],
+    await test(['${Flags.readClosedWorld}=out.world', 'foo.dill'],
         out: 'out.js', readClosedWorld: 'out.world');
     await test(
-        ['${Flags.readClosedWorld}=out.world', 'foo.world', '--out=foo.js'],
+        ['${Flags.readClosedWorld}=out.world', 'foo.dill', '--out=foo.js'],
         out: 'foo.js', readClosedWorld: 'out.world');
     await test(
       [Flags.readClosedWorld, Flags.writeData, 'foo.dill'],
diff --git a/pkg/compiler/test/end_to_end/dill_loader_test.dart b/pkg/compiler/test/end_to_end/dill_loader_test.dart
index 81cbfb7..f5529d55 100644
--- a/pkg/compiler/test/end_to_end/dill_loader_test.dart
+++ b/pkg/compiler/test/end_to_end/dill_loader_test.dart
@@ -27,7 +27,6 @@
     Uri uri = Uri.base.resolve(filename);
     DiagnosticCollector diagnostics = new DiagnosticCollector();
     OutputCollector output = new OutputCollector();
-    Uri entryPoint = Uri.parse('memory:main.dill');
 
     var options = new CompilerOptions()
       ..target = new Dart2jsTarget("dart2js", new TargetFlags())
@@ -41,12 +40,12 @@
     List<int> kernelBinary =
         serializeComponent((await kernelForProgram(uri, options)).component);
     CompilerImpl compiler = compilerFor(
-        entryPoint: entryPoint,
+        entryPoint: uri,
         memorySourceFiles: {'main.dill': kernelBinary},
         diagnosticHandler: diagnostics,
         outputProvider: output);
     await compiler.setupSdk();
-    KernelResult result = await compiler.kernelLoader.load(entryPoint);
+    KernelResult result = await compiler.kernelLoader.load();
     compiler.frontendStrategy.registerLoadedLibraries(result);
 
     Expect.equals(0, diagnostics.errors.length);
diff --git a/pkg/compiler/test/end_to_end/exit_code_test.dart b/pkg/compiler/test/end_to_end/exit_code_test.dart
index abe4757..b830f92 100644
--- a/pkg/compiler/test/end_to_end/exit_code_test.dart
+++ b/pkg/compiler/test/end_to_end/exit_code_test.dart
@@ -61,9 +61,9 @@
   }
 
   @override
-  Future<bool> run(Uri uri) {
+  Future<bool> run() {
     test('Compiler.run');
-    return super.run(uri);
+    return super.run();
   }
 
   test(String marker) {
@@ -161,7 +161,7 @@
       // handler = (uri, begin, end, message, kind) {};
       Compiler compiler = new TestCompiler(compilerInput, compilerOutput,
           compilerDiagnostics, compilerOptions, marker, type, onTest);
-      return compiler.run(compilerOptions.entryPoint).then((bool success) {
+      return compiler.run().then((bool success) {
         return new api.CompilationResult(compiler, isSuccess: success);
       });
     }
diff --git a/pkg/compiler/test/end_to_end/modular_loader_test.dart b/pkg/compiler/test/end_to_end/modular_loader_test.dart
index 3dccb70..ae9a5b8 100644
--- a/pkg/compiler/test/end_to_end/modular_loader_test.dart
+++ b/pkg/compiler/test/end_to_end/modular_loader_test.dart
@@ -37,15 +37,18 @@
 
     DiagnosticCollector diagnostics = new DiagnosticCollector();
     OutputCollector output = new OutputCollector();
-    Uri entryPoint = Uri.parse('memory:c.dill');
+    Uri entryPoint = Uri.parse('org-dartlang-test:///c2.dart');
     CompilerImpl compiler = compilerFor(
         entryPoint: entryPoint,
-        options: ['--dill-dependencies=memory:a.dill,memory:b.dill'],
+        options: [
+          '--input-dill=memory:c.dill',
+          '--dill-dependencies=memory:a.dill,memory:b.dill'
+        ],
         memorySourceFiles: {'a.dill': aDill, 'b.dill': bDill, 'c.dill': cDill},
         diagnosticHandler: diagnostics,
         outputProvider: output);
     await compiler.setupSdk();
-    KernelResult result = await compiler.kernelLoader.load(entryPoint);
+    KernelResult result = await compiler.kernelLoader.load();
     compiler.frontendStrategy.registerLoadedLibraries(result);
 
     Expect.equals(0, diagnostics.errors.length);
diff --git a/pkg/compiler/test/helpers/memory_compiler.dart b/pkg/compiler/test/helpers/memory_compiler.dart
index 3a19a1b..3b6ca9a 100644
--- a/pkg/compiler/test/helpers/memory_compiler.dart
+++ b/pkg/compiler/test/helpers/memory_compiler.dart
@@ -108,7 +108,7 @@
   if (beforeRun != null) {
     beforeRun(compiler);
   }
-  bool isSuccess = await compiler.run(entryPoint);
+  bool isSuccess = await compiler.run();
   fe.InitializedCompilerState compilerState = kernelInitializedCompilerState =
       compiler.kernelLoader.initializedCompilerState;
   return new CompilationResult(compiler,
@@ -169,7 +169,7 @@
 
   CompilerOptions compilerOptions = CompilerOptions.parse(options,
       librariesSpecificationUri: librariesSpecificationUri)
-    ..entryPoint = entryPoint
+    ..entryUri = entryPoint
     ..environment = {}
     ..packageConfig = packageConfig;
   compilerOptions.kernelInitializedCompilerState =
diff --git a/pkg/compiler/test/model/enqueuer_test.dart b/pkg/compiler/test/model/enqueuer_test.dart
index 797896c..9102ac5 100644
--- a/pkg/compiler/test/model/enqueuer_test.dart
+++ b/pkg/compiler/test/model/enqueuer_test.dart
@@ -159,7 +159,7 @@
 '''
   }, options: [
     Flags.disableInlining,
-  ]);
+  ], entryPoint: Uri.parse('memory:main.dart'));
 
   void checkInvariant(
       Enqueuer enqueuer, ElementEnvironment elementEnvironment) {
@@ -277,7 +277,7 @@
     }
   };
 
-  await compiler.run(Uri.parse('memory:main.dart'));
+  await compiler.run();
 
   checkLiveMembers(
       compiler.enqueuer.resolutionEnqueuerForTesting,
diff --git a/pkg/compiler/test/serialization/serialization_test_helper.dart b/pkg/compiler/test/serialization/serialization_test_helper.dart
index 2507434..0a7b306 100644
--- a/pkg/compiler/test/serialization/serialization_test_helper.dart
+++ b/pkg/compiler/test/serialization/serialization_test_helper.dart
@@ -152,12 +152,13 @@
   File(closedWorldFileUri.path).writeAsBytesSync(closedWorldBytes);
   OutputCollector collector3b = new OutputCollector();
   CompilationResult result3b = await runCompiler(
-      entryPoint: dillFileUri,
+      entryPoint: entryPoint,
       memorySourceFiles: memorySourceFiles,
       packageConfig: packageConfig,
       librariesSpecificationUri: librariesSpecificationUri,
       options: commonOptions +
           [
+            '${Flags.inputDill}=$dillFileUri',
             '${Flags.readClosedWorld}=$closedWorldFileUri',
             '${Flags.writeData}=global.data'
           ],
diff --git a/pkg/compiler/tool/modular_test_suite.dart b/pkg/compiler/tool/modular_test_suite.dart
index c045cc1..c2054cb 100644
--- a/pkg/compiler/tool/modular_test_suite.dart
+++ b/pkg/compiler/tool/modular_test_suite.dart
@@ -73,6 +73,7 @@
 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}) {
@@ -260,7 +261,7 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dart2jsScript,
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${toUri(module, dillId)}',
+      '${Flags.inputDill}=${toUri(module, dillId)}',
       if (dillDependencies.isNotEmpty)
         '--dill-dependencies=${dillDependencies.join(',')}',
       '--out=${toUri(module, modularUpdatedDillId)}',
@@ -330,7 +331,8 @@
       _dart2jsScript,
       // TODO(sigmund): remove this dependency on libraries.json
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${toUri(module, dillId)}',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
+      '${Flags.inputDill}=${toUri(module, dillId)}',
       for (String flag in flags) '--enable-experiment=$flag',
       '${Flags.dillDependencies}=${dillDependencies.join(',')}',
       if (useModularAnalysis)
@@ -379,7 +381,8 @@
       _dart2jsScript,
       // TODO(sigmund): remove this dependency on libraries.json
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${toUri(module, globalUpdatedDillId)}',
+      '${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)}',
@@ -431,7 +434,8 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dart2jsScript,
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${toUri(module, globalUpdatedDillId)}',
+      '${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)}',
@@ -483,7 +487,8 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dart2jsScript,
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
-      '${toUri(module, globalUpdatedDillId)}',
+      '${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)}',
@@ -530,6 +535,7 @@
       _dart2jsScript,
       // TODO(sigmund): remove this dependency on libraries.json
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
       '${toUri(module, globalUpdatedDillId)}',
       for (String flag in flags) '--enable-experiment=$flag',
       '${Flags.readClosedWorld}=${toUri(module, closedWorldId)}',
@@ -581,6 +587,7 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dart2jsScript,
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
       '${toUri(module, globalUpdatedDillId)}',
       for (String flag in flags) '--enable-experiment=$flag',
       '${Flags.readData}=${toUri(module, globalDataId)}',
@@ -628,6 +635,7 @@
       '--packages=${sdkRoot.toFilePath()}/.packages',
       _dart2jsScript,
       if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
+      '${Flags.entryUri}=$fakeRoot${module.mainSource}',
       '${toUri(module, globalUpdatedDillId)}',
       for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
       '${Flags.readData}=${toUri(module, globalDataId)}',
diff --git a/tools/VERSION b/tools/VERSION
index dc7ef35..caa0e82 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 226
+PRERELEASE 227
 PRERELEASE_PATCH 0
\ No newline at end of file