Version 2.14.0-3.0.dev

Merge commit '17bac2f18068487158b758810894547dcd441dd2' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 1224444..ef7591c 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-04-13T11:00:55.084091",
+  "generated": "2021-04-13T13:32:11.977579",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -339,7 +339,7 @@
       "name": "http_parser",
       "rootUri": "../third_party/pkg/http_parser",
       "packageUri": "lib/",
-      "languageVersion": "2.11"
+      "languageVersion": "2.12"
     },
     {
       "name": "http_retry",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c2e449..3441a82 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -144,6 +144,12 @@
 
 [#44211]: https://github.com/dart-lang/sdk/issues/44211
 
+## 2.12.3 - 2021-04-12
+
+This is a patch release that fixes a vulnerability in `dart:html` related to
+DOM clobbering. Thanks again to **Vincenzo di Cicco** for finding and reporting
+this vulnerability.
+
 ## 2.12.2 - 2021-03-17
 
 This is a patch release that fixes crashes reported by Flutter 2 users (issue
diff --git a/DEPS b/DEPS
index 86b73eb..62dd712 100644
--- a/DEPS
+++ b/DEPS
@@ -110,7 +110,7 @@
   "html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev" : "7aca9e87d4a68374b685334f20359320054b8d7b",
-  "http_parser_rev": "5dd4d16693242049dfb43b5efa429fedbf932e98",
+  "http_parser_rev": "7720bfd42a0c096734c5213478fdce92c62f0293",
   "http_retry_rev": "845771af7bb5ab38ab740ce4a31f3b0c7680302b",
   "http_rev": "69d6064dd92470ed7ccd50a808fc789ee7716fe8",
   "http_throttle_tag" : "1.0.2",
diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
index 467f323..be674c8 100644
--- a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
+++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
@@ -16,4 +16,5 @@
     - test/flow_analysis/reachability/data/**
     - test/flow_analysis/type_promotion/data/**
     - test/flow_analysis/why_not_promoted/data/**
+    - test/inference/inferred_type_arguments/data/**
     - test/inheritance/data/**
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 40fcb0f..3288d8b 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -362,7 +362,6 @@
 
     return driver
         .getResult(path, sendCachedToStream: sendCachedToStream)
-        .then((value) => value.state == ResultState.VALID ? value : null)
         .catchError((e, st) {
       instrumentationService.logException(e, st);
       return null;
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index deca868..fedd848 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -87,6 +87,9 @@
 
   Location _getLocationOffsetLength(int offset, int length) {
     var path = resolvedUnit.path;
+    if (path == null) {
+      throw StateError('DartUnitOutlineComputer called with invalid result');
+    }
     var startLocation = resolvedUnit.lineInfo.getLocation(offset);
     var startLine = startLocation.lineNumber;
     var startColumn = startLocation.columnNumber;
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 8ad83ca..3a2ec51 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -33,7 +33,7 @@
       List<ImportedElements> importedElementsList) async {
     var unit = libraryResult.unit;
     var path = libraryResult.path;
-    if (unit == null) {
+    if (unit == null || path == null) {
       // We should never reach this point because the libraryResult should be
       // valid.
       return SourceChange('');
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index c557341..0cec373 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -61,7 +61,7 @@
 
     // Prepare the resolved units.
     var result = await server.getResolvedUnit(file);
-    if (result == null) {
+    if (result.state != ResultState.VALID) {
       server.sendResponse(Response.fileNotAnalyzed(request, file));
       return;
     }
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index ee2cb5c..7c029d8 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -24,7 +24,7 @@
   var context = tracker.getContext(analysisContext);
   if (context == null) return;
 
-  var librariesObject = context.getLibraries(resolvedUnit.path);
+  var librariesObject = context.getLibraries(resolvedUnit.path!);
 
   var importedUriSet = resolvedUnit.libraryElement.importedLibraries
       .map((importedLibrary) => importedLibrary.source.uri)
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 87310e8..7c20027 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -96,7 +96,7 @@
   }) async {
     request.checkAborted();
     var pathContext = request.resourceProvider.pathContext;
-    if (!file_paths.isDart(pathContext, request.result.path)) {
+    if (!file_paths.isDart(pathContext, request.result.path!)) {
       return const <CompletionSuggestion>[];
     }
 
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 9c530a8..d2ce0e3 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
@@ -700,7 +700,7 @@
       ExecutableElement element, bool invokeSuper) async {
     var displayTextBuffer = StringBuffer();
     var builder = ChangeBuilder(session: request.result.session);
-    await builder.addDartFileEdit(request.result.path, (builder) {
+    await builder.addDartFileEdit(request.result.path!, (builder) {
       builder.addReplacement(range.node(targetId), (builder) {
         builder.writeOverride(
           element,
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 988a42d..8aa88e2 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -264,7 +264,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => completionContext.resolveResult.path;
+  String get file => completionContext.resolveResult.path!;
 
   String get key => completionContext.key;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index e71629b..9bd0039 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -120,7 +120,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => statementContext.resolveResult.path;
+  String get file => statementContext.resolveResult.path!;
 
   LineInfo get lineInfo => statementContext.resolveResult.lineInfo;
 
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index fb8a04f..543d8c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -33,7 +33,7 @@
     this.selectionLength = 0,
     required this.resolvedResult,
     required this.workspace,
-  })  : file = resolvedResult.path,
+  })  : file = resolvedResult.path!,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index 50132d8..65467c5 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -281,7 +281,7 @@
   /// library associated with the analysis [result].
   Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
     var analysisOptions = result.session.analysisContext.analysisOptions;
-    for (var unitResult in result.units) {
+    for (var unitResult in result.units!) {
       var overrideSet = _readOverrideSet(unitResult);
       for (var error in unitResult.errors) {
         var processor = ErrorProcessor.getProcessor(analysisOptions, error);
@@ -348,7 +348,7 @@
       await compute(producer);
       var newHash = computeChangeHash();
       if (newHash != oldHash) {
-        changeMap.add(result.path, code);
+        changeMap.add(result.path!, code);
       }
     }
 
@@ -398,7 +398,7 @@
     if (useConfigFiles) {
       var provider = result.session.resourceProvider;
       var context = provider.pathContext;
-      var dartFileName = result.path;
+      var dartFileName = result.path!;
       var configFileName = '${context.withoutExtension(dartFileName)}.config';
       var configFile = provider.getFile(configFileName);
       try {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index 7241c32..a39cc31 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -248,7 +248,7 @@
     this.overrideSet,
     this.selectionOffset = -1,
     this.selectionLength = 0,
-  })  : file = resolvedResult.path,
+  })  : file = resolvedResult.path!,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
index c841c0f..0f22239 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
@@ -27,7 +27,7 @@
     }
 
     var libraryPath = resolvedResult.libraryElement.source.fullName;
-    var partPath = resolvedResult.path;
+    var partPath = resolvedResult.path!;
     var relativePath = relative(libraryPath, from: dirname(partPath));
     var uri = Uri.file(relativePath).toString();
     var replacementRange = range.node(libraryName);
diff --git a/pkg/analysis_server/lib/src/services/flutter/property.dart b/pkg/analysis_server/lib/src/services/flutter/property.dart
index 0d4f3e3..11af175 100644
--- a/pkg/analysis_server/lib/src/services/flutter/property.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/property.dart
@@ -118,7 +118,7 @@
       );
     }
 
-    await builder.addDartFileEdit(resolvedUnit.path, (builder) {
+    await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
       _changeCode(builder, (builder) {
         var expression = value.expression;
         if (expression != null) {
@@ -155,7 +155,7 @@
       }
 
       var beginOffset = argumentExpression.offset;
-      await builder.addDartFileEdit(resolvedUnit.path, (builder) {
+      await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
         builder.addDeletion(
           SourceRange(beginOffset, endOffset - beginOffset),
         );
@@ -559,7 +559,7 @@
 
     var builder = ChangeBuilder(session: property.resolvedUnit.session);
 
-    await builder.addDartFileEdit(property.resolvedUnit.path, (builder) {
+    await builder.addDartFileEdit(property.resolvedUnit.path!, (builder) {
       property._changeCode(builder, (builder) {
         if (leftCode == rightCode && topCode == bottomCode) {
           builder.writeReference(classEdgeInsets);
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index 822589b..e81ca0e 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -30,6 +30,7 @@
     handler = EditDomainHandler(server);
   }
 
+  @failingTest
   Future test_BAD_doesNotExist() async {
     // The analysis driver fails to return an error
     var request =
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 4320775..850b29a 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -360,7 +360,7 @@
   Map<String, FileResult> fileResults = {};
 
   void addFileResult(FileResult result) {
-    fileResults[result.path] = result;
+    fileResults[result.path!] = result;
   }
 
   @override
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 6c36a21..4a17594 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -17,7 +17,9 @@
 abstract class AnalysisResult {
   /// The absolute and normalized path of the file that was analyzed.
   /// If [state] is not [ResultState.VALID], throws [StateError].
-  String get path;
+  ///
+  /// TODO(migration): should not be nullable
+  String? get path;
 
   /// Return the session used to compute this result.
   /// If [state] is not [ResultState.VALID], throws [StateError].
@@ -84,13 +86,13 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class ParsedLibraryResult implements AnalysisResult {
   /// The parsed units of the library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
-  List<ParsedUnitResult> get units;
+  ///
+  /// TODO(migration): should not be null, probably empty list
+  List<ParsedUnitResult>? get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
   /// this library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
   ElementDeclarationResult? getElementDeclaration(Element element);
 }
 
@@ -132,21 +134,17 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class ResolvedLibraryResult implements AnalysisResult {
   /// The element representing this library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
-  LibraryElement get element;
+  LibraryElement? get element;
 
   /// The type provider used when resolving the library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
   TypeProvider get typeProvider;
 
   /// The resolved units of the library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
-  List<ResolvedUnitResult> get units;
+  List<ResolvedUnitResult>? get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
   /// this library.
-  /// If [state] is not [ResultState.VALID], throws [StateError].
   ElementDeclarationResult? getElementDeclaration(Element element);
 }
 
@@ -173,10 +171,6 @@
 
 /// An indication of whether an analysis result is valid, and if not why.
 enum ResultState {
-  /// An indication that the analysis result cannot be provided because
-  /// the library is created from summary.
-  EXTERNAL_LIBRARY,
-
   /// An indication that analysis could not be performed because the path
   /// represents a file of a type that cannot be analyzed.
   INVALID_FILE_TYPE,
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 0317cd7..ef61719 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -851,7 +851,6 @@
   StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK,
   StrongModeCode.TOP_LEVEL_IDENTIFIER_NO_TYPE,
   StrongModeCode.TOP_LEVEL_INSTANCE_GETTER,
-  StrongModeCode.TOP_LEVEL_INSTANCE_METHOD,
   TodoCode.TODO,
 ];
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 75f297c..8f17b48 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -215,7 +215,7 @@
   final _resultController = StreamController<ResolvedUnitResult>();
 
   /// The stream that will be written to when analysis results are produced.
-  late final Stream<ResolvedUnitResult> _resultStream;
+  late final Stream<ResolvedUnitResult> _onResults;
 
   /// Resolution signatures of the most recently produced results for files.
   final Map<String, String> _lastProducedSignatures = {};
@@ -282,7 +282,7 @@
         _externalSummaries = externalSummaries,
         testingData = retainDataForTesting ? TestingData() : null {
     _createNewSession(null);
-    _resultStream = _resultController.stream.asBroadcastStream();
+    _onResults = _resultController.stream.asBroadcastStream();
     _testView = AnalysisDriverTestView(this);
     _createFileTracker();
     _scheduler.add(this);
@@ -361,7 +361,7 @@
   ///
   /// Results might be produced even for files that have never been added
   /// using [addFile], for example when [getResult] was called for a file.
-  Stream<ResolvedUnitResult> get results => _resultStream;
+  Stream<ResolvedUnitResult> get results => _onResults;
 
   /// Return the search support for the driver.
   Search get search => _search;
@@ -649,7 +649,7 @@
     FileState file = _fsState.getFileForPath(path);
 
     if (file.isExternalLibrary) {
-      return NotValidParsedLibraryResultImpl(ResultState.EXTERNAL_LIBRARY);
+      return ParsedLibraryResultImpl.external(currentSession, file.uri);
     }
 
     if (file.isPart) {
@@ -680,7 +680,7 @@
     }
 
     if (file.isExternalLibrary) {
-      return NotValidParsedLibraryResultImpl(ResultState.EXTERNAL_LIBRARY);
+      return ParsedLibraryResultImpl.external(currentSession, file.uri);
     }
 
     if (file.isPart) {
@@ -718,7 +718,7 @@
 
     if (file.isExternalLibrary) {
       return Future.value(
-        NotValidResolvedLibraryResultImpl(ResultState.EXTERNAL_LIBRARY),
+        ResolvedLibraryResultImpl.external(currentSession, file.uri),
       );
     }
 
@@ -756,7 +756,7 @@
 
     if (file.isExternalLibrary) {
       return Future.value(
-        NotValidResolvedLibraryResultImpl(ResultState.EXTERNAL_LIBRARY),
+        ResolvedLibraryResultImpl.external(currentSession, file.uri),
       );
     }
 
@@ -1102,7 +1102,7 @@
           // last time, so we don't need to produce it again now.
         } else {
           _resultController.add(result);
-          _lastProducedSignatures[result.path] = result._signature;
+          _lastProducedSignatures[result.path!] = result._signature;
         }
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index 1f4ded0..c2e5b28 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -18,7 +18,7 @@
   final AnalysisSession session;
 
   @override
-  final String path;
+  final String? path;
 
   @override
   final Uri uri;
@@ -75,7 +75,7 @@
   NotValidAnalysisResultImpl(this.state);
 
   @override
-  String get path {
+  String? get path {
     throw StateError('This result is not valid');
   }
 
@@ -117,46 +117,6 @@
   }
 }
 
-class NotValidParsedLibraryResultImpl extends NotValidAnalysisResultImpl
-    implements ParsedLibraryResult {
-  NotValidParsedLibraryResultImpl(ResultState state) : super(state);
-
-  @override
-  List<ParsedUnitResult> get units {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  ElementDeclarationResult? getElementDeclaration(Element element) {
-    throw StateError('This result is not valid');
-  }
-}
-
-class NotValidResolvedLibraryResultImpl extends NotValidAnalysisResultImpl
-    implements ResolvedLibraryResult {
-  NotValidResolvedLibraryResultImpl(ResultState state) : super(state);
-
-  @override
-  LibraryElement get element {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  TypeProvider get typeProvider {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  List<ResolvedUnitResult> get units {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  ElementDeclarationResult? getElementDeclaration(Element element) {
-    throw StateError('This result is not valid');
-  }
-}
-
 /// The implementation of [ResolvedUnitResult] when not [ResultState.VALID].
 class NotValidResolvedUnitResultImpl extends NotValidFileResultImpl
     implements ResolvedUnitResult {
@@ -212,14 +172,20 @@
 class ParsedLibraryResultImpl extends AnalysisResultImpl
     implements ParsedLibraryResult {
   @override
-  final List<ParsedUnitResult> units;
+  final List<ParsedUnitResult>? units;
 
   ParsedLibraryResultImpl(
-      AnalysisSession session, String path, Uri uri, this.units)
+      AnalysisSession session, String? path, Uri uri, this.units)
       : super(session, path, uri);
 
+  ParsedLibraryResultImpl.external(AnalysisSession session, Uri uri)
+      : this(session, null, uri, null);
+
   @override
   ResultState get state {
+    if (path == null) {
+      return ResultState.NOT_A_FILE;
+    }
     return ResultState.VALID;
   }
 
@@ -237,7 +203,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units.firstWhere(
+    var unitResult = units!.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -295,22 +261,28 @@
 class ResolvedLibraryResultImpl extends AnalysisResultImpl
     implements ResolvedLibraryResult {
   @override
-  final LibraryElement element;
+  final LibraryElement? element;
 
   @override
-  final List<ResolvedUnitResult> units;
+  final List<ResolvedUnitResult>? units;
 
   ResolvedLibraryResultImpl(
-      AnalysisSession session, String path, Uri uri, this.element, this.units)
+      AnalysisSession session, String? path, Uri uri, this.element, this.units)
       : super(session, path, uri);
 
+  ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri)
+      : this(session, null, uri, null, null);
+
   @override
   ResultState get state {
+    if (path == null) {
+      return ResultState.NOT_A_FILE;
+    }
     return ResultState.VALID;
   }
 
   @override
-  TypeProvider get typeProvider => element.typeProvider;
+  TypeProvider get typeProvider => element!.typeProvider;
 
   @override
   ElementDeclarationResult? getElementDeclaration(Element element) {
@@ -326,7 +298,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units.firstWhere(
+    var unitResult = units!.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -335,7 +307,7 @@
         buffer.writeln(' is not defined in this library.');
         // TODO(scheglov) https://github.com/dart-lang/sdk/issues/45430
         buffer.writeln('elementPath: $elementPath');
-        buffer.writeln('unitPaths: ${units.map((e) => e.path).toList()}');
+        buffer.writeln('unitPaths: ${units!.map((e) => e.path).toList()}');
         throw ArgumentError('$buffer');
       },
     );
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index d65da13..235e67d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -54,7 +54,7 @@
     var resolvedLibrary = await _getResolvedLibrary(libraryPath);
 
     var unitPath = element.source!.fullName;
-    return resolvedLibrary.units.singleWhere((resolvedUnit) {
+    return resolvedLibrary.units!.singleWhere((resolvedUnit) {
       return resolvedUnit.path == unitPath;
     });
   }
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index fb17e85..e7dff9b 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -398,7 +398,7 @@
         performance: performance,
       );
       var result =
-          libraryUnit.units.firstWhere((element) => element.path == path);
+          libraryUnit.units!.firstWhere((element) => element.path == path);
       return result;
     });
   }
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 58fcf57..bf643c4 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -14223,13 +14223,6 @@
           "getter, '{1}', which has an implicit type.",
       correction: "Add an explicit type for either '{0}' or '{1}'.");
 
-  static const StrongModeCode TOP_LEVEL_INSTANCE_METHOD = StrongModeCode(
-      ErrorType.STATIC_WARNING,
-      'TOP_LEVEL_INSTANCE_METHOD',
-      "The type of '{0}' can't be inferred because it refers to an instance "
-          "method, '{1}', which has an implicit type.",
-      correction: "Add an explicit type for either '{0}' or '{1}'.");
-
   @override
   final ErrorType type;
 
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index e4fea47..ee2b7f3 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -1029,14 +1029,6 @@
           _codeChecker._recordMessage(
               n, StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, [_name, e.name]);
         }
-      } else if (!isMethodCall &&
-          e is ExecutableElement &&
-          e.kind == ElementKind.METHOD &&
-          !e.isStatic) {
-        if (_hasAnyImplicitType(e)) {
-          _codeChecker._recordMessage(
-              n, StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, [_name, e.name]);
-        }
       }
     }
   }
@@ -1135,19 +1127,7 @@
     var method = node.methodName.staticElement;
     validateIdentifierElement(node, method, isMethodCall: true);
     if (method is ExecutableElement) {
-      if (method.kind == ElementKind.METHOD &&
-          !method.isStatic &&
-          method.hasImplicitReturnType) {
-        _codeChecker._recordMessage(node,
-            StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, [_name, method.name]);
-      }
       if (node.typeArguments == null && method.typeParameters.isNotEmpty) {
-        if (method.kind == ElementKind.METHOD &&
-            !method.isStatic &&
-            _anyParameterHasImplicitType(method)) {
-          _codeChecker._recordMessage(node,
-              StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, [_name, method.name]);
-        }
         // Type inference might depend on the parameters
         node.argumentList.accept(this);
       }
@@ -1179,16 +1159,4 @@
   visitThrowExpression(ThrowExpression node) {
     // Nothing to validate.
   }
-
-  bool _anyParameterHasImplicitType(ExecutableElement e) {
-    for (var parameter in e.parameters) {
-      if (parameter.hasImplicitType) return true;
-    }
-    return false;
-  }
-
-  bool _hasAnyImplicitType(ExecutableElement e) {
-    if (e.hasImplicitReturnType) return true;
-    return _anyParameterHasImplicitType(e);
-  }
 }
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index c285f9b..5b8847d 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -497,7 +497,7 @@
 
     var expression = findNode.variableDeclaration('x =').initializer!;
 
-    var file = getFile(result.path);
+    var file = getFile(result.path!);
     var evaluator = ConstantEvaluator(
       file.createSource(result.uri),
       result.libraryElement as LibraryElementImpl,
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
index 978ea99..3eec88f 100644
--- a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
@@ -138,7 +138,7 @@
   Future<List<CompilationUnit>> _resolveLibrary(String libraryPath) async {
     var session = contextFor(libraryPath).currentSession;
     var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
-    return resolvedLibrary.units.map((ru) => ru.unit!).toList();
+    return resolvedLibrary.units!.map((ru) => ru.unit!).toList();
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 6572ba2..9ddda1e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -3063,7 +3063,7 @@
     driver.changeFile(b);
     await waitForIdleWithoutExceptions();
 
-    List<String> analyzedPaths = allResults.map((r) => r.path).toList();
+    List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
 
     // The changed file must be the first.
     expect(analyzedPaths[0], b);
@@ -3105,7 +3105,7 @@
     driver.changeFile(a);
     await waitForIdleWithoutExceptions();
 
-    List<String> analyzedPaths = allResults.map((r) => r.path).toList();
+    List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
 
     // The changed files must be the first.
     expect(analyzedPaths[0], a);
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index c32728a..f1235ca 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -175,7 +175,7 @@
 
     expect(parsedLibrary.units, hasLength(1));
     {
-      var parsedUnit = parsedLibrary.units[0];
+      var parsedUnit = parsedLibrary.units![0];
       expect(parsedUnit.session, session);
       expect(parsedUnit.path, testPath);
       expect(parsedUnit.uri, Uri.parse('package:test/test.dart'));
@@ -249,15 +249,15 @@
 
     expect(parsedLibrary.units, hasLength(3));
     expect(
-      parsedLibrary.units[0].path,
+      parsedLibrary.units![0].path,
       convertPath('/home/test/lib/test.dart'),
     );
     expect(
-      parsedLibrary.units[1].path,
+      parsedLibrary.units![1].path,
       convertPath('/home/test/lib/a.dart'),
     );
     expect(
-      parsedLibrary.units[2].path,
+      parsedLibrary.units![2].path,
       convertPath('/home/test/lib/c.dart'),
     );
   }
@@ -307,21 +307,21 @@
     expect(parsedLibrary.units, hasLength(3));
 
     {
-      var aUnit = parsedLibrary.units[0];
+      var aUnit = parsedLibrary.units![0];
       expect(aUnit.path, a);
       expect(aUnit.uri, Uri.parse('package:test/a.dart'));
       expect(aUnit.unit.declarations, hasLength(1));
     }
 
     {
-      var bUnit = parsedLibrary.units[1];
+      var bUnit = parsedLibrary.units![1];
       expect(bUnit.path, b);
       expect(bUnit.uri, Uri.parse('package:test/b.dart'));
       expect(bUnit.unit.declarations, hasLength(2));
     }
 
     {
-      var cUnit = parsedLibrary.units[2];
+      var cUnit = parsedLibrary.units![2];
       expect(cUnit.path, c);
       expect(cUnit.uri, Uri.parse('package:test/c.dart'));
       expect(cUnit.unit.declarations, hasLength(3));
@@ -393,13 +393,13 @@
     var typeProvider = resolvedLibrary.typeProvider;
     expect(typeProvider.intType.element.name, 'int');
 
-    var libraryElement = resolvedLibrary.element;
+    var libraryElement = resolvedLibrary.element!;
 
     var aClass = libraryElement.getType('A')!;
 
     var bClass = libraryElement.getType('B')!;
 
-    var aUnitResult = resolvedLibrary.units[0];
+    var aUnitResult = resolvedLibrary.units![0];
     expect(aUnitResult.path, a);
     expect(aUnitResult.uri, Uri.parse('package:test/a.dart'));
     expect(aUnitResult.content, aContent);
@@ -408,7 +408,7 @@
     expect(aUnitResult.unit!.declarations, hasLength(1));
     expect(aUnitResult.errors, isEmpty);
 
-    var bUnitResult = resolvedLibrary.units[1];
+    var bUnitResult = resolvedLibrary.units![1];
     expect(bUnitResult.path, b);
     expect(bUnitResult.uri, Uri.parse('package:test/b.dart'));
     expect(bUnitResult.content, bContent);
@@ -449,7 +449,7 @@
 ''');
 
     var resolvedLibrary = await session.getResolvedLibrary(testPath);
-    var unitElement = resolvedLibrary.element.definingCompilationUnit;
+    var unitElement = resolvedLibrary.element!.definingCompilationUnit;
 
     var fooElement = unitElement.topLevelVariables[0];
     expect(fooElement.name, 'foo');
@@ -478,15 +478,15 @@
 
     expect(resolvedLibrary.units, hasLength(3));
     expect(
-      resolvedLibrary.units[0].path,
+      resolvedLibrary.units![0].path,
       convertPath('/home/test/lib/test.dart'),
     );
     expect(
-      resolvedLibrary.units[1].path,
+      resolvedLibrary.units![1].path,
       convertPath('/home/test/lib/a.dart'),
     );
     expect(
-      resolvedLibrary.units[2].path,
+      resolvedLibrary.units![2].path,
       convertPath('/home/test/lib/c.dart'),
     );
   }
@@ -509,7 +509,7 @@
     expect(resolvedLibrary.path, testPath);
     expect(resolvedLibrary.uri, Uri.parse('package:test/test.dart'));
     expect(resolvedLibrary.units, hasLength(1));
-    expect(resolvedLibrary.units[0].unit!.declaredElement, isNotNull);
+    expect(resolvedLibrary.units![0].unit!.declaredElement, isNotNull);
   }
 
   test_getResolvedLibraryByElement_differentSession() async {
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 54c65b5..aa6dfb3 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -700,7 +700,7 @@
 
     var result = fileResolver.resolveLibrary(path: aPath);
     expect(result.path, aPath);
-    expect(result.units.length, 2);
+    expect(result.units?.length, 2);
   }
 
   test_reuse_compatibleOptions() async {
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 6bd56ae..3d1234d 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -607,7 +607,6 @@
 import 'todo_test.dart' as todo_test;
 import 'top_level_cycle_test.dart' as top_level_cycle;
 import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
-import 'top_level_instance_method_test.dart' as top_level_instance_method;
 import 'type_alias_cannot_reference_itself_test.dart'
     as type_alias_cannot_reference_itself;
 import 'type_annotation_deferred_class_test.dart'
@@ -1087,7 +1086,6 @@
     todo_test.main();
     top_level_cycle.main();
     top_level_instance_getter.main();
-    top_level_instance_method.main();
     type_alias_cannot_reference_itself.main();
     type_annotation_deferred_class.main();
     type_argument_not_matching_bounds.main();
diff --git a/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart b/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
deleted file mode 100644
index b71dd5b..0000000
--- a/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(TopLevelInstanceMethodTest);
-  });
-}
-
-@reflectiveTest
-class TopLevelInstanceMethodTest extends PubPackageResolutionTest {
-  test_noParameter() async {
-    await assertErrorsInCode('''
-class A {
-  f() => 0;
-}
-var x = new A().f();
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 32, 11),
-    ]);
-  }
-
-  test_parameter() async {
-    await assertNoErrorsInCode('''
-class A {
-  int f(v) => 0;
-}
-var x = new A().f(0);
-''');
-  }
-
-  test_parameter_generic() async {
-    await assertErrorsInCode('''
-class A {
-  int f<T>(v) => 0;
-}
-var x = new A().f(0);
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 40, 12),
-    ]);
-  }
-
-  test_parameter_generic_explicit() async {
-    await assertNoErrorsInCode('''
-class A {
-  int f<T>(v) => 0;
-}
-var x = new A().f<int>(0);
-''');
-  }
-
-  test_static() async {
-    await assertNoErrorsInCode('''
-class A {
-  static f() => 0;
-}
-var x = A.f();
-''');
-  }
-
-  test_tearOff() async {
-    await assertErrorsInCode('''
-class A {
-  f() => 0;
-}
-var x = new A().f;
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 40, 1),
-    ]);
-  }
-
-  test_tearOff_parameter() async {
-    await assertErrorsInCode('''
-class A {
-  int f(v) => 0;
-}
-var x = new A().f;
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 45, 1),
-    ]);
-  }
-
-  test_tearoff_static() async {
-    await assertNoErrorsInCode('''
-class A {
-  static f() => 0;
-}
-var x = A.f;
-''');
-  }
-}
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index fc25b65..212b95b 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -804,6 +804,29 @@
 ''');
   }
 
+  test_initializer_fromInstanceMethod() async {
+    var library = await _encodeDecodeLibrary(r'''
+class A {
+  int foo() => 0;
+}
+class B extends A {
+  foo() => 1;
+}
+var x = A().foo();
+var y = B().foo();
+''');
+    checkElementText(library, r'''
+class A {
+  int foo() {}
+}
+class B extends A {
+  int foo() {}
+}
+int x;
+int y;
+''');
+  }
+
   test_initializer_functionExpression() async {
     var library = await _encodeDecodeLibrary(r'''
 import 'dart:async';
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index cc1d282..d77818f 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -2560,7 +2560,7 @@
   }
 
   test_infer_use_of_void() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 class B {
   void f() {}
 }
@@ -2568,9 +2568,8 @@
   f() {}
 }
 var x = new C().f();
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_METHOD, 65, 11),
-    ]);
+''');
+    assertType(findElement.topVar('x').type, 'void');
   }
 
   test_inferConstsTransitively() async {
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 8fdbc40..f99f600 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -285,7 +285,7 @@
   /// Extract documentation from the file that was parsed to produce the given
   /// [result].
   Future<void> _validateFile(ParsedUnitResult result) async {
-    filePath = result.path;
+    filePath = result.path!;
     hasWrittenFilePath = false;
     CompilationUnit unit = result.unit;
     for (CompilationUnitMember declaration in unit.declarations) {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index dc60a78..443c711 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1281,7 +1281,7 @@
   /// the given [resolvedUnit] and [timeStamp].
   DartFileEditBuilderImpl(ChangeBuilderImpl changeBuilder, this.resolvedUnit,
       int timeStamp, this.libraryChangeBuilder)
-      : super(changeBuilder, resolvedUnit.path, timeStamp);
+      : super(changeBuilder, resolvedUnit.path!, timeStamp);
 
   @override
   bool get hasEdits =>
diff --git a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
index d424abf..a302a76 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
@@ -21,7 +21,7 @@
   DartFoldingRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [FoldingCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
index 95bd889..5e55b48 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
@@ -21,7 +21,7 @@
   DartHighlightsRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [HighlightsCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
index 684e9e7..191101c 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
@@ -19,7 +19,7 @@
   DartEntryRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [EntryCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
index 23709a3..4e1850c 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
@@ -28,7 +28,7 @@
       this.resourceProvider, this.offset, this.length, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [NavigationCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
index f436774..6bd0592 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
@@ -20,7 +20,7 @@
   DartOccurrencesRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [OccurrencesCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
index 284f140..44d4dd9 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
@@ -20,7 +20,7 @@
   DartOutlineRequestImpl(this.resourceProvider, this.result);
 
   @override
-  String get path => result.path;
+  String get path => result.path!;
 }
 
 /// A concrete implementation of [OutlineCollector].
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 977a16c..0dfdbc8 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -16545,7 +16545,7 @@
 
   String? get status native;
 
-  FontFaceSet add(FontFace arg) native;
+  FontFaceSet? add(FontFace arg) native;
 
   bool check(String font, [String? text]) native;
 
@@ -40994,8 +40994,8 @@
 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
   NodeValidator validator;
 
-  /// Did we modify the tree by removing anything.
-  bool modifiedTree = false;
+  /// Number of tree modifications this instance has made.
+  int numTreeModifications = 0;
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
@@ -41026,12 +41026,12 @@
       }
     }
 
-    modifiedTree = false;
-    walk(node, null);
-    while (modifiedTree) {
-      modifiedTree = false;
+    // Walk the tree until no new modifications are added to the tree.
+    var previousTreeModifications;
+    do {
+      previousTreeModifications = numTreeModifications;
       walk(node, null);
-    }
+    } while (previousTreeModifications != numTreeModifications);
   }
 
   /// Aggressively try to remove node.
@@ -41039,7 +41039,7 @@
     // If we have the parent, it's presumably already passed more sanitization
     // or is the fragment, so ask it to remove the child. And if that fails
     // try to set the outer html.
-    modifiedTree = true;
+    numTreeModifications++;
     if (parent == null || parent != node.parentNode) {
       node.remove();
     } else {
diff --git a/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart b/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
index 5a3d0f2..2d7205c 100644
--- a/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
+++ b/tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
@@ -453,6 +453,20 @@
             "<input id='bad' onmouseover='alert(1)'>",
         "");
 
+    // Walking templates triggers a recursive sanitization call, which shouldn't
+    // invalidate the information collected from the previous visit of the later
+    // nodes in the walk.
+    testHtml(
+        'DOM clobbering with recursive sanitize call using templates',
+        validator,
+        "<form><div>"
+            "<input id=childNodes />"
+            "<template></template>"
+            "<input id=childNodes name=lastChild />"
+            "<img id=exploitImg src=0 onerror='alert(1)' />"
+            "</div></form>",
+        "");
+
     test('tagName makes containing form invalid', () {
       var fragment = document.body!.createFragment(
           "<form onmouseover='alert(2)'><input name='tagName'>",
diff --git a/tests/lib_2/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart b/tests/lib_2/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
index 1b3ea60..ee31868 100644
--- a/tests/lib_2/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
+++ b/tests/lib_2/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
@@ -478,6 +478,20 @@
         "<input id='bad' onmouseover='alert(1)'>",
         "");
 
+    // Walking templates triggers a recursive sanitization call, which shouldn't
+    // invalidate the information collected from the previous visit of the later
+    // nodes in the walk.
+    testHtml(
+        'DOM clobbering with recursive sanitize call using templates',
+        validator,
+        "<form><div>"
+          "<input id=childNodes />"
+          "<template></template>"
+          "<input id=childNodes name=lastChild />"
+          "<img id=exploitImg src=0 onerror='alert(1)' />"
+          "</div></form>",
+        "");
+
     test('tagName makes containing form invalid', () {
       var fragment = document.body.createFragment(
           "<form onmouseover='alert(2)'><input name='tagName'>",
diff --git a/tools/VERSION b/tools/VERSION
index baa7861..9201ef4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 2
+PRERELEASE 3
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index 475b759..4518982 100644
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -796,7 +796,11 @@
     return syn_op
 
 
-def generate_operation(interface_name, result_type_name, oper_name, arguments):
+def generate_operation(interface_name,
+                       result_type_name,
+                       oper_name,
+                       arguments,
+                       result_nullable=False):
     """ Synthesize an IDLOperation with no AST used for support of setlike."""
     """ Arguments is a list of argument where each argument is:
           [IDLType, argument_name, optional_boolean] """
@@ -805,6 +809,7 @@
 
     syn_op.type = IDLType(None, result_type_name)
     syn_op.type = resolveTypedef(syn_op.type)
+    syn_op.type.nullable = result_nullable
 
     for argument in arguments:
         arg = IDLArgument(None, argument[1])
@@ -854,9 +859,13 @@
     setlike_ops.append(set_op)
 
     if not set_like.is_read_only:
+        # Issue #45676: `add` can return null on Firefox, so this should be
+        # typed nullable.
+        add_result_nullable = True
         set_op = generate_operation(
             interface.id, interface.id, 'add',
-            [[IDLType(None, set_like.value_type.base_type), 'arg']])
+            [[IDLType(None, set_like.value_type.base_type), 'arg']],
+            add_result_nullable)
         setlike_ops.append(set_op)
         set_op = generate_operation(
             interface.id, 'boolean', 'delete',
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
index 0c45b8c..1fbafbd 100644
--- a/tools/dom/src/Validators.dart
+++ b/tools/dom/src/Validators.dart
@@ -158,8 +158,8 @@
 class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
   NodeValidator validator;
 
-  /// Did we modify the tree by removing anything.
-  bool modifiedTree = false;
+  /// Number of tree modifications this instance has made.
+  int numTreeModifications = 0;
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
@@ -190,12 +190,12 @@
       }
     }
 
-    modifiedTree = false;
-    walk(node, null);
-    while (modifiedTree) {
-      modifiedTree = false;
+    // Walk the tree until no new modifications are added to the tree.
+    var previousTreeModifications;
+    do {
+      previousTreeModifications = numTreeModifications;
       walk(node, null);
-    }
+    } while (previousTreeModifications != numTreeModifications);
   }
 
   /// Aggressively try to remove node.
@@ -203,7 +203,7 @@
     // If we have the parent, it's presumably already passed more sanitization
     // or is the fragment, so ask it to remove the child. And if that fails
     // try to set the outer html.
-    modifiedTree = true;
+    numTreeModifications++;
     if (parent == null || parent != node.parentNode) {
       node.remove();
     } else {