Version 2.19.0-18.0.dev

Merge commit '210af2940f89ffc3ddf8c929cb2f0e8dbd8fd399' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02ba848..d26be9c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
 
 ### Libraries
 
-### `dart:developer`
+#### `dart:developer`
 
 #### `dart:developer`
 
@@ -19,6 +19,16 @@
 
 - Deprecated `UserTag.MAX_USER_TAGS` in favor of `UserTag.maxUserTags`.
 
+#### `dart:mirrors`
+
+- **Breaking change** [#34233][]: The APIs [`MirrorsUsed`][] and [`Comment`][]
+  have been removed. `MirrorsUsed` was experimental and deprecated; `Comment`
+  was previously used internally in dart2js. Both are no longer functional.
+
+[#34233]: https://github.com/dart-lang/sdk/issues/34233
+[`MirrorsUsed`]: https://api.dart.dev/stable/dart-mirrors/MirrorsUsed-class.html
+[`Comment`]: https://api.dart.dev/stable/dart-mirrors/Comment-class.html
+
 ### Tools
 
 #### Linter
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
index 30ace8f..8206e04 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_imports.dart
@@ -72,24 +72,25 @@
     var lineInfo = unit.lineInfo;
     var hasLibraryDirective = false;
     var directives = <_DirectiveInfo>[];
-    // Track the end offset of any library-level comment/annotations that should
-    // remain at the top of the file regardless of whether it was attached to a
-    // directive that's moved/removed.
-    // Code up to this offset will be excluded from the comment/docs/annotation
-    // text for the computed DirectiveInfo and also its range for replacement
-    // in the document.
-    int? libraryDocsAndAnnotationsEndOffset;
     for (var directive in unit.directives) {
       if (directive is LibraryDirective) {
         hasLibraryDirective = true;
       }
       if (directive is UriBasedDirective) {
+        // Track the end offset of any library-level comment/annotations that should
+        // remain at the top of the file regardless of whether it was attached to a
+        // directive that's moved/removed.
+        // Code up to this offset will be excluded from the comment/docs/annotation
+        // text for the computed DirectiveInfo and also its range for replacement
+        // in the document.
+        int? libraryDocsAndAnnotationsEndOffset;
         var priority = _getDirectivePriority(directive);
         if (priority != null) {
           var offset = directive.offset;
           var end = directive.end;
 
-          final isPseudoLibraryDirective = directive == unit.directives.first;
+          final isPseudoLibraryDirective =
+              !hasLibraryDirective && directive == unit.directives.first;
           Annotation? lastLibraryAnnotation;
           if (isPseudoLibraryDirective) {
             // Find the last library-level annotation that does not come
@@ -99,10 +100,17 @@
             lastLibraryAnnotation = directive.metadata
                 .takeWhile(_isLibraryTargetAnnotation)
                 .lastOrNull;
-            if (lastLibraryAnnotation != null) {
-              libraryDocsAndAnnotationsEndOffset =
-                  lineInfo.getOffsetOfLineAfter(lastLibraryAnnotation.end);
-              // In the case of a blank line after the last library annotation
+
+            // If there is no annotation, use the end of the doc text (since the
+            // doc text is considered library-level here).
+            libraryDocsAndAnnotationsEndOffset = lastLibraryAnnotation?.end ??
+                directive.documentationComment?.end;
+
+            // Fix up the offset to be after the line end.
+            if (libraryDocsAndAnnotationsEndOffset != null) {
+              libraryDocsAndAnnotationsEndOffset = lineInfo
+                  .getOffsetOfLineAfter(libraryDocsAndAnnotationsEndOffset);
+              // In the case of a blank line after the annotation/doc text
               // we should include that in the library part. Otherwise it will
               // be included in the top of the following directive and may
               // result in an extra blank line in the annotation block if it
@@ -124,84 +132,25 @@
           final leadingToken =
               lastLibraryAnnotation == null ? directive.beginToken : null;
           final leadingComment = leadingToken != null
-              ? getLeadingComment(unit, leadingToken, lineInfo)
+              ? getLeadingComment(unit, leadingToken, lineInfo,
+                  isPseudoLibraryDirective: isPseudoLibraryDirective)
               : null;
           final trailingComment = getTrailingComment(unit, directive, lineInfo);
 
-          /// Computes the offset to use for the start of directive-specific
-          /// code below taking into account code already included by
-          /// [libraryDocsAndAnnotationsEndOffset].
-          final clampedOffset = libraryDocsAndAnnotationsEndOffset == null
-              ? (int offset) => offset
-              : (int offset) =>
-                  math.max(libraryDocsAndAnnotationsEndOffset!, offset);
-
-          String? leadingCommentText;
           if (leadingComment != null && leadingToken != null) {
-            offset = clampedOffset(leadingComment.offset);
-            leadingCommentText = code.substring(
-              offset,
-              clampedOffset(leadingToken.offset),
-            );
+            offset = libraryDocsAndAnnotationsEndOffset != null
+                ? math.max(
+                    libraryDocsAndAnnotationsEndOffset, leadingComment.offset)
+                : leadingComment.offset;
           }
-          String? trailingCommentText;
           if (trailingComment != null) {
-            trailingCommentText =
-                code.substring(directive.end, trailingComment.end);
             end = trailingComment.end;
           }
-          String? documentationText;
-          var documentationComment = directive.documentationComment;
-          if (documentationComment != null) {
-            documentationText = code.substring(
-              clampedOffset(documentationComment.offset),
-              clampedOffset(documentationComment.end),
-            );
-          }
-          String? annotationText;
-          String? postAnnotationCommentText;
-          var beginToken = directive.metadata.beginToken;
-          var endToken = directive.metadata.endToken;
-          if (beginToken != null && endToken != null) {
-            var annotationOffset = clampedOffset(beginToken.offset);
-            var annotationEnd = clampedOffset(endToken.end);
-            if (annotationOffset != annotationEnd) {
-              annotationText = code.substring(
-                annotationOffset,
-                annotationEnd,
-              );
-            }
-            // Capture text between the end of the annotation and the directive
-            // text as there may be end-of line or line comments between.
-            // If not, this will capture the newline between the two, as it
-            // cannot be assumed there is a newline after annotationText because
-            // of the possibility of comments.
-            if (annotationEnd <
-                directive.firstTokenAfterCommentAndMetadata.offset) {
-              postAnnotationCommentText = code.substring(annotationEnd,
-                  directive.firstTokenAfterCommentAndMetadata.offset);
-            }
-          }
-          var text = code.substring(
-              directive.firstTokenAfterCommentAndMetadata.offset,
-              directive.end);
-          var uriContent = directive.uri.stringValue ?? '';
+          offset = libraryDocsAndAnnotationsEndOffset ?? offset;
+          final text = code.substring(offset, end);
+          final uriContent = directive.uri.stringValue ?? '';
           directives.add(
-            _DirectiveInfo(
-              directive,
-              priority,
-              leadingCommentText,
-              documentationText,
-              annotationText,
-              postAnnotationCommentText,
-              uriContent,
-              trailingCommentText,
-              isPseudoLibraryDirective
-                  ? (libraryDocsAndAnnotationsEndOffset ?? offset)
-                  : offset,
-              end,
-              text,
-            ),
+            _DirectiveInfo(directive, priority, uriContent, offset, end, text),
           );
         }
       }
@@ -213,24 +162,12 @@
     var firstDirectiveOffset = directives.first.offset;
     var lastDirectiveEnd = directives.last.end;
 
-    // Without a library directive, the library comment is the comment of the
-    // first directive.
-    _DirectiveInfo? libraryDocumentationDirective;
-    if (!hasLibraryDirective && directives.isNotEmpty) {
-      libraryDocumentationDirective = directives.first;
-    }
-
     // sort
     directives.sort();
     // append directives with grouping
     String directivesCode;
     {
       var sb = StringBuffer();
-      if (libraryDocumentationDirective != null &&
-          libraryDocumentationDirective.documentationText != null) {
-        sb.write(libraryDocumentationDirective.documentationText);
-        sb.write(endOfLine);
-      }
       _DirectivePriority? currentPriority;
       for (var directiveInfo in directives) {
         if (!hasUnresolvedIdentifierError) {
@@ -245,24 +182,7 @@
           }
           currentPriority = directiveInfo.priority;
         }
-        if (directiveInfo.leadingCommentText != null) {
-          sb.write(directiveInfo.leadingCommentText);
-        }
-        if (directiveInfo != libraryDocumentationDirective &&
-            directiveInfo.documentationText != null) {
-          sb.write(directiveInfo.documentationText);
-          sb.write(endOfLine);
-        }
-        if (directiveInfo.annotationText != null) {
-          sb.write(directiveInfo.annotationText);
-        }
-        if (directiveInfo.postAnnotationCommentText != null) {
-          sb.write(directiveInfo.postAnnotationCommentText);
-        }
         sb.write(directiveInfo.text);
-        if (directiveInfo.trailingCommentText != null) {
-          sb.write(directiveInfo.trailingCommentText);
-        }
         sb.write(endOfLine);
       }
       directivesCode = sb.toString();
@@ -286,14 +206,16 @@
   /// Gets the first comment token considered to be the leading comment for this
   /// token.
   ///
-  /// Leading comments for the first directive in a file are considered library
-  /// comments and not returned unless they contain blank lines, in which case
-  /// only the last part of the comment will be returned (unless it is a
-  /// language directive comment, in which case it will also be skipped) or an
-  /// '// ignore:' comment which should always be treated as attached to the
-  /// import.
+  /// Leading comments for the first directive in a file with no library
+  /// directive (indicated with [isPseudoLibraryDirective]) are considered
+  /// library comments and not included unless they contain blank lines, in
+  /// which case only the last part of the comment will be returned (unless it
+  /// is a language directive comment, in which case it will also be skipped),
+  /// or an '// ignore:' comment which should always be treated as attached to
+  /// the import.
   static Token? getLeadingComment(
-      CompilationUnit unit, Token beginToken, LineInfo lineInfo) {
+      CompilationUnit unit, Token beginToken, LineInfo lineInfo,
+      {required bool isPseudoLibraryDirective}) {
     if (beginToken.precedingComments == null) {
       return null;
     }
@@ -301,8 +223,9 @@
     Token? firstComment = beginToken.precedingComments;
     var comment = firstComment;
     var nextComment = comment?.next;
-    // Don't connect comments that have a blank line between them
-    while (comment != null && nextComment != null) {
+    // Don't connect comments that have a blank line between them if this is
+    // a psuedo-library directive.
+    while (isPseudoLibraryDirective && comment != null && nextComment != null) {
       var currentLine = lineInfo.getLocation(comment.offset).lineNumber;
       var nextLine = lineInfo.getLocation(nextComment.offset).lineNumber;
       if (nextLine - currentLine > 1) {
@@ -400,12 +323,7 @@
 class _DirectiveInfo implements Comparable<_DirectiveInfo> {
   final UriBasedDirective directive;
   final _DirectivePriority priority;
-  final String? leadingCommentText;
-  final String? documentationText;
-  final String? annotationText;
-  final String? postAnnotationCommentText;
   final String uri;
-  final String? trailingCommentText;
 
   /// The offset of the first token, usually the keyword but may include leading comments.
   final int offset;
@@ -419,12 +337,7 @@
   _DirectiveInfo(
     this.directive,
     this.priority,
-    this.leadingCommentText,
-    this.documentationText,
-    this.annotationText,
-    this.postAnnotationCommentText,
     this.uri,
-    this.trailingCommentText,
     this.offset,
     this.end,
     this.text,
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 0177328..5a0daa7 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -32,16 +32,12 @@
 
   @override
   void addSource(String path, String content) {
-    if (useLineEndingsForPlatform) {
-      content = normalizeNewlinesForPlatform(content);
-    }
+    content = normalizeSource(content);
     super.addSource(path, content);
   }
 
   void addTestSource(String code) {
-    if (useLineEndingsForPlatform) {
-      code = normalizeNewlinesForPlatform(code);
-    }
+    code = normalizeSource(code);
     testCode = code;
     addSource(testFile, code);
   }
@@ -58,12 +54,15 @@
 
   @override
   File newFile(String path, String content) {
-    if (useLineEndingsForPlatform) {
-      content = normalizeNewlinesForPlatform(content);
-    }
+    content = normalizeSource(content);
     return super.newFile(path, content);
   }
 
+  /// Convenient function to normalize newlines in [code] for the current
+  /// platform if [useLineEndingsForPlatform] is `true`.
+  String normalizeSource(String code) =>
+      useLineEndingsForPlatform ? normalizeNewlinesForPlatform(code) : code;
+
   Future<void> resolveFile2(String path) async {
     var result =
         await (await session).getResolvedUnit(path) as ResolvedUnitResult;
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index 686b25d..3d59aee 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -561,19 +561,25 @@
 ''');
   }
 
-  Future<void>
-      test_sort_imports_dontConnectFirstCommentsWithBlankLinesBetween() async {
+  Future<void> test_sort_imports_blankLinesInImportComments() async {
+    // Only the blank line in the first import is treated specially and split.
     await _computeUnitAndErrors(r'''
-// Copyright...
+// Import 1 comment 1
 
-// Some comment related to the line below
+// Import 1 comment 2
 import 'package:b/a.dart';
+// Import 2 comment 1
+
+// Import 2 comment 2
 import 'package:a/b.dart';''');
     _assertOrganize(r'''
-// Copyright...
+// Import 1 comment 1
 
+// Import 2 comment 1
+
+// Import 2 comment 2
 import 'package:a/b.dart';
-// Some comment related to the line below
+// Import 1 comment 2
 import 'package:b/a.dart';''');
   }
 
@@ -658,7 +664,8 @@
 ''');
   }
 
-  Future<void> test_sort_imports_with_library_keepPrecedingComments() async {
+  Future<void>
+      test_sort_imports_with_library_blankLineInImportComments() async {
     await _computeUnitAndErrors(r'''
 /// Copyright...
 library lib;
@@ -677,11 +684,11 @@
 /// Copyright...
 library lib;
 
-// Test comment
-
 // Comment for a
 
 import 'package:a/b.dart';
+// Test comment
+
 // We are keeping this because ... l1
 // We are keeping this because ... l2
 // We are keeping this because ... l3
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
index 4fa30e3..010d536 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
@@ -7,7 +7,6 @@
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show RefactoringProblemSeverity, SourceChange, SourceEdit;
 import 'package:test/test.dart';
@@ -39,9 +38,7 @@
   /// Asserts that [refactoringChange] contains a [FileEdit] for the file
   /// with the given [path], and it results the [expectedCode].
   void assertFileChangeResult(String path, String expectedCode) {
-    if (useLineEndingsForPlatform) {
-      expectedCode = normalizeNewlinesForPlatform(expectedCode);
-    }
+    expectedCode = normalizeSource(expectedCode);
     // prepare FileEdit
     var fileEdit = refactoringChange.getFileEdit(convertPath(path));
     if (fileEdit == null) {
@@ -120,9 +117,7 @@
   /// Asserts that [refactoringChange] contains a [FileEdit] for [testFile], and
   /// it results the [expectedCode].
   void assertTestChangeResult(String expectedCode) {
-    if (useLineEndingsForPlatform) {
-      expectedCode = normalizeNewlinesForPlatform(expectedCode);
-    }
+    expectedCode = normalizeSource(expectedCode);
     // prepare FileEdit
     var fileEdit = refactoringChange.getFileEdit(testFile);
     if (fileEdit == null) {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
index 96a9ead..cd65f80 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
@@ -37,9 +37,7 @@
 
   @override
   void addTestSource(String code) {
-    if (useLineEndingsForPlatform) {
-      code = normalizeNewlinesForPlatform(code);
-    }
+    code = normalizeSource(code);
     final eol = code.contains('\r\n') ? '\r\n' : '\n';
     var offset = code.indexOf('/*caret*/');
     if (offset >= 0) {
@@ -122,9 +120,7 @@
   /// given [snippet] which produces the [expected] code when applied to [testCode].
   Future<void> assertHasAssistAt(String snippet, String expected,
       {int length = 0}) async {
-    if (useLineEndingsForPlatform) {
-      expected = normalizeNewlinesForPlatform(expected);
-    }
+    expected = normalizeSource(expected);
     _offset = findOffset(snippet);
     _length = length;
     var assist = await _assertHasAssist();
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
index f8ac287..7ad2c40 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
@@ -142,7 +142,10 @@
 
     var assist = await assertHasAssist(expected);
 
-    expect(assist.selection!.offset, expected.indexOf('child: '));
+    expect(
+      assist.selection!.offset,
+      normalizeSource(expected).indexOf('child: '),
+    );
     expect(assist.selectionLength, 0);
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
index 3f9c655..e6dfe49 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_generic_test.dart
@@ -53,7 +53,7 @@
     var editGroup = assist.linkedEditGroups.first;
     expect(editGroup.length, 'widget'.length);
     var pos = editGroup.positions.single;
-    expect(pos.offset, expected.indexOf('widget('));
+    expect(pos.offset, normalizeSource(expected).indexOf('widget('));
   }
 
   Future<void> test_minimal() async {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index c0f1f6e..111c333 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -11,7 +11,6 @@
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
-import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -162,9 +161,7 @@
     var fileEdits = fix.change.edits;
     expect(fileEdits, hasLength(1));
 
-    if (useLineEndingsForPlatform) {
-      expected = normalizeNewlinesForPlatform(expected);
-    }
+    expected = normalizeSource(expected);
 
     var fileContent = testCode;
     resultCode = SourceEdit.applySequence(fileContent, fileEdits[0].edits);
@@ -256,9 +253,7 @@
       int? expectedNumberOfFixesForKind,
       String? matchFixMessage,
       bool allowFixAllFixes = false}) async {
-    if (useLineEndingsForPlatform) {
-      expected = normalizeNewlinesForPlatform(expected);
-    }
+    expected = normalizeSource(expected);
     var error = await _findErrorToFix(
       errorFilter: errorFilter,
       length: length,
@@ -285,9 +280,7 @@
 
   Future<void> assertHasFixAllFix(ErrorCode errorCode, String expected,
       {String? target}) async {
-    if (useLineEndingsForPlatform) {
-      expected = normalizeNewlinesForPlatform(expected);
-    }
+    expected = normalizeSource(expected);
     var error = await _findErrorToFixOfType(errorCode);
     var fix = await _assertHasFixAllFix(error);
     change = fix.change;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 2dec46a..17ed8d6 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1135,11 +1135,9 @@
 
   R? visitConstructorElement(ConstructorElement element);
 
-  @Deprecated('Override visitExportElement2() instead')
+  @Deprecated('Override visitLibraryExportElement() instead')
   R? visitExportElement(ExportElement element);
 
-  R? visitExportElement2(LibraryExportElement element);
-
   R? visitExtensionElement(ExtensionElement element);
 
   R? visitFieldElement(FieldElement element);
@@ -1150,17 +1148,19 @@
 
   R? visitGenericFunctionTypeElement(GenericFunctionTypeElement element);
 
-  @Deprecated('Override visitImportElement2() instead')
+  @Deprecated('Override visitLibraryImportElement() instead')
   R? visitImportElement(ImportElement element);
 
-  R? visitImportElement2(LibraryImportElement element);
-
   R? visitLabelElement(LabelElement element);
 
   R? visitLibraryAugmentationElement(LibraryAugmentationElement element);
 
   R? visitLibraryElement(LibraryElement element);
 
+  R? visitLibraryExportElement(LibraryExportElement element);
+
+  R? visitLibraryImportElement(LibraryImportElement element);
+
   R? visitLocalVariableElement(LocalVariableElement element);
 
   R? visitMethodElement(MethodElement element);
diff --git a/pkg/analyzer/lib/dart/element/visitor.dart b/pkg/analyzer/lib/dart/element/visitor.dart
index 7beaa7c..2ec106e 100644
--- a/pkg/analyzer/lib/dart/element/visitor.dart
+++ b/pkg/analyzer/lib/dart/element/visitor.dart
@@ -104,14 +104,11 @@
 
   R? visitExecutableElement(ExecutableElement element) => visitElement(element);
 
-  @Deprecated('Override visitExportElement2() instead')
+  @Deprecated('Override visitLibraryExportElement() instead')
   @override
   R? visitExportElement(ExportElement element) => visitElement(element);
 
   @override
-  R? visitExportElement2(LibraryExportElement element) => visitElement(element);
-
-  @override
   R? visitExtensionElement(ExtensionElement element) => visitElement(element);
 
   @override
@@ -130,14 +127,11 @@
   R? visitGenericFunctionTypeElement(GenericFunctionTypeElement element) =>
       visitElement(element);
 
-  @Deprecated('Override visitImportElement2() instead')
+  @Deprecated('Override visitLibraryImportElement() instead')
   @override
   R? visitImportElement(ImportElement element) => visitElement(element);
 
   @override
-  R? visitImportElement2(LibraryImportElement element) => visitElement(element);
-
-  @override
   R? visitLabelElement(LabelElement element) => visitElement(element);
 
   @override
@@ -147,6 +141,14 @@
   @override
   R? visitLibraryElement(LibraryElement element) => visitElement(element);
 
+  @override
+  R? visitLibraryExportElement(LibraryExportElement element) =>
+      visitElement(element);
+
+  @override
+  R? visitLibraryImportElement(LibraryImportElement element) =>
+      visitElement(element);
+
   R? visitLocalElement(LocalElement element) {
     if (element is LocalVariableElement) {
       return visitVariableElement(element);
@@ -244,7 +246,7 @@
     return null;
   }
 
-  @Deprecated('Override visitExportElement2() instead')
+  @Deprecated('Override visitLibraryExportElement() instead')
   @override
   R? visitExportElement(ExportElement element) {
     element.visitChildren(this);
@@ -252,12 +254,6 @@
   }
 
   @override
-  R? visitExportElement2(LibraryExportElement element) {
-    element.visitChildren(this);
-    return null;
-  }
-
-  @override
   R? visitExtensionElement(ExtensionElement element) {
     element.visitChildren(this);
     return null;
@@ -287,7 +283,7 @@
     return null;
   }
 
-  @Deprecated('Override visitImportElement2() instead')
+  @Deprecated('Override visitLibraryImportElement() instead')
   @override
   R? visitImportElement(ImportElement element) {
     element.visitChildren(this);
@@ -295,12 +291,6 @@
   }
 
   @override
-  R? visitImportElement2(LibraryImportElement element) {
-    element.visitChildren(this);
-    return null;
-  }
-
-  @override
   R? visitLabelElement(LabelElement element) {
     element.visitChildren(this);
     return null;
@@ -319,6 +309,18 @@
   }
 
   @override
+  R? visitLibraryExportElement(LibraryExportElement element) {
+    element.visitChildren(this);
+    return null;
+  }
+
+  @override
+  R? visitLibraryImportElement(LibraryImportElement element) {
+    element.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitLocalVariableElement(LocalVariableElement element) {
     element.visitChildren(this);
     return null;
@@ -407,14 +409,11 @@
   @override
   R? visitConstructorElement(ConstructorElement element) => null;
 
-  @Deprecated('Override visitExportElement2() instead')
+  @Deprecated('Override visitLibraryExportElement() instead')
   @override
   R? visitExportElement(ExportElement element) => null;
 
   @override
-  R? visitExportElement2(LibraryExportElement element) => null;
-
-  @override
   R? visitExtensionElement(ExtensionElement element) => null;
 
   @override
@@ -431,14 +430,11 @@
   R? visitGenericFunctionTypeElement(GenericFunctionTypeElement element) =>
       null;
 
-  @Deprecated('Override visitImportElement2() instead')
+  @Deprecated('Override visitLibraryImportElement() instead')
   @override
   R? visitImportElement(ImportElement element) => null;
 
   @override
-  R? visitImportElement2(LibraryImportElement element) => null;
-
-  @override
   R? visitLabelElement(LabelElement element) => null;
 
   @override
@@ -449,6 +445,12 @@
   R? visitLibraryElement(LibraryElement element) => null;
 
   @override
+  R? visitLibraryExportElement(LibraryExportElement element) => null;
+
+  @override
+  R? visitLibraryImportElement(LibraryImportElement element) => null;
+
+  @override
   R? visitLocalVariableElement(LocalVariableElement element) => null;
 
   @override
@@ -508,14 +510,11 @@
   @override
   R? visitConstructorElement(ConstructorElement element) => _throw(element);
 
-  @Deprecated('Override visitExportElement2() instead')
+  @Deprecated('Override visitLibraryExportElement() instead')
   @override
   R? visitExportElement(ExportElement element) => _throw(element);
 
   @override
-  R? visitExportElement2(LibraryExportElement element) => _throw(element);
-
-  @override
   R? visitExtensionElement(ExtensionElement element) => _throw(element);
 
   @override
@@ -532,14 +531,11 @@
   R? visitGenericFunctionTypeElement(GenericFunctionTypeElement element) =>
       _throw(element);
 
-  @Deprecated('Override visitImportElement2() instead')
+  @Deprecated('Override visitLibraryImportElement() instead')
   @override
   R? visitImportElement(ImportElement element) => _throw(element);
 
   @override
-  R? visitImportElement2(LibraryImportElement element) => _throw(element);
-
-  @override
   R? visitLabelElement(LabelElement element) => _throw(element);
 
   @override
@@ -550,6 +546,12 @@
   R? visitLibraryElement(LibraryElement element) => _throw(element);
 
   @override
+  R? visitLibraryExportElement(LibraryExportElement element) => _throw(element);
+
+  @override
+  R? visitLibraryImportElement(LibraryImportElement element) => _throw(element);
+
+  @override
   R? visitLocalVariableElement(LocalVariableElement element) => _throw(element);
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index b2e4b1f..15ea65d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -530,23 +530,12 @@
 
   /// Parse and resolve all files in [_library].
   Map<FileState, CompilationUnitImpl> _parseAndResolve() {
-    // Parse all files.
-    final libraryFile = _library.file;
-    final libraryUnit = _parse(libraryFile);
-    final units = <FileState, CompilationUnitImpl>{
-      libraryFile: libraryUnit,
-    };
-    for (final part in _library.parts) {
-      if (part is PartWithFile) {
-        final partFile = part.includedPart?.file;
-        if (partFile != null) {
-          units[partFile] = _parse(partFile);
-        }
-      }
-    }
-
-    // Resolve URIs in directives to corresponding sources.
-    _resolveDirectives(units, libraryUnit);
+    final units = <FileState, CompilationUnitImpl>{};
+    _resolveDirectives(
+      containerKind: _library,
+      containerElement: _libraryElement,
+      units: units,
+    );
 
     units.forEach((file, unit) {
       _resolveFile(file, unit);
@@ -561,132 +550,160 @@
     required AugmentationImportDirectiveImpl directive,
     required AugmentationImportElement element,
     required AugmentationImportState state,
-    // TODO(scheglov) wrong value, wrong name
-    required ErrorReporter libraryErrorReporter,
+    required ErrorReporter errorReporter,
     required Set<AugmentationFileKind> seenAugmentations,
+    required Map<FileState, CompilationUnitImpl> units,
   }) {
     directive.element = element;
 
-    final primaryUriState = state.uri;
-    if (primaryUriState is DirectiveUriWithString) {
-      directive.uriContent = primaryUriState.relativeUriStr;
-      directive.uriSource = primaryUriState.source;
+    final uriState = state.uri;
+    if (uriState is DirectiveUriWithString) {
+      directive.uriContent = uriState.relativeUriStr;
+      directive.uriSource = uriState.source;
     }
 
+    final AugmentationFileKind? importedAugmentationKind;
     if (state is AugmentationImportWithUri) {
       if (state.importedSource == null) {
         // TODO(scheglov) When do we have a valid URI here and in imports?
         final errorCode = state.uri.isValid
             ? CompileTimeErrorCode.URI_DOES_NOT_EXIST
             : CompileTimeErrorCode.INVALID_URI;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [state.uri.relativeUriStr],
         );
+        return;
       } else if (state is AugmentationImportWithFile) {
-        final importedAugmentation = state.importedAugmentation;
+        importedAugmentationKind = state.importedAugmentation;
         if (!state.importedFile.exists) {
           final errorCode = isGeneratedSource(state.importedSource)
               ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
               : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-          libraryErrorReporter.reportErrorForNode(
+          errorReporter.reportErrorForNode(
             errorCode,
             directive.uri,
             [state.importedFile.uriStr],
           );
-        } else if (importedAugmentation == null) {
-          libraryErrorReporter.reportErrorForNode(
+          return;
+        } else if (importedAugmentationKind == null) {
+          errorReporter.reportErrorForNode(
             CompileTimeErrorCode.IMPORT_OF_NOT_AUGMENTATION,
             directive.uri,
             [state.importedFile.uriStr],
           );
-        } else if (!seenAugmentations.add(importedAugmentation)) {
-          libraryErrorReporter.reportErrorForNode(
+          return;
+        } else if (!seenAugmentations.add(importedAugmentationKind)) {
+          errorReporter.reportErrorForNode(
             CompileTimeErrorCode.DUPLICATE_AUGMENTATION_IMPORT,
             directive.uri,
             [state.importedFile.uriStr],
           );
+          return;
         }
+      } else {
+        return;
       }
     } else {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         CompileTimeErrorCode.URI_WITH_INTERPOLATION,
         directive.uri,
       );
+      return;
     }
-  }
 
-  void _resolveDirectives(
-    Map<FileState, CompilationUnitImpl> units,
-    CompilationUnitImpl libraryUnit,
-  ) {
-    libraryUnit.element = _libraryElement.definingCompilationUnit;
+    final augmentationFile = importedAugmentationKind.file;
+    final augmentationUnit = _parse(augmentationFile);
+    units[augmentationFile] = augmentationUnit;
 
-    ErrorReporter libraryErrorReporter = _getErrorReporter(_library.file);
+    final importedAugmentation = element.importedAugmentation!;
+    directive.uriSource = importedAugmentation.source;
+    augmentationUnit.element = importedAugmentation.definingCompilationUnit;
 
-    var augmentationImportIndex = 0;
-    var libraryImportIndex = 0;
-    var libraryExportIndex = 0;
-
-    LibraryIdentifier? libraryNameNode;
-    final seenAugmentations = <AugmentationFileKind>{};
-    var seenPartSources = <Source>{};
-    var directivesToResolve = <DirectiveImpl>[];
-    final partIndexes = _PartDirectiveIndexes();
-    for (Directive directive in libraryUnit.directives) {
-      if (directive is LibraryDirectiveImpl) {
-        libraryNameNode = directive.name;
-        directivesToResolve.add(directive);
-      } else if (directive is AugmentationImportDirectiveImpl) {
-        final index = augmentationImportIndex++;
-        _resolveAugmentationImportDirective(
-          directive: directive,
-          // TODO(scheglov) Not only in the library.
-          element: _libraryElement.augmentationImports[index],
-          // TODO(scheglov) Not only in the library.
-          state: _library.augmentationImports[index],
-          // TODO(scheglov) Not only in the library.
-          libraryErrorReporter: libraryErrorReporter,
-          seenAugmentations: seenAugmentations,
-        );
-      } else if (directive is ImportDirectiveImpl) {
-        _resolveLibraryImportDirective(
-          directive: directive,
-          importElement: _libraryElement.libraryImports[libraryImportIndex],
-          importState: _library.libraryImports[libraryImportIndex],
-          libraryErrorReporter: libraryErrorReporter,
-        );
-        libraryImportIndex++;
-      } else if (directive is ExportDirectiveImpl) {
-        _resolveLibraryExportDirective(
-          directive: directive,
-          exportElement: _libraryElement.libraryExports[libraryExportIndex],
-          exportState: _library.libraryExports[libraryExportIndex],
-          libraryErrorReporter: libraryErrorReporter,
-        );
-        libraryExportIndex++;
-      } else if (directive is PartDirectiveImpl) {
-        _resolvePartDirective(
-          directive: directive,
-          partIndexes: partIndexes,
-          libraryErrorReporter: libraryErrorReporter,
-          libraryNameNode: libraryNameNode,
-          units: units,
-          directivesToResolve: directivesToResolve,
-          seenPartSources: seenPartSources,
-        );
+    for (final directive in augmentationUnit.directives) {
+      if (directive is AugmentationImportDirectiveImpl) {
+        directive.element = importedAugmentation;
       }
     }
 
-    // TODO(brianwilkerson) Report the error
-    // ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART
+    _resolveDirectives(
+      containerKind: importedAugmentationKind,
+      containerElement: importedAugmentation,
+      units: units,
+    );
+  }
 
-    //
-    // Resolve the relevant directives to the library element.
-    //
-    for (var directive in directivesToResolve) {
-      directive.element = _libraryElement;
+  /// Parses the file of [containerKind], and resolves directives.
+  /// Recursively parses augmentations and parts.
+  void _resolveDirectives({
+    required LibraryOrAugmentationFileKind containerKind,
+    required LibraryOrAugmentationElement containerElement,
+    required Map<FileState, CompilationUnitImpl> units,
+  }) {
+    final containerFile = containerKind.file;
+    final containerUnit = _parse(containerFile);
+    containerUnit.element = containerElement.definingCompilationUnit;
+    units[containerFile] = containerUnit;
+
+    final containerErrorReporter = _getErrorReporter(containerFile);
+
+    var augmentationImportIndex = 0;
+    var libraryExportIndex = 0;
+    var libraryImportIndex = 0;
+    var partIndex = 0;
+
+    LibraryIdentifier? libraryNameNode;
+    final seenAugmentations = <AugmentationFileKind>{};
+    final seenPartSources = <Source>{};
+    for (Directive directive in containerUnit.directives) {
+      if (directive is AugmentationImportDirectiveImpl) {
+        final index = augmentationImportIndex++;
+        _resolveAugmentationImportDirective(
+          directive: directive,
+          element: containerElement.augmentationImports[index],
+          state: containerKind.augmentationImports[index],
+          errorReporter: containerErrorReporter,
+          seenAugmentations: seenAugmentations,
+          units: units,
+        );
+      } else if (directive is ExportDirectiveImpl) {
+        final index = libraryExportIndex++;
+        _resolveLibraryExportDirective(
+          directive: directive,
+          exportElement: containerElement.libraryExports[index],
+          exportState: containerKind.libraryExports[index],
+          errorReporter: containerErrorReporter,
+        );
+      } else if (directive is ImportDirectiveImpl) {
+        final index = libraryImportIndex++;
+        _resolveLibraryImportDirective(
+          directive: directive,
+          importElement: containerElement.libraryImports[index],
+          importState: containerKind.libraryImports[index],
+          errorReporter: containerErrorReporter,
+        );
+      } else if (directive is LibraryAugmentationDirectiveImpl) {
+        // TODO(scheglov) test
+        directive.element = containerElement;
+      } else if (directive is LibraryDirectiveImpl) {
+        directive.element = containerElement;
+        libraryNameNode = directive.name;
+      } else if (directive is PartDirectiveImpl) {
+        if (containerKind is LibraryFileKind &&
+            containerElement is LibraryElementImpl) {
+          final index = partIndex++;
+          _resolvePartDirective(
+            directive: directive,
+            partState: containerKind.parts[index],
+            partElement: containerElement.parts2[index],
+            errorReporter: containerErrorReporter,
+            libraryNameNode: libraryNameNode,
+            units: units,
+            seenPartSources: seenPartSources,
+          );
+        }
+      }
     }
   }
 
@@ -732,7 +749,7 @@
     required ExportDirectiveImpl directive,
     required LibraryExportElement exportElement,
     required LibraryExportState exportState,
-    required ErrorReporter libraryErrorReporter,
+    required ErrorReporter errorReporter,
   }) {
     directive.element = exportElement;
     _resolveNamespaceDirective(
@@ -746,7 +763,7 @@
     if (exportState is LibraryExportWithUri) {
       final selectedUriStr = exportState.selectedUri.relativeUriStr;
       if (selectedUriStr.startsWith('dart-ext:')) {
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
           directive.uri,
         );
@@ -754,7 +771,7 @@
         final errorCode = exportState.selectedUri.isValid
             ? CompileTimeErrorCode.URI_DOES_NOT_EXIST
             : CompileTimeErrorCode.INVALID_URI;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [selectedUriStr],
@@ -764,20 +781,20 @@
         final errorCode = isGeneratedSource(exportState.exportedSource)
             ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
             : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [selectedUriStr],
         );
       } else if (exportState.exportedLibrarySource == null) {
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
           directive.uri,
           [selectedUriStr],
         );
       }
     } else {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         CompileTimeErrorCode.URI_WITH_INTERPOLATION,
         directive.uri,
       );
@@ -788,7 +805,7 @@
     required ImportDirectiveImpl directive,
     required LibraryImportElement importElement,
     required LibraryImportState importState,
-    required ErrorReporter libraryErrorReporter,
+    required ErrorReporter errorReporter,
   }) {
     directive.element = importElement;
     directive.prefix?.staticElement = importElement.prefix?.element;
@@ -803,7 +820,7 @@
     if (importState is LibraryImportWithUri) {
       final selectedUriStr = importState.selectedUri.relativeUriStr;
       if (selectedUriStr.startsWith('dart-ext:')) {
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
           directive.uri,
         );
@@ -811,7 +828,7 @@
         final errorCode = importState.selectedUri.isValid
             ? CompileTimeErrorCode.URI_DOES_NOT_EXIST
             : CompileTimeErrorCode.INVALID_URI;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [selectedUriStr],
@@ -821,20 +838,20 @@
         final errorCode = isGeneratedSource(importState.importedSource)
             ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
             : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [selectedUriStr],
         );
       } else if (importState.importedLibrarySource == null) {
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
           directive.uri,
           [selectedUriStr],
         );
       }
     } else {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         CompileTimeErrorCode.URI_WITH_INTERPOLATION,
         directive.uri,
       );
@@ -868,25 +885,20 @@
 
   void _resolvePartDirective({
     required PartDirectiveImpl directive,
-    required _PartDirectiveIndexes partIndexes,
-    required ErrorReporter libraryErrorReporter,
+    required PartState partState,
+    required PartElement partElement,
+    required ErrorReporter errorReporter,
     required LibraryIdentifier? libraryNameNode,
     required Map<FileState, CompilationUnitImpl> units,
-    required List<DirectiveImpl> directivesToResolve,
     required Set<Source> seenPartSources,
   }) {
     StringLiteral partUri = directive.uri;
 
-    final index = partIndexes.directive++;
-
-    final partState = _library.parts[index];
     directive.uriSource = partState.includedSource;
-
-    final partElement = _libraryElement.parts2[index];
     directive.element = partElement;
 
     if (partState is! PartWithUri) {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         CompileTimeErrorCode.URI_WITH_INTERPOLATION,
         directive.uri,
       );
@@ -897,7 +909,7 @@
       final errorCode = partState.uri.isValid
           ? CompileTimeErrorCode.URI_DOES_NOT_EXIST
           : CompileTimeErrorCode.INVALID_URI;
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         errorCode,
         directive.uri,
         [partState.uri.relativeUriStr],
@@ -909,7 +921,7 @@
 
     if (includedKind is! PartFileKind) {
       if (includedFile.exists) {
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           CompileTimeErrorCode.PART_OF_NON_PART,
           partUri,
           [partUri.toSource()],
@@ -918,7 +930,7 @@
         final errorCode = isGeneratedSource(includedFile.source)
             ? CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED
             : CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-        libraryErrorReporter.reportErrorForNode(
+        errorReporter.reportErrorForNode(
           errorCode,
           directive.uri,
           [partUri.toSource()],
@@ -931,13 +943,13 @@
       if (!includedKind.libraries.contains(_library)) {
         final name = includedKind.unlinked.name;
         if (libraryNameNode == null) {
-          libraryErrorReporter.reportErrorForNode(
+          errorReporter.reportErrorForNode(
             CompileTimeErrorCode.PART_OF_UNNAMED_LIBRARY,
             partUri,
             [name],
           );
         } else {
-          libraryErrorReporter.reportErrorForNode(
+          errorReporter.reportErrorForNode(
             CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
             partUri,
             [libraryNameNode.name, name],
@@ -946,7 +958,7 @@
         return;
       }
     } else if (includedKind.library != _library) {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
         CompileTimeErrorCode.PART_OF_DIFFERENT_LIBRARY,
         partUri,
         [_library.file.uriStr, includedFile.uriStr],
@@ -954,7 +966,9 @@
       return;
     }
 
-    var partUnit = units[includedFile]!;
+    final partUnit = _parse(includedFile);
+    units[includedFile] = partUnit;
+
     final partElementUri = partElement.uri;
     if (partElementUri is DirectiveUriWithUnit) {
       partUnit.element = partElementUri.unit;
@@ -965,7 +979,7 @@
 
     for (final directive in partUnit.directives) {
       if (directive is PartOfDirectiveImpl) {
-        directivesToResolve.add(directive);
+        directive.element = _libraryElement;
       }
     }
 
@@ -973,7 +987,7 @@
     // Validate that the part source is unique in the library.
     //
     if (!seenPartSources.add(partSource)) {
-      libraryErrorReporter.reportErrorForNode(
+      errorReporter.reportErrorForNode(
           CompileTimeErrorCode.DUPLICATE_PART, partUri, [partSource.uri]);
     }
   }
@@ -1075,8 +1089,3 @@
 
   UnitAnalysisResult(this.file, this.unit, this.errors);
 }
-
-class _PartDirectiveIndexes {
-  int directive = 0;
-  int element = 0;
-}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index b0018c9..e8b91a4 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3812,6 +3812,7 @@
     ..addToken('exportKeyword', exportKeyword)
     ..addNode('uri', uri)
     ..addNodeList('combinators', combinators)
+    ..addNodeList('configurations', configurations)
     ..addToken('semicolon', semicolon);
 
   @override
@@ -6471,6 +6472,7 @@
     ..addToken('asKeyword', asKeyword)
     ..addNode('prefix', prefix)
     ..addNodeList('combinators', combinators)
+    ..addNodeList('configurations', configurations)
     ..addToken('semicolon', semicolon);
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 4a90b77..2f13dee 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4434,7 +4434,7 @@
 
   @override
   T? accept<T>(ElementVisitor<T> visitor) {
-    return visitor.visitExportElement2(this);
+    return visitor.visitLibraryExportElement(this);
   }
 
   @override
@@ -4502,7 +4502,7 @@
 
   @override
   T? accept<T>(ElementVisitor<T> visitor) {
-    return visitor.visitImportElement2(this);
+    return visitor.visitLibraryImportElement(this);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index bc8a8d3..634506e 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -266,6 +266,10 @@
     }
   }
 
+  void visitLibraryAugmentationDirective(LibraryAugmentationDirective node) {
+    _resolveAnnotations(node.metadata);
+  }
+
   void visitLibraryDirective(LibraryDirective node) {
     _resolveAnnotations(node.metadata);
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d7408ef..9a01970 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1891,6 +1891,13 @@
   }
 
   @override
+  void visitLibraryAugmentationDirective(LibraryAugmentationDirective node) {
+    checkUnreachableNode(node);
+    node.visitChildren(this);
+    elementResolver.visitLibraryAugmentationDirective(node);
+  }
+
+  @override
   void visitLibraryDirective(LibraryDirective node) {
     checkUnreachableNode(node);
     node.visitChildren(this);
diff --git a/pkg/analyzer/test/src/dart/resolution/augmentation_import_test.dart b/pkg/analyzer/test/src/dart/resolution/augmentation_import_test.dart
index 1457bd4..8cfd850 100644
--- a/pkg/analyzer/test/src/dart/resolution/augmentation_import_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/augmentation_import_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'context_collection_resolution.dart';
@@ -15,12 +16,181 @@
 @reflectiveTest
 class AugmentationImportDirectiveResolutionTest
     extends PubPackageResolutionTest {
-  test_augmentation() async {
+  test_inAugmentation_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import augment 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+library augment 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertNoErrorsInResult();
+
+    final node = findNode.augmentationImportDirective('c.dart');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithAugmentation
+      uri: package:test/c.dart
+  uriContent: c.dart
+  uriElement: package:test/a.dart::@augmentation::package:test/c.dart
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_augmentation_duplicate() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import augment 'c.dart';
+import augment 'c.dart' /*2*/;
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+library augment 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.DUPLICATE_AUGMENTATION_IMPORT, 66, 8),
+    ]);
+
+    final node = findNode.augmentationImportDirective('/*2*/');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithAugmentation
+      uri: package:test/c.dart
+  uriContent: c.dart
+  uriElement: package:test/a.dart::@augmentation::package:test/c.dart
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notAugmentation_invalidUri() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import augment 'da:';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.INVALID_URI, 41, 5),
+    ]);
+
+    final node = findNode.augmentationImportDirective('da:');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'da:'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithRelativeUri
+      relativeUri: da:
+  uriContent: da:
+  uriElement: <null>
+  uriSource: <null>
+''');
+  }
+
+  test_inAugmentation_notAugmentation_library() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import augment 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', '');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.IMPORT_OF_NOT_AUGMENTATION, 41, 8),
+    ]);
+
+    final node = findNode.augmentationImportDirective('c.dart');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notAugmentation_uriDoesNotExist() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import augment 'c.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 41, 8),
+    ]);
+
+    final node = findNode.augmentationImportDirective('c.dart');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inLibrary_augmentation() async {
     newFile('$testPackageLibPath/a.dart', r'''
 library augment 'test.dart';
 ''');
 
-    await resolveTestCode(r'''
+    await assertNoErrorsInCode(r'''
 import augment 'a.dart';
 ''');
 
@@ -41,12 +211,43 @@
 ''');
   }
 
-  test_library() async {
+  test_inLibrary_augmentation_duplicate() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+
+    await assertErrorsInCode(r'''
+import augment 'a.dart';
+import augment /*2*/ 'a.dart';
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_AUGMENTATION_IMPORT, 46, 8),
+    ]);
+
+    final node = findNode.augmentationImportDirective('/*2*/');
+    assertResolvedNodeText(node, r'''
+AugmentationImportDirective
+  importKeyword: import
+  augmentKeyword: augment
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: AugmentationImportElement
+    uri: DirectiveUriWithAugmentation
+      uri: package:test/a.dart
+  uriContent: a.dart
+  uriElement: self::@augmentation::package:test/a.dart
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_notAugmentation_library() async {
     newFile('$testPackageLibPath/a.dart', '');
 
-    await resolveTestCode(r'''
+    await assertErrorsInCode(r'''
 import augment 'a.dart';
-''');
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NOT_AUGMENTATION, 15, 8),
+    ]);
 
     final node = findNode.augmentationImportDirective('a.dart');
     assertResolvedNodeText(node, r'''
@@ -65,14 +266,16 @@
 ''');
   }
 
-  test_partOfName() async {
+  test_inLibrary_notAugmentation_partOfName() async {
     newFile('$testPackageLibPath/a.dart', r'''
 part of my.lib;
 ''');
 
-    await resolveTestCode(r'''
+    await assertErrorsInCode(r'''
 import augment 'a.dart';
-''');
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NOT_AUGMENTATION, 15, 8),
+    ]);
 
     final node = findNode.augmentationImportDirective('a.dart');
     assertResolvedNodeText(node, r'''
@@ -91,14 +294,16 @@
 ''');
   }
 
-  test_partOfUri() async {
+  test_inLibrary_notAugmentation_partOfUri() async {
     newFile('$testPackageLibPath/a.dart', r'''
 part of 'test.dart';
 ''');
 
-    await resolveTestCode(r'''
+    await assertErrorsInCode(r'''
 import augment 'a.dart';
-''');
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NOT_AUGMENTATION, 15, 8),
+    ]);
 
     final node = findNode.augmentationImportDirective('a.dart');
     assertResolvedNodeText(node, r'''
diff --git a/pkg/analyzer/test/src/dart/resolution/export_test.dart b/pkg/analyzer/test/src/dart/resolution/export_test.dart
deleted file mode 100644
index 50965c1..0000000
--- a/pkg/analyzer/test/src/dart/resolution/export_test.dart
+++ /dev/null
@@ -1,115 +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:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ExportResolutionTest);
-  });
-}
-
-@reflectiveTest
-class ExportResolutionTest extends PubPackageResolutionTest {
-  test_configurations_default() async {
-    newFile('$testPackageLibPath/a.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
-
-    declaredVariables = {
-      'dart.library.html': 'false',
-      'dart.library.io': 'false',
-    };
-
-    await assertNoErrorsInCode(r'''
-export 'a.dart'
-  if (dart.library.html) 'a_html.dart'
-  if (dart.library.io) 'a_io.dart';
-''');
-
-    assertNamespaceDirectiveSelected(
-      findNode.export('a.dart'),
-      expectedRelativeUri: 'a.dart',
-      expectedUri: 'package:test/a.dart',
-    );
-
-    assertElementLibraryUri(
-      result.libraryElement.exportNamespace.get('A'),
-      'package:test/a.dart',
-    );
-  }
-
-  test_configurations_first() async {
-    newFile('$testPackageLibPath/a.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
-
-    declaredVariables = {
-      'dart.library.html': 'true',
-      'dart.library.io': 'false',
-    };
-
-    await assertNoErrorsInCode(r'''
-export 'a.dart'
-  if (dart.library.html) 'a_html.dart'
-  if (dart.library.io) 'a_io.dart';
-''');
-
-    assertNamespaceDirectiveSelected(
-      findNode.export('a.dart'),
-      expectedRelativeUri: 'a_html.dart',
-      expectedUri: 'package:test/a_html.dart',
-    );
-
-    assertElementLibraryUri(
-      result.libraryElement.exportNamespace.get('A'),
-      'package:test/a_html.dart',
-    );
-  }
-
-  test_configurations_second() async {
-    newFile('$testPackageLibPath/a.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
-    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
-
-    declaredVariables = {
-      'dart.library.html': 'false',
-      'dart.library.io': 'true',
-    };
-
-    await assertNoErrorsInCode(r'''
-export 'a.dart'
-  if (dart.library.html) 'a_html.dart'
-  if (dart.library.io) 'a_io.dart';
-''');
-
-    assertNamespaceDirectiveSelected(
-      findNode.export('a.dart'),
-      expectedRelativeUri: 'a_io.dart',
-      expectedUri: 'package:test/a_io.dart',
-    );
-
-    assertElementLibraryUri(
-      result.libraryElement.exportNamespace.get('A'),
-      'package:test/a_io.dart',
-    );
-  }
-
-  /// Test that both getter and setter are in the export namespace.
-  test_namespace_getter_setter() async {
-    newFile('$testPackageLibPath/a.dart', r'''
-get f => null;
-set f(_) {}
-''');
-    await resolveTestCode(r'''
-export 'a.dart';
-''');
-    var exportNamespace = result.libraryElement.exportNamespace;
-    expect(exportNamespace.get('f'), isNotNull);
-    expect(exportNamespace.get('f='), isNotNull);
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/resolution/library_export_test.dart b/pkg/analyzer/test/src/dart/resolution/library_export_test.dart
new file mode 100644
index 0000000..d1116c0
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/library_export_test.dart
@@ -0,0 +1,548 @@
+// 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/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExportDirectiveResolutionTest);
+  });
+}
+
+@reflectiveTest
+class ExportDirectiveResolutionTest extends PubPackageResolutionTest {
+  test_inAugmentation_library() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+export 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', '');
+
+    await resolveFile2(b.path);
+    assertNoErrorsInResult();
+
+    final node = findNode.export('c.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: package:test/c.dart
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+export 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+library augment 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.export('c.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_partOfName() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+export 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+part of my.lib;
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.export('c.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_partOfUri() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+export 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+part of 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.export('c.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inLibrary_configurations_default() async {
+    newFile('$testPackageLibPath/a.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
+
+    declaredVariables = {
+      'dart.library.html': 'false',
+      'dart.library.io': 'false',
+    };
+
+    await assertNoErrorsInCode(r'''
+export 'a.dart'
+  if (dart.library.html) 'a_html.dart'
+  if (dart.library.io) 'a_io.dart';
+''');
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  configurations
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: html
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_html.dart'
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: io
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_io.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: package:test/a.dart
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_configurations_first() async {
+    newFile('$testPackageLibPath/a.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
+
+    declaredVariables = {
+      'dart.library.html': 'true',
+      'dart.library.io': 'false',
+    };
+
+    await assertNoErrorsInCode(r'''
+export 'a.dart'
+  if (dart.library.html) 'a_html.dart'
+  if (dart.library.io) 'a_io.dart';
+''');
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  configurations
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: html
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_html.dart'
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: io
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_io.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/a_html.dart
+  selectedSource: package:test/a_html.dart
+  selectedUriContent: a_html.dart
+  uriContent: a.dart
+  uriElement: package:test/a_html.dart
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_configurations_second() async {
+    newFile('$testPackageLibPath/a.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_html.dart', 'class A {}');
+    newFile('$testPackageLibPath/a_io.dart', 'class A {}');
+
+    declaredVariables = {
+      'dart.library.html': 'false',
+      'dart.library.io': 'true',
+    };
+
+    await assertNoErrorsInCode(r'''
+export 'a.dart'
+  if (dart.library.html) 'a_html.dart'
+  if (dart.library.io) 'a_io.dart';
+''');
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  configurations
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: html
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_html.dart'
+    Configuration
+      ifKeyword: if
+      leftParenthesis: (
+      name: DottedName
+        components
+          SimpleIdentifier
+            token: dart
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: library
+            staticElement: <null>
+            staticType: null
+          SimpleIdentifier
+            token: io
+            staticElement: <null>
+            staticType: null
+      rightParenthesis: )
+      uri: SimpleStringLiteral
+        literal: 'a_io.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/a_io.dart
+  selectedSource: package:test/a_io.dart
+  selectedUriContent: a_io.dart
+  uriContent: a.dart
+  uriElement: package:test/a_io.dart
+  uriSource: package:test/a.dart
+''');
+  }
+
+  /// Test that both getter and setter are in the export namespace.
+  test_inLibrary_namespace_getter_setter() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+get f => null;
+set f(_) {}
+''');
+    await resolveTestCode(r'''
+export 'a.dart';
+''');
+    var exportNamespace = result.libraryElement.exportNamespace;
+    expect(exportNamespace.get('f'), isNotNull);
+    expect(exportNamespace.get('f='), isNotNull);
+  }
+
+  test_inLibrary_noRelativeUriStr() async {
+    await assertErrorsInCode(r'''
+export '${'foo'}.dart';
+''', [
+      error(CompileTimeErrorCode.URI_WITH_INTERPOLATION, 7, 15),
+    ]);
+
+    final node = findNode.export('export');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: StringInterpolation
+    elements
+      InterpolationString
+        contents: '
+      InterpolationExpression
+        leftBracket: ${
+        expression: SimpleStringLiteral
+          literal: 'foo'
+        rightBracket: }
+      InterpolationString
+        contents: .dart'
+    staticType: String
+    stringValue: null
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUri
+  selectedSource: <null>
+  selectedUriContent: null
+  uriContent: null
+  uriElement: <null>
+  uriSource: <null>
+''');
+  }
+
+  test_inLibrary_noSource() async {
+    await assertErrorsInCode(r'''
+export 'foo:bar';
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 9),
+    ]);
+
+    final node = findNode.export('export');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'foo:bar'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithRelativeUri
+      relativeUri: foo:bar
+  selectedSource: <null>
+  selectedUriContent: foo:bar
+  uriContent: foo:bar
+  uriElement: <null>
+  uriSource: <null>
+''');
+  }
+
+  test_inLibrary_notLibrary_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+
+    await assertErrorsInCode(r'''
+export 'a.dart';
+''', [
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_notLibrary_partOfName() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+part of my.lib;
+''');
+
+    await assertErrorsInCode(r'''
+export 'a.dart';
+''', [
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_notLibrary_partOfUri() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+part of 'test.dart';
+''');
+
+    await assertErrorsInCode(r'''
+export 'a.dart';
+''', [
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.export('a.dart');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/library_import_test.dart b/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
index d52aea9..1dbaafc 100644
--- a/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'context_collection_resolution.dart';
@@ -14,7 +15,153 @@
 
 @reflectiveTest
 class ImportDirectiveResolutionTest extends PubPackageResolutionTest {
-  test_configurations_default() async {
+  test_inAugmentation_library() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', '');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(HintCode.UNUSED_IMPORT, 33, 8),
+    ]);
+
+    final node = findNode.import('c.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: package:test/c.dart
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+library augment 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.import('c.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_partOfName() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+part of my.lib;
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.import('c.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inAugmentation_notLibrary_partOfUri() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+import 'c.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+part of 'b.dart';
+''');
+
+    await resolveFile2(b.path);
+    assertErrorsInResult([
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 33, 8),
+    ]);
+
+    final node = findNode.import('c.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'c.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/c.dart
+  selectedSource: package:test/c.dart
+  selectedUriContent: c.dart
+  uriContent: c.dart
+  uriElement: <null>
+  uriSource: package:test/c.dart
+''');
+  }
+
+  test_inLibrary_configurations_default() async {
     newFile('$testPackageLibPath/a.dart', 'class A {}');
     newFile('$testPackageLibPath/a_html.dart', 'class A {}');
     newFile('$testPackageLibPath/a_io.dart', 'class A {}');
@@ -32,17 +179,95 @@
 var a = A();
 ''');
 
-    assertNamespaceDirectiveSelected(
-      findNode.import('a.dart'),
-      expectedRelativeUri: 'a.dart',
-      expectedUri: 'package:test/a.dart',
-    );
-
-    var a = findElement.topVar('a');
-    assertElementLibraryUri(a.type.element, 'package:test/a.dart');
+    final node = findNode.unit;
+    assertResolvedNodeText(node, r'''
+CompilationUnit
+  directives
+    ImportDirective
+      importKeyword: import
+      uri: SimpleStringLiteral
+        literal: 'a.dart'
+      configurations
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: html
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_html.dart'
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: io
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_io.dart'
+      semicolon: ;
+      element: LibraryImportElement
+        uri: DirectiveUriWithLibrary
+          uri: package:test/a.dart
+      selectedSource: package:test/a.dart
+      selectedUriContent: a.dart
+      uriContent: a.dart
+      uriElement: package:test/a.dart
+      uriSource: package:test/a.dart
+  declarations
+    TopLevelVariableDeclaration
+      variables: VariableDeclarationList
+        keyword: var
+        variables
+          VariableDeclaration
+            name: SimpleIdentifier
+              token: a
+              staticElement: self::@variable::a
+              staticType: null
+            equals: =
+            initializer: InstanceCreationExpression
+              constructorName: ConstructorName
+                type: NamedType
+                  name: SimpleIdentifier
+                    token: A
+                    staticElement: package:test/a.dart::@class::A
+                    staticType: null
+                  type: A
+                staticElement: package:test/a.dart::@class::A::@constructor::•
+              argumentList: ArgumentList
+                leftParenthesis: (
+                rightParenthesis: )
+              staticType: A
+            declaredElement: self::@variable::a
+      semicolon: ;
+      declaredElement: <null>
+''');
   }
 
-  test_configurations_first() async {
+  test_inLibrary_configurations_first() async {
     newFile('$testPackageLibPath/a.dart', 'class A {}');
     newFile('$testPackageLibPath/a_html.dart', 'class A {}');
     newFile('$testPackageLibPath/a_io.dart', 'class A {}');
@@ -60,17 +285,95 @@
 var a = A();
 ''');
 
-    assertNamespaceDirectiveSelected(
-      findNode.import('a.dart'),
-      expectedRelativeUri: 'a_html.dart',
-      expectedUri: 'package:test/a_html.dart',
-    );
-
-    var a = findElement.topVar('a');
-    assertElementLibraryUri(a.type.element, 'package:test/a_html.dart');
+    final node = findNode.unit;
+    assertResolvedNodeText(node, r'''
+CompilationUnit
+  directives
+    ImportDirective
+      importKeyword: import
+      uri: SimpleStringLiteral
+        literal: 'a.dart'
+      configurations
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: html
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_html.dart'
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: io
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_io.dart'
+      semicolon: ;
+      element: LibraryImportElement
+        uri: DirectiveUriWithLibrary
+          uri: package:test/a_html.dart
+      selectedSource: package:test/a_html.dart
+      selectedUriContent: a_html.dart
+      uriContent: a.dart
+      uriElement: package:test/a_html.dart
+      uriSource: package:test/a.dart
+  declarations
+    TopLevelVariableDeclaration
+      variables: VariableDeclarationList
+        keyword: var
+        variables
+          VariableDeclaration
+            name: SimpleIdentifier
+              token: a
+              staticElement: self::@variable::a
+              staticType: null
+            equals: =
+            initializer: InstanceCreationExpression
+              constructorName: ConstructorName
+                type: NamedType
+                  name: SimpleIdentifier
+                    token: A
+                    staticElement: package:test/a_html.dart::@class::A
+                    staticType: null
+                  type: A
+                staticElement: package:test/a_html.dart::@class::A::@constructor::•
+              argumentList: ArgumentList
+                leftParenthesis: (
+                rightParenthesis: )
+              staticType: A
+            declaredElement: self::@variable::a
+      semicolon: ;
+      declaredElement: <null>
+''');
   }
 
-  test_configurations_second() async {
+  test_inLibrary_configurations_second() async {
     newFile('$testPackageLibPath/a.dart', 'class A {}');
     newFile('$testPackageLibPath/a_html.dart', 'class A {}');
     newFile('$testPackageLibPath/a_io.dart', 'class A {}');
@@ -88,13 +391,264 @@
 var a = A();
 ''');
 
-    assertNamespaceDirectiveSelected(
-      findNode.import('a.dart'),
-      expectedRelativeUri: 'a_io.dart',
-      expectedUri: 'package:test/a_io.dart',
-    );
+    final node = findNode.unit;
+    assertResolvedNodeText(node, r'''
+CompilationUnit
+  directives
+    ImportDirective
+      importKeyword: import
+      uri: SimpleStringLiteral
+        literal: 'a.dart'
+      configurations
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: html
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_html.dart'
+        Configuration
+          ifKeyword: if
+          leftParenthesis: (
+          name: DottedName
+            components
+              SimpleIdentifier
+                token: dart
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: library
+                staticElement: <null>
+                staticType: null
+              SimpleIdentifier
+                token: io
+                staticElement: <null>
+                staticType: null
+          rightParenthesis: )
+          uri: SimpleStringLiteral
+            literal: 'a_io.dart'
+      semicolon: ;
+      element: LibraryImportElement
+        uri: DirectiveUriWithLibrary
+          uri: package:test/a_io.dart
+      selectedSource: package:test/a_io.dart
+      selectedUriContent: a_io.dart
+      uriContent: a.dart
+      uriElement: package:test/a_io.dart
+      uriSource: package:test/a.dart
+  declarations
+    TopLevelVariableDeclaration
+      variables: VariableDeclarationList
+        keyword: var
+        variables
+          VariableDeclaration
+            name: SimpleIdentifier
+              token: a
+              staticElement: self::@variable::a
+              staticType: null
+            equals: =
+            initializer: InstanceCreationExpression
+              constructorName: ConstructorName
+                type: NamedType
+                  name: SimpleIdentifier
+                    token: A
+                    staticElement: package:test/a_io.dart::@class::A
+                    staticType: null
+                  type: A
+                staticElement: package:test/a_io.dart::@class::A::@constructor::•
+              argumentList: ArgumentList
+                leftParenthesis: (
+                rightParenthesis: )
+              staticType: A
+            declaredElement: self::@variable::a
+      semicolon: ;
+      declaredElement: <null>
+''');
+  }
 
-    var a = findElement.topVar('a');
-    assertElementLibraryUri(a.type.element, 'package:test/a_io.dart');
+  test_inLibrary_library() async {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    await assertNoErrorsInCode(r'''
+// ignore: unused_import
+import 'a.dart';
+''');
+
+    final node = findNode.import('a.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: package:test/a.dart
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_noRelativeUriStr() async {
+    await assertErrorsInCode(r'''
+import '${'foo'}.dart';
+''', [
+      error(CompileTimeErrorCode.URI_WITH_INTERPOLATION, 7, 15),
+    ]);
+
+    final node = findNode.import('import');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: StringInterpolation
+    elements
+      InterpolationString
+        contents: '
+      InterpolationExpression
+        leftBracket: ${
+        expression: SimpleStringLiteral
+          literal: 'foo'
+        rightBracket: }
+      InterpolationString
+        contents: .dart'
+    staticType: String
+    stringValue: null
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUri
+  selectedSource: <null>
+  selectedUriContent: null
+  uriContent: null
+  uriElement: <null>
+  uriSource: <null>
+''');
+  }
+
+  test_inLibrary_noSource() async {
+    await assertErrorsInCode(r'''
+import 'foo:bar';
+''', [
+      error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 9),
+    ]);
+
+    final node = findNode.import('import');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'foo:bar'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithRelativeUri
+      relativeUri: foo:bar
+  selectedSource: <null>
+  selectedUriContent: foo:bar
+  uriContent: foo:bar
+  uriElement: <null>
+  uriSource: <null>
+''');
+  }
+
+  test_inLibrary_notLibrary_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+
+    await assertErrorsInCode(r'''
+import 'a.dart';
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.import('a.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_notLibrary_partOfName() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+part of my.lib;
+''');
+
+    await assertErrorsInCode(r'''
+import 'a.dart';
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.import('a.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
+  }
+
+  test_inLibrary_notLibrary_partOfUri() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+part of 'test.dart';
+''');
+
+    await assertErrorsInCode(r'''
+import 'a.dart';
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 7, 8),
+    ]);
+
+    final node = findNode.import('a.dart');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:test/a.dart
+  selectedSource: package:test/a.dart
+  selectedUriContent: a.dart
+  uriContent: a.dart
+  uriElement: <null>
+  uriSource: package:test/a.dart
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 6d2bd25..82538d6 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -16,7 +16,6 @@
 import 'constructor_reference_test.dart' as constructor_reference;
 import 'constructor_test.dart' as constructor;
 import 'enum_test.dart' as enum_resolution;
-import 'export_test.dart' as export_;
 import 'extension_method_test.dart' as extension_method;
 import 'extension_override_test.dart' as extension_override;
 import 'field_formal_parameter_test.dart' as field_formal_parameter;
@@ -41,6 +40,7 @@
 import 'interpolation_string_test.dart' as interpolation_string;
 import 'language_version_test.dart' as language_version;
 import 'library_element_test.dart' as library_element;
+import 'library_export_test.dart' as library_export;
 import 'library_import_prefix_test.dart' as library_import_prefix;
 import 'library_import_test.dart' as library_import;
 import 'local_function_test.dart' as local_function;
@@ -86,7 +86,6 @@
     constructor.main();
     constructor_reference.main();
     enum_resolution.main();
-    export_.main();
     extension_method.main();
     extension_override.main();
     field_formal_parameter.main();
@@ -108,6 +107,7 @@
     interpolation_string.main();
     language_version.main();
     library_element.main();
+    library_export.main();
     library_import_prefix.main();
     library_import.main();
     local_function.main();
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 0c26b7e..c41a403 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -267,6 +267,14 @@
   }
 
   @override
+  void visitConfiguration(Configuration node) {
+    _writeln('Configuration');
+    _withIndent(() {
+      _writeNamedChildEntities(node);
+    });
+  }
+
+  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     _writeln('ConstructorDeclaration');
     _withIndent(() {
@@ -353,6 +361,14 @@
   }
 
   @override
+  void visitDottedName(DottedName node) {
+    _writeln('DottedName');
+    _withIndent(() {
+      _writeNamedChildEntities(node);
+    });
+  }
+
+  @override
   void visitDoubleLiteral(DoubleLiteral node) {
     _writeln('DoubleLiteral');
     _withIndent(() {
@@ -1380,6 +1396,12 @@
         final uriStr = _stringOfSource(uri.augmentation.source);
         _writelnWithIndent('uri: $uriStr');
       });
+    } else if (uri is DirectiveUriWithLibrary) {
+      _writeln('DirectiveUriWithLibrary');
+      _withIndent(() {
+        final uriStr = _stringOfSource(uri.library.source);
+        _writelnWithIndent('uri: $uriStr');
+      });
     } else if (uri is DirectiveUriWithUnit) {
       _writeln('DirectiveUriWithUnit');
       _withIndent(() {
@@ -1438,6 +1460,10 @@
       _sink.writeln('<null>');
     } else if (element is AugmentationImportElement) {
       _writeAugmentationImportElement(element);
+    } else if (element is LibraryExportElement) {
+      _writeLibraryExportElement(element);
+    } else if (element is LibraryImportElement) {
+      _writeLibraryImportElement(element);
     } else if (element is PartElement) {
       _writePartElement(element);
     } else {
@@ -1464,6 +1490,24 @@
     }
   }
 
+  void _writeLibraryExportElement(LibraryExportElement element) {
+    _writeln('LibraryExportElement');
+    _withIndent(() {
+      _sink.write(_indent);
+      _sink.write('uri: ');
+      _writeDirectiveUri(element.uri);
+    });
+  }
+
+  void _writeLibraryImportElement(LibraryImportElement element) {
+    _writeln('LibraryImportElement');
+    _withIndent(() {
+      _sink.write(_indent);
+      _sink.write('uri: ');
+      _writeDirectiveUri(element.uri);
+    });
+  }
+
   void _writeln(String line) {
     _sink.writeln(line);
   }
diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md
index a21d663..e574f92 100644
--- a/pkg/compiler/README.md
+++ b/pkg/compiler/README.md
@@ -223,8 +223,7 @@
 
   * `lib/src/common/elements.dart`: provides an interface to lookup basic
     elements like the class of `Object`, `int`, `List`, and their corresponding
-    interface types, constructors for symbols, annotations such as
-    `@MirrorsUsed`, the `identical` function, etc. These are normally restricted
+    interface types, constructors for symbols, annotations such as the `identical` function. These are normally restricted
     to elements that are understood directly in Dart.
 
   * `lib/src/js_backend/backend_helpers.dart`: provides a way to lookup internal
@@ -278,10 +277,6 @@
   import, export, and part directives and keep crawling. It also triggers the
   patch parser to load patch files.
 
-* `lib/src/mirrors_used.dart`: task that analyzes `@MirrorsUsed` annotations,
-  which let the compiler continue to do tree-shaking even when code is used via
-  `dart:mirrors`.
-
 * Input/output: the compiler is designed to avoid all dependencies on dart:io.
   Most data is consumed and emitted via provider APIs.
 
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
index a0f4161..31de9ed 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -20,6 +20,7 @@
 import 'namer.dart';
 import 'native_data.dart';
 import 'runtime_types_codegen.dart' show RuntimeTypesSubstitutions;
+import 'runtime_types_new_interfaces.dart' as interfaces;
 
 class RecipeEncoding {
   final jsAst.Literal recipe;
@@ -28,13 +29,16 @@
   const RecipeEncoding(this.recipe, this.typeVariables);
 }
 
-abstract class RecipeEncoder {
+abstract class RecipeEncoder implements interfaces.RecipeEncoder {
   /// Returns a [RecipeEncoding] representing the given [recipe] to be
   /// evaluated against a type environment with shape [structure].
   RecipeEncoding encodeRecipe(ModularEmitter emitter,
       TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);
 
-  jsAst.Literal encodeGroundRecipe(ModularEmitter emitter, TypeRecipe recipe);
+  @override
+  // TODO(48820): Remove covariant when ModularEmitter is migrated.
+  jsAst.Literal encodeGroundRecipe(
+      covariant ModularEmitter emitter, TypeRecipe recipe);
 
   /// Returns a [jsAst.Literal] representing [supertypeArgument] to be evaluated
   /// against a [FullTypeEnvironmentStructure] representing [declaringType]. Any
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart
new file mode 100644
index 0000000..2b65d05
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new_interfaces.dart
@@ -0,0 +1,7 @@
+import '../js_emitter/code_emitter_task_interfaces.dart';
+import '../js_model/type_recipe.dart';
+import '../js/js.dart' as jsAst;
+
+abstract class RecipeEncoder {
+  jsAst.Literal encodeGroundRecipe(ModularEmitter emitter, TypeRecipe recipe);
+}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 9791f4a..1ac3892 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -2,8 +2,6 @@
 // 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.
 
-// @dart = 2.10
-
 library js_backend.runtime_types_resolution;
 
 import '../common.dart';
@@ -14,19 +12,20 @@
 import '../elements/types.dart';
 import '../ir/runtime_type_analysis.dart';
 import '../kernel/kelements.dart';
-import '../kernel/kernel_world.dart';
+import '../kernel/kernel_world_interfaces.dart';
 import '../options.dart';
 import '../serialization/serialization.dart';
 import '../universe/class_hierarchy.dart';
 import '../universe/class_set.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
-import '../world.dart';
+import '../world_interfaces.dart';
 import 'backend_usage.dart';
 
 abstract class RtiNode {
   Entity get entity;
-  Set<RtiNode> _dependencies;
+
+  Set<RtiNode>? _dependencies;
   bool _hasTest = false;
 
   Iterable<RtiNode> get dependencies => _dependencies ?? const [];
@@ -40,17 +39,14 @@
       // [entity]!
       return false;
     }
-    _dependencies ??= {};
-    return _dependencies.add(node);
+    return (_dependencies ??= {}).add(node);
   }
 
   void markTest() {
     if (!hasTest) {
       _hasTest = true;
-      if (_dependencies != null) {
-        for (RtiNode node in _dependencies) {
-          node.markTest();
-        }
+      for (RtiNode node in dependencies) {
+        node.markTest();
       }
     }
   }
@@ -87,11 +83,13 @@
   final Entity function;
   final ParameterStructure parameterStructure;
   final bool isCallTarget;
-  final Name instanceName;
+  final Name? instanceName;
   final bool isNoSuchMethod;
 
   MethodNode(this.function, this.parameterStructure,
-      {this.isCallTarget, this.instanceName, this.isNoSuchMethod = false});
+      {required this.isCallTarget,
+      this.instanceName,
+      this.isNoSuchMethod = false});
 
   @override
   Entity get entity => function;
@@ -139,10 +137,10 @@
   @override
   bool selectorApplies(Selector selector, BuiltWorld world) {
     if (property.memberName != selector.memberName) return false;
-    if (type is FunctionType &&
-        !selector.callStructure
-            .signatureApplies(ParameterStructure.fromType(type))) return false;
-    return true;
+    final myType = type;
+    return myType is! FunctionType ||
+        selector.callStructure
+            .signatureApplies(ParameterStructure.fromType(myType));
   }
 
   @override
@@ -159,7 +157,7 @@
   final Map<ClassEntity, ClassNode> _classes = {};
   final Map<Entity, MethodNode> _methods = {};
   final Map<MemberEntity, CallablePropertyNode> _callableProperties = {};
-  Map<Selector, Set<Entity>> _appliedSelectorMap;
+  final Map<Selector, Set<Entity>> _appliedSelectorMap = {};
   final Map<Entity, Set<GenericInstantiation>> _instantiationMap = {};
   final Map<ClassEntity, Set<InterfaceType>> _classInstantiationMap = {};
 
@@ -234,7 +232,7 @@
   /// needs it in order to generate the check against `A<int>`.
   ///
   Iterable<Entity> getTypeArgumentDependencies(Entity entity) {
-    Iterable<RtiNode> dependencies;
+    Iterable<RtiNode>? dependencies;
     if (entity is ClassEntity) {
       dependencies = _classes[entity]?.dependencies;
     } else if (_isProperty(entity)) {
@@ -272,7 +270,7 @@
     return _methods.putIfAbsent(function, () {
       MethodNode node;
       if (function is FunctionEntity) {
-        Name instanceName;
+        Name? instanceName;
         bool isCallTarget;
         bool isNoSuchMethod;
         if (function.isInstanceMember) {
@@ -289,7 +287,7 @@
             isNoSuchMethod: isNoSuchMethod);
       } else {
         ParameterStructure parameterStructure = ParameterStructure.fromType(
-            _elementEnvironment.getLocalFunctionType(function));
+            _elementEnvironment.getLocalFunctionType(function as Local));
         node = MethodNode(function, parameterStructure, isCallTarget: true);
       }
       return node;
@@ -312,7 +310,7 @@
     ///
     void registerDependencies(RtiNode node, DartType type) {
       type.forEachTypeVariable((TypeVariableType typeVariable) {
-        Entity typeDeclaration = typeVariable.element.typeDeclaration;
+        final typeDeclaration = typeVariable.element.typeDeclaration!;
         if (typeDeclaration is ClassEntity) {
           node.addDependency(_getClassNode(typeDeclaration));
         } else {
@@ -329,7 +327,7 @@
       }
 
       void onTypeVariable(TypeVariableType type) {
-        Entity declaration = type.element.typeDeclaration;
+        final declaration = type.element.typeDeclaration!;
         if (declaration is ClassEntity) {
           node.addDependency(_getClassNode(declaration));
         } else {
@@ -362,18 +360,12 @@
     //
     // TODO(johnniwinther): Make this dependency visible from code, possibly
     // using generic methods.
-    if (_commonElements.jsArrayClass != null) {
-      _getClassNode(_commonElements.jsArrayClass)
-          .addDependency(_getClassNode(_commonElements.listClass));
-    }
-    if (_commonElements.setLiteralClass != null) {
-      _getClassNode(_commonElements.setLiteralClass)
-          .addDependency(_getClassNode(_commonElements.setClass));
-    }
-    if (_commonElements.mapLiteralClass != null) {
-      _getClassNode(_commonElements.mapLiteralClass)
-          .addDependency(_getClassNode(_commonElements.mapClass));
-    }
+    _getClassNode(_commonElements.jsArrayClass)
+        .addDependency(_getClassNode(_commonElements.listClass));
+    _getClassNode(_commonElements.setLiteralClass)
+        .addDependency(_getClassNode(_commonElements.setClass));
+    _getClassNode(_commonElements.mapLiteralClass)
+        .addDependency(_getClassNode(_commonElements.mapClass));
 
     void processCheckedType(DartType type) {
       var typeWithoutNullability = type.withoutNullability;
@@ -479,7 +471,7 @@
   void _propagateTests() {
     void processTypeVariableType(TypeVariableType type) {
       TypeVariableEntity variable = type.element;
-      final typeDeclaration = variable.typeDeclaration;
+      final typeDeclaration = variable.typeDeclaration!;
       if (typeDeclaration is ClassEntity) {
         _getClassNode(typeDeclaration).markTest();
       } else {
@@ -559,7 +551,7 @@
 
   void _addImplicitChecksViaInstantiation(TypeVariableType variable) {
     TypeVariableEntity entity = variable.element;
-    Entity declaration = entity.typeDeclaration;
+    final declaration = entity.typeDeclaration!;
     if (declaration is ClassEntity) {
       classInstantiationsOf(declaration).forEach((InterfaceType type) {
         _addImplicitCheck(type.typeArguments[entity.index]);
@@ -606,9 +598,8 @@
       // set of is-checks.
       for (ClassEntity base in _classHierarchy.allSubtypesOf(cls)) {
         classInstantiationsOf(base).forEach((InterfaceType subtype) {
-          InterfaceType instance = _dartTypes.asInstanceOf(subtype, cls);
-          assert(instance != null);
-          _addImplicitChecks(instance.typeArguments);
+          final instance = _dartTypes.asInstanceOf(subtype, cls);
+          _addImplicitChecks(instance!.typeArguments);
         });
       }
     });
@@ -621,10 +612,6 @@
       _addImplicitChecks(typeArguments);
     });
 
-    if (forRtiNeeds) {
-      _appliedSelectorMap = {};
-    }
-
     _world.forEachDynamicTypeArgument(
         (Selector selector, Iterable<DartType> typeArguments) {
       for (CallableNode node in [
@@ -650,7 +637,7 @@
   void Function(InterfaceType) onInterface;
   void Function(TypeVariableType) onTypeVariable;
 
-  _DependencyVisitor({this.onInterface, this.onTypeVariable});
+  _DependencyVisitor({required this.onInterface, required this.onTypeVariable});
 
   @override
   bool handleInterfaceType(InterfaceType type) {
@@ -824,8 +811,8 @@
         classesNeedingTypeArguments,
         methodsNeedingSignature,
         methodsNeedingTypeArguments,
-        null,
-        null,
+        const {},
+        const {},
         selectorsNeedingTypeArguments,
         instantiationsNeedingTypeArguments);
   }
@@ -837,8 +824,8 @@
     sink.writeClasses(classesNeedingTypeArguments);
     sink.writeMembers(methodsNeedingSignature);
     sink.writeMembers(methodsNeedingTypeArguments);
-    assert(localFunctionsNeedingSignature == null);
-    assert(localFunctionsNeedingTypeArguments == null);
+    assert(localFunctionsNeedingSignature.isEmpty);
+    assert(localFunctionsNeedingTypeArguments.isEmpty);
     sink.writeList(selectorsNeedingTypeArguments,
         (Selector selector) => selector.writeToDataSink(sink));
     sink.writeList(instantiationsNeedingTypeArguments, sink.writeInt);
@@ -937,17 +924,18 @@
 
   final Set<Local> localFunctionsUsingTypeVariableLiterals = {};
 
-  Map<Selector, Set<Entity>> selectorsNeedingTypeArgumentsForTesting;
+  Map<Selector, Set<Entity>>? selectorsNeedingTypeArgumentsForTesting;
 
-  Map<Entity, Set<GenericInstantiation>>
+  Map<Entity, Set<GenericInstantiation>>?
       _instantiatedEntitiesNeedingTypeArgumentsForTesting;
+
   Map<Entity, Set<GenericInstantiation>>
       get instantiatedEntitiesNeedingTypeArgumentsForTesting =>
           _instantiatedEntitiesNeedingTypeArgumentsForTesting ?? const {};
 
   final Set<GenericInstantiation> _genericInstantiations = {};
 
-  TypeVariableTests typeVariableTestsForTesting;
+  TypeVariableTests? typeVariableTestsForTesting;
 
   RuntimeTypesNeedBuilderImpl(this._elementEnvironment);
 
@@ -973,7 +961,8 @@
 
   @override
   void registerTypeVariableLiteral(TypeVariableType variable) {
-    Entity typeDeclaration = variable.element.typeDeclaration;
+    final typeDeclaration = variable.element.typeDeclaration;
+    assert(typeDeclaration != null);
     if (typeDeclaration is ClassEntity) {
       registerClassUsingTypeVariableLiteral(typeDeclaration);
     } else if (typeDeclaration is FunctionEntity) {
@@ -1027,7 +1016,7 @@
       } else if (_isProperty(entity)) {
         // Do nothing. We just need to visit the dependencies.
       } else {
-        localFunctionsNeedingTypeArguments.add(entity);
+        localFunctionsNeedingTypeArguments.add(entity as Local);
       }
 
       Iterable<Entity> dependencies =
@@ -1042,35 +1031,33 @@
         closedWorld.closurizedMembersWithFreeTypeVariables.toSet();
 
     // Check local functions and closurized members.
-    void checkClosures({DartType potentialSubtypeOf}) {
+    void checkClosures({required DartType potentialSubtypeOf}) {
       bool checkFunctionType(FunctionType functionType) {
-        ClassEntity contextClass = DartTypes.getClassContext(functionType);
+        final contextClass = DartTypes.getClassContext(functionType);
         if (contextClass != null &&
-            (potentialSubtypeOf == null ||
-                closedWorld.dartTypes
-                    .isPotentialSubtype(functionType, potentialSubtypeOf))) {
+            (closedWorld.dartTypes
+                .isPotentialSubtype(functionType, potentialSubtypeOf))) {
           potentiallyNeedTypeArguments(contextClass);
           return true;
         }
         return false;
       }
 
-      Set<Local> localFunctionsToRemove;
-      Set<FunctionEntity> closurizedMembersToRemove;
+      Set<Local>? localFunctionsToRemove;
+      Set<FunctionEntity>? closurizedMembersToRemove;
       for (Local function in localFunctions) {
         FunctionType functionType =
             _elementEnvironment.getLocalFunctionType(function);
-        if (potentialSubtypeOf == null ||
-            closedWorld.dartTypes
-                .isPotentialSubtype(functionType, potentialSubtypeOf,
-                    // TODO(johnniwinther): Use register generic instantiations
-                    // instead.
-                    assumeInstantiations: _genericInstantiations.isNotEmpty)) {
+        if (closedWorld.dartTypes
+            .isPotentialSubtype(functionType, potentialSubtypeOf,
+                // TODO(johnniwinther): Use register generic instantiations
+                // instead.
+                assumeInstantiations: _genericInstantiations.isNotEmpty)) {
           if (functionType.typeVariables.isNotEmpty) {
             potentiallyNeedTypeArguments(function);
           }
           functionType.forEachTypeVariable((TypeVariableType typeVariable) {
-            Entity typeDeclaration = typeVariable.element.typeDeclaration;
+            final typeDeclaration = typeVariable.element.typeDeclaration!;
             if (!processedEntities.contains(typeDeclaration)) {
               potentiallyNeedTypeArguments(typeDeclaration);
             }
@@ -1110,7 +1097,7 @@
           type.forEachTypeVariable((TypeVariableType typeVariable) {
             // This handles checks against type variables and function types
             // containing type variables.
-            Entity typeDeclaration = typeVariable.element.typeDeclaration;
+            final typeDeclaration = typeVariable.element.typeDeclaration!;
             potentiallyNeedTypeArguments(typeDeclaration);
           });
           if (type is FunctionType) {
@@ -1163,11 +1150,11 @@
         checkFunction(method, _elementEnvironment.getFunctionType(method));
       }
     });
-    for (KLocalFunction function in closedWorld.genericLocalFunctions) {
+    for (final function in closedWorld.genericLocalFunctions) {
       if (closedWorld.annotationsData
           // TODO(johnniwinther): Support @pragma on local functions and use
           // this here instead of the enclosing member.
-          .getParameterCheckPolicy(function.memberContext)
+          .getParameterCheckPolicy((function as KLocalFunction).memberContext)
           .isEmitted) {
         checkFunction(
             function, _elementEnvironment.getLocalFunctionType(function));
@@ -1215,7 +1202,7 @@
       throw UnsupportedError('Unexpected type $type');
     }
 
-    void addClass(ClassEntity cls) {
+    void addClass(ClassEntity? cls) {
       if (cls != null) {
         classesDirectlyNeedingRuntimeType.add(cls);
       }
@@ -1239,7 +1226,7 @@
           Iterable<ClassEntity> receiverClasses =
               impliedClasses(runtimeTypeUse.receiverType);
           Iterable<ClassEntity> argumentClasses =
-              impliedClasses(runtimeTypeUse.argumentType);
+              impliedClasses(runtimeTypeUse.argumentType!);
 
           for (ClassEntity receiverClass in receiverClasses) {
             for (ClassEntity argumentClass in argumentClasses) {
@@ -1303,7 +1290,7 @@
         FunctionType functionType =
             _elementEnvironment.getLocalFunctionType(function);
         functionType.forEachTypeVariable((TypeVariableType typeVariable) {
-          Entity typeDeclaration = typeVariable.element.typeDeclaration;
+          final typeDeclaration = typeVariable.element.typeDeclaration!;
           if (!processedEntities.contains(typeDeclaration)) {
             potentiallyNeedTypeArguments(typeDeclaration);
           }
@@ -1313,7 +1300,7 @@
       for (FunctionEntity function
           in closedWorld.closurizedMembersWithFreeTypeVariables) {
         methodsNeedingSignature.add(function);
-        potentiallyNeedTypeArguments(function.enclosingClass);
+        potentiallyNeedTypeArguments(function.enclosingClass!);
       }
     }
 
@@ -1326,8 +1313,7 @@
             localFunctionsNeedingTypeArguments.contains(target)) {
           selectorsNeedingTypeArguments.add(selector);
           if (retainDataForTesting) {
-            selectorsNeedingTypeArgumentsForTesting ??= {};
-            selectorsNeedingTypeArgumentsForTesting
+            (selectorsNeedingTypeArgumentsForTesting ??= {})
                 .putIfAbsent(selector, () => {})
                 .add(target);
           } else {
@@ -1352,8 +1338,7 @@
       if (retainDataForTesting) {
         if (methodsNeedingTypeArguments.contains(target) ||
             localFunctionsNeedingTypeArguments.contains(target)) {
-          _instantiatedEntitiesNeedingTypeArgumentsForTesting ??= {};
-          _instantiatedEntitiesNeedingTypeArgumentsForTesting
+          (_instantiatedEntitiesNeedingTypeArgumentsForTesting ??= {})
               .putIfAbsent(target, () => {})
               .addAll(instantiations);
         }
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 0e14253..7a3be27 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -234,7 +234,7 @@
       code = js(template, fieldName);
     }
     jsAst.Name getterName = _namer.deriveGetterName(field.accessorName);
-    return StubMethod(getterName, code);
+    return StubMethod(getterName, code, element: field.element);
   }
 
   /// Generates a setter for the given [field].
@@ -259,7 +259,7 @@
     }
 
     jsAst.Name setterName = _namer.deriveSetterName(field.accessorName);
-    return StubMethod(setterName, code);
+    return StubMethod(setterName, code, element: field.element);
   }
 }
 
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 5932c85..790e988 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -26,6 +26,7 @@
 import 'startup_emitter/emitter.dart' as startup_js_emitter;
 import 'startup_emitter/fragment_merger.dart';
 
+import 'code_emitter_task_interfaces.dart' as interfaces;
 import 'metadata_collector.dart' show MetadataCollector;
 import 'model.dart';
 import 'native_emitter.dart' show NativeEmitter;
@@ -155,7 +156,7 @@
 ///
 /// Note that the emission phase is not itself modular but performed on
 /// the closed world computed by the codegen enqueuer.
-abstract class ModularEmitter {
+abstract class ModularEmitter implements interfaces.ModularEmitter {
   /// Returns the JS prototype of the given class [e].
   jsAst.Expression prototypeAccess(ClassEntity e);
 
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart
new file mode 100644
index 0000000..3071fdf
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task_interfaces.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2022, 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.
+
+abstract class ModularEmitter {}
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index 9aadb62..6c7af9e 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -97,7 +97,7 @@
     // TODO(sra): .withSourceInformation(sourceInformation);
 
     jsAst.Name name = _namer.invocationName(callSelector);
-    return ParameterStubMethod(name, null, function);
+    return ParameterStubMethod(name, null, function, element: functionField);
   }
 
   /// Generates a stub for a 'signature' selector. The stub calls the underlying
@@ -120,7 +120,8 @@
     // TODO(sra): Generate source information for stub that has no member.
     // TODO(sra): .withSourceInformation(sourceInformation);
 
-    return ParameterStubMethod(operatorSignature, null, function);
+    return ParameterStubMethod(operatorSignature, null, function,
+        element: functionField);
   }
 
   jsAst.Fun _generateSignatureNewRti(FieldEntity functionField) =>
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index ae10aaa..76c71d4 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -2,8 +2,6 @@
 // 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.
 
-// @dart = 2.10
-
 library dart2js.js_emitter.metadata_collector;
 
 import 'package:js_ast/src/precedence.dart' as js_precedence;
@@ -13,10 +11,10 @@
 
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
-import '../js_backend/runtime_types_new.dart' show RecipeEncoder;
+import '../js_backend/runtime_types_new_interfaces.dart' show RecipeEncoder;
 import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 
-import 'code_emitter_task.dart' show Emitter;
+import 'code_emitter_task_interfaces.dart' show ModularEmitter;
 
 /// Represents an entry's position in one of the global metadata arrays.
 ///
@@ -76,17 +74,15 @@
 }
 
 class _MetadataList extends jsAst.DeferredExpression {
-  jsAst.Expression _value;
+  late final jsAst.Expression _value;
 
   void setExpression(jsAst.Expression value) {
-    assert(_value == null);
     assert(value.precedenceLevel == this.precedenceLevel);
     _value = value;
   }
 
   @override
   jsAst.Expression get value {
-    assert(_value != null);
     return _value;
   }
 
@@ -96,7 +92,7 @@
 
 class MetadataCollector implements jsAst.TokenFinalizer {
   final DiagnosticReporter reporter;
-  final Emitter _emitter;
+  final ModularEmitter _emitter;
   final RecipeEncoder _rtiRecipeEncoder;
 
   /// A map used to canonicalize the entries of metadata.
@@ -143,7 +139,7 @@
     }
   }
 
-  jsAst.Expression reifyType(DartType type, OutputUnit outputUnit) {
+  jsAst.Expression? reifyType(DartType type, OutputUnit outputUnit) {
     return _addTypeInOutputUnit(type, outputUnit);
   }
 
@@ -153,19 +149,11 @@
   }
 
   jsAst.Expression _addTypeInOutputUnit(DartType type, OutputUnit outputUnit) {
-    _typesMap[outputUnit] ??= {};
-    BoundMetadataEntry metadataEntry;
-
-    if (_typesMap[outputUnit].containsKey(type)) {
-      metadataEntry = _typesMap[outputUnit][type].single;
-    } else {
-      _typesMap[outputUnit].putIfAbsent(type, () {
-        metadataEntry =
-            BoundMetadataEntry(_computeTypeRepresentationNewRti(type));
-        return [metadataEntry];
-      });
-    }
-    return metadataEntry;
+    final typeMap = _typesMap[outputUnit] ??= {};
+    final metadataEntryList = (typeMap[type] ??= [
+      BoundMetadataEntry(_computeTypeRepresentationNewRti(type))
+    ]);
+    return metadataEntryList.single;
   }
 
   @override
@@ -194,14 +182,13 @@
         entry.finalize(count++);
       }
 
-      List<jsAst.Node> values =
-          entries.map((BoundMetadataEntry e) => e.entry).toList();
+      final values = entries.map((BoundMetadataEntry e) => e.entry).toList();
 
       return jsAst.ArrayInitializer(values);
     }
 
     _typesTokens.forEach((OutputUnit outputUnit, _MetadataList token) {
-      Map<DartType, List<BoundMetadataEntry>> typesMap = _typesMap[outputUnit];
+      final typesMap = _typesMap[outputUnit];
       if (typesMap != null) {
         typesMap.values.forEach(countTokensInTypes);
         token.setExpression(finalizeMap(typesMap));
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index a862f48..fd16183 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -2,8 +2,6 @@
 // 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.
 
-// @dart = 2.10
-
 library dart2js.new_js_emitter.model;
 
 import '../common/elements.dart';
@@ -14,7 +12,7 @@
 import '../js/js.dart' as js show Expression, Name, Statement, TokenFinalizer;
 import '../js/js_debug.dart' as js show nodeToString;
 import '../js_backend/runtime_types_codegen.dart';
-import 'js_emitter.dart' show MetadataCollector;
+import 'metadata_collector.dart' show MetadataCollector;
 
 class Program {
   final List<Fragment> fragments;
@@ -32,10 +30,8 @@
 
   Program(this.fragments, this.typeToInterceptorMap, this._metadataCollector,
       this.finalizers,
-      {this.needsNativeSupport, this.outputContainsConstantList}) {
-    assert(needsNativeSupport != null);
-    assert(outputContainsConstantList != null);
-  }
+      {required this.needsNativeSupport,
+      required this.outputContainsConstantList});
 
   void mergeOutputUnitMetadata(OutputUnit target, OutputUnit source) {
     _metadataCollector.mergeOutputUnitMetadata(target, source);
@@ -187,8 +183,8 @@
   final bool usesNonNullableInitialization;
 
   StaticField(this.element, this.name, this.getterName, this.code,
-      {this.isFinal,
-      this.isLazy,
+      {required this.isFinal,
+      required this.isLazy,
       this.isInitializedByConstant = false,
       this.usesNonNullableInitialization = false});
 
@@ -224,8 +220,8 @@
   final ClassTypeData typeData;
 
   final js.Name name;
-  Class _superclass;
-  Class _mixinClass;
+  Class? superclass;
+  Class? mixinClass;
   final List<Method> methods;
   final List<Field> fields;
   final List<StubMethod> isChecks;
@@ -250,7 +246,7 @@
   /// If non-null, this class is used as a base class for closures with a fixed
   /// small number of arguments in order to inherit `Function.apply`
   /// metadata. The value is the fixed number of arguments.
-  final int sharedClosureApplyMetadata;
+  final int? sharedClosureApplyMetadata;
 
   final bool isMixinApplicationWithMembers;
 
@@ -262,13 +258,13 @@
   bool isEager = false;
 
   /// Leaf tags. See [NativeEmitter.prepareNativeClasses].
-  List<String> nativeLeafTags;
+  List<String>? nativeLeafTags;
 
   /// Non-leaf tags. See [NativeEmitter.prepareNativeClasses].
-  List<String> nativeNonLeafTags;
+  List<String>? nativeNonLeafTags;
 
   /// Native extensions. See [NativeEmitter.prepareNativeClasses].
-  List<Class> nativeExtensions;
+  List<Class>? nativeExtensions;
 
   Class(
       this.element,
@@ -282,36 +278,18 @@
       this.gettersSetters,
       this.isChecks,
       this.functionTypeIndex,
-      {this.hasRtiField,
-      this.onlyForRti,
-      this.onlyForConstructor,
-      this.isDirectlyInstantiated,
-      this.isNative,
-      this.isClosureBaseClass,
+      {required this.hasRtiField,
+      required this.onlyForRti,
+      required this.onlyForConstructor,
+      required this.isDirectlyInstantiated,
+      required this.isNative,
+      required this.isClosureBaseClass,
       this.sharedClosureApplyMetadata,
-      this.isMixinApplicationWithMembers}) {
-    assert(onlyForRti != null);
-    assert(onlyForConstructor != null);
-    assert(isDirectlyInstantiated != null);
-    assert(isNative != null);
-    assert(isClosureBaseClass != null);
-  }
+      required this.isMixinApplicationWithMembers});
 
   bool get isSimpleMixinApplication => false;
 
-  Class get superclass => _superclass;
-
-  void setSuperclass(Class superclass) {
-    _superclass = superclass;
-  }
-
-  Class get mixinClass => _mixinClass;
-
-  void setMixinClass(Class mixinClass) {
-    _mixinClass = mixinClass;
-  }
-
-  js.Name get superclassName => superclass?.name;
+  js.Name? get superclassName => superclass?.name;
 
   @override
   String toString() => 'Class(name=${name.key},element=$element)';
@@ -328,10 +306,10 @@
       List<StubMethod> gettersSetters,
       List<StubMethod> isChecks,
       js.Expression functionTypeIndex,
-      {bool hasRtiField,
-      bool onlyForRti,
-      bool onlyForConstructor,
-      bool isDirectlyInstantiated})
+      {required bool hasRtiField,
+      required bool onlyForRti,
+      required bool onlyForConstructor,
+      required bool isDirectlyInstantiated})
       : super(
             element,
             typeData,
@@ -424,7 +402,7 @@
 abstract class Method {
   /// The element should only be used during the transition to the new model.
   /// Uses indicate missing information in the model.
-  final MemberEntity element;
+  final MemberEntity? element;
 
   /// The name of the method. If the method is a [ParameterStubMethod] for a
   /// static function, then the name can be `null`. In that case, only the
@@ -438,7 +416,7 @@
 /// A method that corresponds to a method in the original Dart program.
 abstract class DartMethod extends Method {
   final bool needsTearOff;
-  final js.Name tearOffName;
+  final js.Name? tearOffName;
   final List<ParameterStubMethod> parameterStubs;
   final bool canBeApplied;
   final int applyIndex;
@@ -448,7 +426,7 @@
   // If the type is encoded in the metadata table this field contains an index
   // into the table. Otherwise the type contains type variables in which case
   // this field holds a function computing the function signature.
-  final js.Expression functionType;
+  final js.Expression? functionType;
 
   // Signature information for this method. [optionalParameterDefaultValues] is
   // only required and stored here if the method [canBeApplied]. The count is
@@ -459,24 +437,20 @@
   // If this method can be torn off, contains the name of the corresponding
   // call method. For example, for the member `foo$1$name` it would be
   // `call$1$name` (in unminified mode).
-  final js.Name callName;
+  final js.Name? callName;
 
   DartMethod(FunctionEntity element, js.Name name, js.Expression code,
       this.parameterStubs, this.callName,
-      {this.needsTearOff,
+      {required this.needsTearOff,
       this.tearOffName,
-      this.canBeApplied,
-      this.requiredParameterCount,
+      required this.canBeApplied,
+      required this.requiredParameterCount,
       this.optionalParameterDefaultValues,
       this.functionType,
-      this.applyIndex})
+      required this.applyIndex})
       : super(element, name, code) {
-    assert(needsTearOff != null);
     assert(!needsTearOff || tearOffName != null);
-    assert(canBeApplied != null);
-    assert(!canBeApplied ||
-        (requiredParameterCount != null &&
-            optionalParameterDefaultValues != null));
+    assert(!canBeApplied || optionalParameterDefaultValues != null);
   }
 
   bool get isStatic;
@@ -487,7 +461,7 @@
   /// a method via `super`. If [aliasName] is non-null, the emitter has to
   /// ensure that this method is registered on the prototype under both [name]
   /// and [aliasName].
-  final js.Name aliasName;
+  final js.Name? aliasName;
 
   /// `true` if the tear-off needs to access methods directly rather than rely
   /// on JavaScript prototype lookup. This happens when a tear-off getter is
@@ -516,18 +490,18 @@
     js.Expression code,
     List<ParameterStubMethod> parameterStubs,
     js.Name callName, {
-    bool needsTearOff,
-    js.Name tearOffName,
+    required bool needsTearOff,
+    js.Name? tearOffName,
     this.aliasName,
-    this.tearOffNeedsDirectAccess,
-    bool canBeApplied,
-    int requiredParameterCount,
+    required this.tearOffNeedsDirectAccess,
+    required bool canBeApplied,
+    required int requiredParameterCount,
     /* List | Map */ optionalParameterDefaultValues,
-    this.isClosureCallMethod,
-    this.inheritsApplyMetadata,
-    this.isIntercepted,
-    js.Expression functionType,
-    int applyIndex,
+    required this.isClosureCallMethod,
+    required this.inheritsApplyMetadata,
+    required this.isIntercepted,
+    js.Expression? functionType,
+    required int applyIndex,
   }) : super(element, name, code, parameterStubs, callName,
             needsTearOff: needsTearOff,
             tearOffName: tearOffName,
@@ -535,9 +509,7 @@
             requiredParameterCount: requiredParameterCount,
             optionalParameterDefaultValues: optionalParameterDefaultValues,
             functionType: functionType,
-            applyIndex: applyIndex) {
-    assert(isClosureCallMethod != null);
-  }
+            applyIndex: applyIndex);
 
   @override
   bool get isStatic => false;
@@ -553,7 +525,7 @@
 /// to a method in the original Dart program. Examples are getter and setter
 /// stubs and stubs to dispatch calls to methods with optional parameters.
 class StubMethod extends Method {
-  StubMethod(js.Name name, js.Expression code, {MemberEntity element})
+  StubMethod(js.Name name, js.Expression code, {MemberEntity? element})
       : super(element, name, code);
 
   @override
@@ -578,10 +550,10 @@
   /// name when it is used this way.
   ///
   /// If a stub's member can not be torn off, the [callName] is `null`.
-  js.Name callName;
+  js.Name? callName;
 
   ParameterStubMethod(js.Name name, this.callName, js.Expression code,
-      {MemberEntity element})
+      {required MemberEntity element})
       : super(name, code, element: element);
 
   @override
@@ -597,13 +569,13 @@
 class StaticDartMethod extends DartMethod implements StaticMethod {
   StaticDartMethod(FunctionEntity element, js.Name name, js.Expression code,
       List<ParameterStubMethod> parameterStubs, js.Name callName,
-      {bool needsTearOff,
-      js.Name tearOffName,
-      bool canBeApplied,
-      int requiredParameterCount,
+      {required bool needsTearOff,
+      js.Name? tearOffName,
+      required bool canBeApplied,
+      required int requiredParameterCount,
       /* List | Map */ optionalParameterDefaultValues,
-      js.Expression functionType,
-      int applyIndex})
+      js.Expression? functionType,
+      required int applyIndex})
       : super(element, name, code, parameterStubs, callName,
             needsTearOff: needsTearOff,
             tearOffName: tearOffName,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 542f7d6..112b504 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -200,7 +200,7 @@
     _classes.forEach((ClassEntity cls, Class c) {
       ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
       if (superclass != null) {
-        c.setSuperclass(_classes[superclass]);
+        c.superclass = _classes[superclass];
         assert(
             c.onlyForConstructor || c.superclass != null,
             failedAt(
@@ -211,7 +211,7 @@
       if (c.isSimpleMixinApplication || c.isMixinApplicationWithMembers) {
         ClassEntity effectiveMixinClass =
             _elementEnvironment.getEffectiveMixinClass(cls);
-        c.setMixinClass(_classes[effectiveMixinClass]);
+        c.mixinClass = _classes[effectiveMixinClass];
         assert(
             c.mixinClass != null,
             failedAt(
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index f74885d..0c92464 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -2,12 +2,10 @@
 // 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.
 
-// @dart = 2.10
-
 import 'dart:collection';
 import '../../common/elements.dart' show ElementEnvironment;
 import '../../deferred_load/output_unit.dart'
-    show ImportDescription, OutputUnit, OutputUnitData, deferredPartFileName;
+    show OutputUnit, OutputUnitData, deferredPartFileName;
 import '../../elements/entities.dart';
 import '../../js/js.dart' as js;
 import '../../options.dart';
@@ -167,8 +165,9 @@
   final List<EmittedOutputUnit> emittedOutputUnits = [];
   final Set<PreFragment> successors = {};
   final Set<PreFragment> predecessors = {};
-  FinalizedFragment finalizedFragment;
+  late final FinalizedFragment finalizedFragment;
   int size = 0;
+
   // TODO(joshualitt): interleave dynamically when it makes sense.
   bool shouldInterleave = false;
 
@@ -275,7 +274,6 @@
       Program program,
       Map<OutputUnit, CodeFragment> outputUnitMap,
       Map<CodeFragment, FinalizedFragment> codeFragmentMap) {
-    assert(finalizedFragment == null);
     List<CodeFragment> codeFragments = shouldInterleave
         ? [interleaveEmittedOutputUnits(program)]
         : bundleEmittedOutputUnits(program);
@@ -390,7 +388,7 @@
   String toString() {
     List<String> outputUnitStrings = [];
     for (var outputUnit in outputUnits) {
-      List<String> importStrings = [];
+      List<String?> importStrings = [];
       for (var import in outputUnit.imports) {
         importStrings.add(import.name);
       }
@@ -462,11 +460,11 @@
       List<CodeFragment> codeFragments = [];
       for (var outputUnit in outputUnits) {
         if (omittedOutputUnits.contains(outputUnit)) continue;
-        var codeFragment = outputUnitMap[outputUnit];
+        final codeFragment = outputUnitMap[outputUnit]!;
         if (uniqueCodeFragments.add(codeFragment)) {
           codeFragments.add(codeFragment);
         }
-        var finalizedFragment = codeFragmentMap[codeFragment];
+        final finalizedFragment = codeFragmentMap[codeFragment]!;
         if (uniqueFinalizedFragments.add(finalizedFragment)) {
           finalizedFragments.add(finalizedFragment);
         }
@@ -487,16 +485,16 @@
       for (int j = i + 1; j < allOutputUnits.length; j++) {
         var b = allOutputUnits[j];
         if (b.imports.containsAll(aImports)) {
-          backEdges[b] ??= {};
+          final backEdge = backEdges[b] ??= {};
 
           // Remove transitive edges from nodes that will reach 'b' from the
           // edge we just added.
           // Note: Because we add edges in order (starting from the smallest
           // sets) we always add transitive edges before the last direct edge.
-          backEdges[b].removeWhere((c) => aImports.containsAll(c.imports));
+          backEdge.removeWhere((c) => aImports.containsAll(c.imports));
 
           // Create an edge to denote that 'b' must be loaded before 'a'.
-          backEdges[b].add(a);
+          backEdge.add(a);
         }
       }
     }
@@ -525,9 +523,9 @@
     // Get a list of direct edges and then attach them to PreFragments.
     var allEdges = createDirectEdges(outputUnits);
     allEdges.forEach((outputUnit, edges) {
-      var predecessor = outputUnitMap[outputUnit];
+      final predecessor = outputUnitMap[outputUnit]!;
       for (var edge in edges) {
-        var successor = outputUnitMap[edge];
+        final successor = outputUnitMap[edge]!;
         predecessor.successors.add(successor);
         successor.predecessors.add(predecessor);
       }
@@ -576,7 +574,7 @@
   ///   {a}, {b}, {c}+{a, b}, {b, c}+{a, b, c}.
   List<PreFragment> mergeFragments(List<PreFragment> preDeferredFragments) {
     var components = separateComponents(preDeferredFragments);
-    int desiredNumberOfFragment = _options.mergeFragmentsThreshold;
+    final desiredNumberOfFragment = _options.mergeFragmentsThreshold!;
     int idealFragmentSize = (totalSize / desiredNumberOfFragment).ceil();
     List<_Partition> partitions = [];
     void add(PreFragment next) {
@@ -624,7 +622,7 @@
 
     Map<String, List<OutputUnit>> outputUnitsToLoad = {};
     for (var import in outputUnitData.deferredImportDescriptions.keys) {
-      var loadId = outputUnitData.importDeferName[import];
+      final loadId = outputUnitData.importDeferName[import]!;
       List<OutputUnit> loadList = [];
       for (var outputUnit in sortedOutputUnits) {
         assert(!outputUnit.isMainOutput);
@@ -659,9 +657,8 @@
     outputUnitData.deferredImportDescriptions.keys
         .forEach((ImportEntity import) {
       var importDeferName = outputUnitData.importDeferName[import];
-      List<FinalizedFragment> fragments = fragmentsToLoad[importDeferName];
-      ImportDescription description =
-          outputUnitData.deferredImportDescriptions[import];
+      final fragments = fragmentsToLoad[importDeferName]!;
+      final description = outputUnitData.deferredImportDescriptions[import]!;
       String getName(LibraryEntity library) {
         var name = _elementEnvironment.getLibraryName(library);
         return name == '' ? '<unnamed>' : name;
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index 673cf82..5433635 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -318,8 +318,8 @@
         classesNeedingTypeArguments,
         methodsNeedingSignature,
         methodsNeedingTypeArguments,
-        null,
-        null,
+        const {},
+        const {},
         selectorsNeedingTypeArguments,
         rtiNeed.instantiationsNeedingTypeArguments);
   }
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index 8aede80..b60859b 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -23,15 +23,20 @@
 import '../world.dart';
 
 import 'element_map.dart';
+import 'kernel_world_interfaces.dart' as interfaces;
 
 /// The immutable result of the [ResolutionWorldBuilder].
-class KClosedWorld implements BuiltWorld {
+class KClosedWorld implements BuiltWorld, interfaces.KClosedWorld {
   final KernelToElementMap elementMap;
+  @override
   final KElementEnvironment elementEnvironment;
+  @override
   final DartTypes dartTypes;
+  @override
   final KCommonElements commonElements;
   final NativeData nativeData;
   final InterceptorData interceptorData;
+  @override
   final BackendUsage backendUsage;
   final NoSuchMethodData noSuchMethodData;
   final Map<ClassEntity, Set<ClassEntity>> mixinUses;
@@ -75,11 +80,13 @@
   ///
   /// A closurized method is considered live if the enclosing class has been
   /// instantiated.
+  @override
   final Set<FunctionEntity> closurizedMembersWithFreeTypeVariables;
 
   /// Set of (live) local functions (closures).
   ///
   /// A live function is one whose enclosing member function has been enqueued.
+  @override
   final Iterable<Local> localFunctions;
 
   @override
@@ -159,6 +166,7 @@
 
   /// Returns `true` if [member] has been marked as used (called, read, etc.) in
   /// this world builder.
+  @override
   bool isMemberUsed(MemberEntity member) => liveMemberUsage.containsKey(member);
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/kernel_world_interfaces.dart b/pkg/compiler/lib/src/kernel/kernel_world_interfaces.dart
new file mode 100644
index 0000000..6bbd4ad
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/kernel_world_interfaces.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2022, 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 '../common/elements.dart';
+import '../elements/entities.dart';
+import '../elements/types.dart';
+import '../js_backend/backend_usage.dart';
+import '../world_interfaces.dart';
+
+abstract class KClosedWorld implements BuiltWorld {
+  KElementEnvironment get elementEnvironment;
+
+  KCommonElements get commonElements;
+
+  Iterable<Local> get localFunctions;
+
+  Set<FunctionEntity> get closurizedMembersWithFreeTypeVariables;
+
+  DartTypes get dartTypes;
+
+  BackendUsage get backendUsage;
+
+  bool isMemberUsed(MemberEntity member);
+}
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 884cef6..3f9581a 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -27,7 +27,7 @@
 
 import 'world_interfaces.dart' as interfaces;
 
-export 'world_interfaces.dart' show World;
+export 'world_interfaces.dart' show World, BuiltWorld;
 
 /// The [JClosedWorld] represents the information known about a program when
 /// compiling with closed-world semantics.
@@ -228,56 +228,3 @@
   /// Registers [interface] as a type argument to `extractTypeArguments`.
   void registerExtractTypeArguments(ClassEntity interface);
 }
-
-/// A [BuiltWorld] is an immutable result of a [WorldBuilder].
-abstract class BuiltWorld {
-  ClassHierarchy get classHierarchy;
-
-  /// Calls [f] for each live generic method.
-  void forEachGenericMethod(void Function(FunctionEntity) f);
-
-  /// All types that are checked either through is, as or checked mode checks.
-  Iterable<DartType> get isChecks;
-
-  /// All type variables named in recipes.
-  Set<TypeVariableType> get namedTypeVariablesNewRti;
-
-  /// All directly instantiated types, that is, the types of
-  /// [directlyInstantiatedClasses].
-  // TODO(johnniwinther): Improve semantic precision.
-  Iterable<InterfaceType> get instantiatedTypes;
-
-  // TODO(johnniwinther): Clean up these getters.
-  /// Methods in instantiated classes that are potentially closurized.
-  Iterable<FunctionEntity> get closurizedMembers;
-
-  /// Static or top level methods that are closurized.
-  Iterable<FunctionEntity> get closurizedStatics;
-
-  /// Properties (fields and getters) which can be called as generic functions.
-  Map<MemberEntity, DartType> get genericCallableProperties;
-
-  /// Type variables used as type literals.
-  Iterable<TypeVariableType> get typeVariableTypeLiterals;
-
-  /// Live user-defined 'noSuchMethod' implementations.
-  Iterable<FunctionEntity> get userNoSuchMethods;
-
-  AnnotationsData get annotationsData;
-
-  /// Calls [f] for each live generic instance methods.
-  void forEachGenericInstanceMethod(void Function(FunctionEntity) f);
-
-  /// Live generic local functions.
-  Iterable<Local> get genericLocalFunctions;
-
-  /// Call [f] for each generic [function] with the type arguments passed
-  /// through static calls to [function].
-  void forEachStaticTypeArgument(
-      void f(Entity function, Set<DartType> typeArguments));
-
-  /// Call [f] for each generic [selector] with the type arguments passed
-  /// through dynamic calls to [selector].
-  void forEachDynamicTypeArgument(
-      void f(Selector selector, Set<DartType> typeArguments));
-}
diff --git a/pkg/compiler/lib/src/world_interfaces.dart b/pkg/compiler/lib/src/world_interfaces.dart
index 84c1a9d..6009784 100644
--- a/pkg/compiler/lib/src/world_interfaces.dart
+++ b/pkg/compiler/lib/src/world_interfaces.dart
@@ -16,13 +16,75 @@
 
 abstract class JClosedWorld implements World {
   AbstractValueDomain get abstractValueDomain;
+
   JCommonElements get commonElements;
+
   ClassHierarchy get classHierarchy;
+
   DartTypes get dartTypes;
+
   NativeData get nativeData;
+
   AnnotationsData get annotationsData;
+
   bool includesClosureCall(Selector selector, AbstractValue? receiver);
+
   Iterable<MemberEntity> locateMembers(
       Selector selector, AbstractValue? receiver);
+
   bool fieldNeverChanges(MemberEntity element);
 }
+
+// TODO(48820): Move back to `world.dart` when migrated.
+/// A [BuiltWorld] is an immutable result of a [WorldBuilder].
+abstract class BuiltWorld {
+  ClassHierarchy get classHierarchy;
+
+  /// Calls [f] for each live generic method.
+  void forEachGenericMethod(void Function(FunctionEntity) f);
+
+  /// All types that are checked either through is, as or checked mode checks.
+  Iterable<DartType> get isChecks;
+
+  /// All type variables named in recipes.
+  Set<TypeVariableType> get namedTypeVariablesNewRti;
+
+  /// All directly instantiated types, that is, the types of
+  /// [directlyInstantiatedClasses].
+  // TODO(johnniwinther): Improve semantic precision.
+  Iterable<InterfaceType> get instantiatedTypes;
+
+  // TODO(johnniwinther): Clean up these getters.
+  /// Methods in instantiated classes that are potentially closurized.
+  Iterable<FunctionEntity> get closurizedMembers;
+
+  /// Static or top level methods that are closurized.
+  Iterable<FunctionEntity> get closurizedStatics;
+
+  /// Properties (fields and getters) which can be called as generic functions.
+  Map<MemberEntity, DartType> get genericCallableProperties;
+
+  /// Type variables used as type literals.
+  Iterable<TypeVariableType> get typeVariableTypeLiterals;
+
+  /// Live user-defined 'noSuchMethod' implementations.
+  Iterable<FunctionEntity> get userNoSuchMethods;
+
+  AnnotationsData get annotationsData;
+
+  /// Calls [f] for each live generic instance methods.
+  void forEachGenericInstanceMethod(void Function(FunctionEntity) f);
+
+  /// Live generic local functions.
+  Iterable<Local> get genericLocalFunctions;
+
+  /// Call [f] for each generic [function] with the type arguments passed
+  /// through static calls to [function].
+  void forEachStaticTypeArgument(
+      void f(Entity function, Set<DartType> typeArguments));
+
+  /// Call [f] for each generic [selector] with the type arguments passed
+  /// through dynamic calls to [selector].
+  void forEachDynamicTypeArgument(
+      void f(Selector selector, Set<DartType> typeArguments));
+}
diff --git a/pkg/dart2js_info/lib/info.dart b/pkg/dart2js_info/lib/info.dart
index cfc7242..1f658a8 100644
--- a/pkg/dart2js_info/lib/info.dart
+++ b/pkg/dart2js_info/lib/info.dart
@@ -125,7 +125,7 @@
   /// Major version indicating breaking changes in the format. A new version
   /// means that an old deserialization algorithm will not work with the new
   /// format.
-  final int version = 6;
+  final int version = 7;
 
   /// Minor version indicating non-breaking changes in the format. A change in
   /// this version number means that the json parsing in this library from a
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 71f07cb..8145e3e 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 9.3.0
+- Update to version `3.60` of the spec.
+- Add `gcType` property to `Event`.
+
 ## 9.2.0
 - Update to version `3.59` of the spec.
 - Add `abstract` flag to `FuncRef`.
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index cf92a35..f0edd09 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.59
+version=3.60
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 45dd4ee..3e66f4b 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
         HeapSnapshotObjectNoData,
         HeapSnapshotObjectNullData;
 
-const String vmServiceVersion = '3.59.0';
+const String vmServiceVersion = '3.60.0';
 
 /// @optional
 const String optional = 'optional';
@@ -4073,6 +4073,13 @@
   @optional
   InstanceRef? inspectee;
 
+  /// The garbage collection (GC) operation performed.
+  ///
+  /// This is provided for the event kinds:
+  ///  - GC
+  @optional
+  String? gcType;
+
   /// The RPC name of the extension that was added.
   ///
   /// This is provided for the ServiceExtensionAdded event.
@@ -4197,6 +4204,7 @@
     this.exception,
     this.bytes,
     this.inspectee,
+    this.gcType,
     this.extensionRPC,
     this.extensionKind,
     this.extensionData,
@@ -4236,6 +4244,7 @@
     bytes = json['bytes'];
     inspectee = createServiceObject(json['inspectee'], const ['InstanceRef'])
         as InstanceRef?;
+    gcType = json['gcType'];
     extensionRPC = json['extensionRPC'];
     extensionKind = json['extensionKind'];
     extensionData = ExtensionData.parse(json['extensionData']);
@@ -4284,6 +4293,7 @@
     _setIfNotNull(json, 'exception', exception?.toJson());
     _setIfNotNull(json, 'bytes', bytes);
     _setIfNotNull(json, 'inspectee', inspectee?.toJson());
+    _setIfNotNull(json, 'gcType', gcType);
     _setIfNotNull(json, 'extensionRPC', extensionRPC);
     _setIfNotNull(json, 'extensionKind', extensionKind);
     _setIfNotNull(json, 'extensionData', extensionData?.data);
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index e7c8f3b..c82374a 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -1,5 +1,5 @@
 name: vm_service
-version: 9.2.0
+version: 9.3.0
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index bf51c64..7572f29 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], 'Version');
     expect(result['major'], 3);
-    expect(result['minor'], 59);
+    expect(result['minor'], 60);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index 4bb45af..d99783f 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(59));
+    expect(result['minor'], equals(60));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/vm/compiler/backend/flow_graph_test.cc b/runtime/vm/compiler/backend/flow_graph_test.cc
index d97244f..ababc2b 100644
--- a/runtime/vm/compiler/backend/flow_graph_test.cc
+++ b/runtime/vm/compiler/backend/flow_graph_test.cc
@@ -9,6 +9,7 @@
 #include "platform/text_buffer.h"
 #include "platform/utils.h"
 #include "vm/compiler/backend/block_builder.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il_printer.h"
 #include "vm/compiler/backend/il_test_helper.h"
 #include "vm/compiler/backend/type_propagator.h"
@@ -244,4 +245,176 @@
                  "}\n");
 }
 
+ISOLATE_UNIT_TEST_CASE(FlowGraph_PhiUnboxingHeuristic_Double) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
+    return;
+  }
+
+  const char* kScript = R"(
+    double foo(double sum, int n) {
+       if (sum == null) return 0.0;
+       for (int i = 0; i < n; i++) {
+          sum += 1.0;
+       }
+       return sum;
+    }
+    main() {
+      foo(0.0, 10);
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true,
+                   ParallelMovesHandling::kSkip);
+
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMatchAndMoveFunctionEntry,
+  }));
+  if (FLAG_sound_null_safety != kNullSafetyOptionStrong) {
+    RELEASE_ASSERT(cursor.TryMatch({
+        kMatchAndMoveBranchFalse,
+        kMatchAndMoveTargetEntry,
+    }));
+  }
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMatchAndMoveUnbox,  // outside of loop
+      kMatchAndMoveCheckSmi,
+      kMoveGlob,
+
+      // Loop header
+      kMatchAndMoveJoinEntry,
+      kMatchAndMoveCheckStackOverflow,
+      kMatchAndMoveBranchTrue,
+
+      // Loop body
+      kMatchAndMoveTargetEntry,
+      kMatchAndMoveBinaryDoubleOp,
+      kMatchAndMoveBinarySmiOp,
+      kMatchAndMoveGoto,
+
+      // Loop header, again
+      kMatchAndMoveJoinEntry,
+      kMatchAndMoveCheckStackOverflow,
+      kMatchAndMoveBranchFalse,
+
+      // After loop
+      kMatchAndMoveTargetEntry,
+      kMatchAndMoveBox,
+      kMatchReturn,
+  }));
+}
+
+static void TestPhiUnboxingHeuristicSimd(const char* script) {
+  if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {
+    return;
+  }
+
+  const auto& root_library = Library::Handle(LoadTestScript(script));
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true,
+                   ParallelMovesHandling::kSkip);
+
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMatchAndMoveFunctionEntry,
+  }));
+  if (FLAG_sound_null_safety != kNullSafetyOptionStrong) {
+    RELEASE_ASSERT(cursor.TryMatch({
+        kMatchAndMoveBranchFalse,
+        kMatchAndMoveTargetEntry,
+    }));
+  }
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMatchAndMoveUnbox,  // outside of loop
+      kMatchAndMoveCheckSmi,
+      kMoveGlob,
+
+      // Loop header
+      kMatchAndMoveJoinEntry,
+      kMatchAndMoveCheckStackOverflow,
+      kMatchAndMoveBranchTrue,
+
+      // Loop body
+      kMatchAndMoveTargetEntry,
+      kMatchAndMoveSimdOp,
+      kMatchAndMoveBinarySmiOp,
+      kMatchAndMoveGoto,
+
+      // Loop header, again
+      kMatchAndMoveJoinEntry,
+      kMatchAndMoveCheckStackOverflow,
+      kMatchAndMoveBranchFalse,
+
+      // After loop
+      kMatchAndMoveTargetEntry,
+      kMatchAndMoveBox,
+      kMatchReturn,
+  }));
+}
+
+ISOLATE_UNIT_TEST_CASE(FlowGraph_PhiUnboxingHeuristic_Float32x4) {
+  const char* kScript = R"(
+    import 'dart:typed_data';
+    Float32x4 foo(Float32x4 sum, int n) {
+       if (sum == null) return Float32x4(0.0, 0.0, 0.0, 0.0);
+       for (int i = 0; i < n; i++) {
+          sum += Float32x4(1.0, 2.0, 3.0, 4.0);
+       }
+       return sum;
+    }
+    main() {
+      foo(Float32x4(0.0, 0.0, 0.0, 0.0), 10);
+    }
+  )";
+  TestPhiUnboxingHeuristicSimd(kScript);
+}
+
+ISOLATE_UNIT_TEST_CASE(FlowGraph_PhiUnboxingHeuristic_Float64x2) {
+  const char* kScript = R"(
+    import 'dart:typed_data';
+    Float64x2 foo(Float64x2 sum, int n) {
+       if (sum == null) return Float64x2(0.0, 0.0);
+       for (int i = 0; i < n; i++) {
+          sum += Float64x2(1.0, 2.0);
+       }
+       return sum;
+    }
+    main() {
+      foo(Float64x2(0.0, 0.0), 10);
+    }
+  )";
+  TestPhiUnboxingHeuristicSimd(kScript);
+}
+
+ISOLATE_UNIT_TEST_CASE(FlowGraph_PhiUnboxingHeuristic_Int32x4) {
+  const char* kScript = R"(
+    import 'dart:typed_data';
+    Int32x4 foo(Int32x4 sum, int n) {
+       if (sum == null) return Int32x4(0, 0, 0, 0);
+       for (int i = 0; i < n; i++) {
+          sum += Int32x4(1, 2, 3, 4);
+       }
+       return sum;
+    }
+    main() {
+      foo(Int32x4(0, 0, 0, 0), 10);
+    }
+  )";
+  TestPhiUnboxingHeuristicSimd(kScript);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 1dd76e6..73b64c5 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -1201,7 +1201,13 @@
   RELEASE_ASSERT(cursor.TryMatch({
       kMatchAndMoveFunctionEntry,
       kMatchAndMoveCheckStackOverflow,
-      kMatchAndMoveCheckClass,
+  }));
+  if (FLAG_sound_null_safety != kNullSafetyOptionStrong) {
+    RELEASE_ASSERT(cursor.TryMatch({
+        kMatchAndMoveCheckClass,
+    }));
+  }
+  RELEASE_ASSERT(cursor.TryMatch({
       kMatchAndMoveUnbox,
       kMatchAndMoveBinaryDoubleOp,
       kMatchAndMoveBinaryDoubleOp,
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 30e332c..086e3e5 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -768,6 +768,14 @@
       cid_ = kSentinelCid;
     } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
       cid_ = kClosureCid;
+    } else if (type_->IsDoubleType()) {
+      cid_ = kDoubleCid;  // double's only implementor is _Double.
+    } else if (type_->IsFloat32x4Type()) {
+      cid_ = kFloat32x4Cid;  // Float32x4's only implementor is _Float32x4.
+    } else if (type_->IsFloat64x2Type()) {
+      cid_ = kFloat64x2Cid;  // Float64x2's only implementor is _Float64x2.
+    } else if (type_->IsInt32x4Type()) {
+      cid_ = kInt32x4Cid;  // Int32x4's only implementor is _Int32x4.
     } else if (type_->type_class_id() != kIllegalCid) {
       const Class& type_class = Class::Handle(type_->type_class());
       Thread* thread = Thread::Current();
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 38a0bf6..cd32fd0 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -17,7 +17,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 59
+#define SERVICE_PROTOCOL_MINOR_VERSION 60
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 622ea1d..d7d7e52 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.59
+# Dart VM Service Protocol 3.60
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.58_ of the Dart VM Service Protocol. This
+This document describes of _version 3.60_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -2226,6 +2226,12 @@
   // This is provided for the Inspect event.
   @Instance inspectee [optional];
 
+  // The garbage collection (GC) operation performed.
+  //
+  // This is provided for the event kinds:
+  //   GC
+  string gcType [optional];
+
   // The RPC name of the extension that was added.
   //
   // This is provided for the ServiceExtensionAdded event.
@@ -4379,5 +4385,6 @@
 3.57 | Added optional `libraryFilters` parameter to `getSourceReport` RPC.
 3.58 | Added optional `local` parameter to `lookupResolvedPackageUris` RPC.
 3.59 | Added `abstract` property to `@Function` and `Function`.
+3.60 | Added `gcType` property to `Event`.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 9e4f399..b0e3fcf 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -284,6 +284,7 @@
   }
   if (gc_stats() != NULL) {
     jsobj.AddProperty("reason", Heap::GCReasonToString(gc_stats()->reason_));
+    jsobj.AddProperty("gcType", Heap::GCTypeToString(gc_stats()->type_));
     isolate_group()->heap()->PrintToJSONObject(Heap::kNew, &jsobj);
     isolate_group()->heap()->PrintToJSONObject(Heap::kOld, &jsobj);
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index ec8addd..b4f4f5c 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -154,8 +154,7 @@
 }
 
 void throwInvalidReflectionError(String memberName) {
-  throw new UnsupportedError("Can't use '$memberName' in reflection "
-      "because it is not included in a @MirrorsUsed annotation.");
+  throw new UnsupportedError("Can't use '$memberName' in reflection.");
 }
 
 /// Helper used to instrument calls when the compiler is invoked with
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 6e19487..963319f 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -120,11 +120,6 @@
 
   /**
    * Returns the name of [symbol].
-   *
-   * The following text is non-normative:
-   *
-   * Using this method may result in larger output.  If possible, use
-   * [MirrorsUsed] to specify which symbols must be retained in clear text.
    */
   external static String getName(Symbol symbol);
 
@@ -1196,283 +1191,3 @@
    */
   Uri get sourceUri;
 }
-
-/**
- * Class used for encoding comments as metadata annotations.
- */
-class Comment {
-  /**
-   * The comment text as written in the source text.
-   */
-  final String text;
-
-  /**
-   * The comment text without the start, end, and padding text.
-   *
-   * For example, if [text] is [: /** Comment text. */ :] then the [trimmedText]
-   * is [: Comment text. :].
-   */
-  final String trimmedText;
-
-  /**
-   * Is [:true:] if this comment is a documentation comment.
-   *
-   * That is, that the comment is either enclosed in [: /** ... */ :] or starts
-   * with [: /// :].
-   */
-  final bool isDocComment;
-
-  const Comment(this.text, this.trimmedText, this.isDocComment);
-}
-
-/**
- * Annotation describing how "dart:mirrors" is used (EXPERIMENTAL).
- *
- * When used as metadata on an import of "dart:mirrors" in library *L*, this
- * class describes how "dart:mirrors" is used by library *L* unless overridden.
- * See [override].
- *
- * The following text is non-normative:
- *
- * In some scenarios, for example, when minifying Dart code, or when generating
- * JavaScript code from a Dart program, the size and performance of the output
- * can suffer from use of reflection.  In those cases, telling the compiler
- * what is used, can have a significant impact.
- *
- * Example usage:
- *
- *     @MirrorsUsed(symbols: 'foo')
- *     import 'dart:mirrors';
- *
- *     class Foo {
- *       noSuchMethod(Invocation invocation) {
- *         print(MirrorSystem.getName(invocation.memberName));
- *       }
- *     }
- *
- *     main() {
- *       new Foo().foo(); // Prints "foo".
- *       new Foo().bar(); // Might print an arbitrary (mangled) name, "bar".
- *     }
- *
- * For a detailed description of the parameters to the [MirrorsUsed] constructor
- * see the comments for [symbols], [targets], [metaTargets] and [override].
- *
- * An import of `dart:mirrors` may have multiple [MirrorsUsed] annotations. This
- * is particularly helpful to specify overrides for specific libraries. For
- * example:
- *
- *     @MirrorsUsed(targets: 'foo.Bar', override: 'foo')
- *     @MirrorsUsed(targets: 'Bar')
- *     import 'dart:mirrors';
- *
- * will ensure that the target `Bar` from the current library and from library
- * `foo` is available for reflection. See also [override].
- */
-@Deprecated("No longer has any effect. Will be removed in a later release.")
-class MirrorsUsed {
-  // Note: the fields of this class are untyped.  This is because the most
-  // convenient way to specify symbols today is using a single string. In
-  // some cases, a const list of classes might be convenient. Some
-  // might prefer to use a const list of symbols.
-
-  /**
-   * The list of strings passed to new [Symbol], and symbols that might be
-   * passed to [MirrorSystem.getName].
-   *
-   * Combined with the names of [targets], [metaTargets] and their members,
-   * this forms the complete list of strings passed to new [Symbol], and
-   * symbols that might be passed to [MirrorSystem.getName] by the library to
-   * which this metadata applies.
-   *
-   * The following text is non-normative:
-   *
-   * Dart2js currently supports the following formats to specify symbols:
-   *
-   * * A constant [List] of [String] constants representing symbol names,
-   *   e.g., `const ['foo', 'bar']`.
-   * * A single [String] constant whose value is a comma-separated list of
-   *   symbol names, e.g., `"foo, bar"`.
-   *
-   * Specifying the `symbols` field turns off the following warnings emitted by
-   * dart2js:
-   *
-   * * Using "MirrorSystem.getName" may result in larger output.
-   * * Using "new Symbol" may result in larger output.
-   *
-   * For example, if you're using [noSuchMethod] to interact with a database,
-   * extract all the possible column names and include them in this list.
-   * Similarly, if you're using [noSuchMethod] to interact with another
-   * language (JavaScript, for example) extract all the identifiers from the
-   * API you use and include them in this list.
-   *
-   * Note that specifying a symbol only ensures that the symbol will be
-   * available under that name at runtime. It does not mark targets with
-   * that name as available for reflection. See [targets] and [metaTargets]
-   * for that purpose.
-   */
-  final symbols;
-
-  /**
-   * A list of reflective targets.
-   *
-   * Combined with [metaTargets], this provides the complete list of reflective
-   * targets used by the library to which this metadata applies.
-   *
-   * The following text is non-normative:
-   *
-   * For now, there is no formal description of what a reflective target is.
-   * Informally, a target is a library, a class, a method or a field.
-   *
-   * Dart2js currently supports the following formats to specify targets:
-   *
-   * * A constant [List] containing [String] constants representing (qualified)
-   *   names of targets and Dart types.
-   * * A single [String] constant whose value is a comma-separated list of
-   *   (qualified) names.
-   * * A single Dart type.
-   *
-   * A (qualified) name is resolved to a target as follows:
-   *
-   * 1. If the qualified name matches a library name, the matching library is
-   *    the target.
-   * 2. Else, find the longest prefix of the name such that the prefix ends
-   *    just before a `.` and is a library name.
-   * 3. Use that library as current scope. If no matching prefix was found, use
-   *    the current library, i.e., the library where the [MirrorsUsed]
-   *    annotation was placed.
-   * 4. Split the remaining suffix (the entire name if no library name was
-   *    found in step 3) into a list of [String] using `.` as a
-   *    separator.
-   * 5. Select all targets in the current scope whose name matches a [String]
-   *    from the list.
-   *
-   * For example:
-   *
-   *     library my.library.one;
-   *
-   *     class A {
-   *       var aField;
-   *     }
-   *
-   *     library main;
-   *
-   *     @MirrorsUsed(targets: "my.library.one.A.aField")
-   *     import "dart:mirrors";
-   *
-   * The [MirrorsUsed] annotation specifies `A` and `aField` from library
-   * `my.library.one` as targets. This will mark the class `A` as a reflective
-   * target. The target specification for `aField` has no effect, as there is
-   * no target in `my.library.one` with that name.
-   *
-   * Note that everything within a target also is available for reflection.
-   * So, if a library is specified as target, all classes in that library
-   * become targets for reflection. Likewise, if a class is a target, all
-   * its methods and fields become targets for reflection. As a consequence,
-   * `aField` in the above example is also a reflective target.
-   *
-   */
-  final targets;
-
-  /**
-   * A list of classes that when used as metadata indicates a reflective
-   * target. See also [targets].
-   *
-   * The following text is non-normative:
-   *
-   * The format for specifying the list of classes is the same as used for
-   * specifying [targets]. However, as a library cannot be used as a metadata
-   * annotation in Dart, adding a library to the list of [metaTargets] has no
-   * effect. In particular, adding a library to [metaTargets] does not make
-   * the library's classes valid metadata annotations to enable reflection.
-   *
-   * If an instance of a class specified in [metaTargets] is used as
-   * metadata annotation on a library, class, field or method, that library,
-   * class, field or  method is added to the set of targets for reflection.
-   *
-   * Example usage:
-   *
-   *     library example;
-   *     @MirrorsUsed(metaTargets: "example.Reflectable")
-   *     import "dart:mirrors";
-   *
-   *     class Reflectable {
-   *       const Reflectable();
-   *     }
-   *
-   *     class Foo {
-   *       @Reflectable()
-   *       reflectableMethod() { ... }
-   *
-   *       nonReflectableMethod() { ... }
-   *     }
-   *
-   * In the above example. `reflectableMethod` is marked as reflectable by
-   * using the `Reflectable` class, which in turn is specified in the
-   * [metaTargets] annotation.
-   *
-   * The method `nonReflectableMethod` lacks a metadata annotation and thus
-   * will not be reflectable at runtime.
-   */
-  final metaTargets;
-
-  /**
-   * A list of library names or "*".
-   *
-   * When used as metadata on an import of "dart:mirrors", this metadata does
-   * not apply to the library in which the annotation is used, but instead
-   * applies to the other libraries (all libraries if "*" is used).
-   *
-   * The following text is non-normative:
-   *
-   * Dart2js currently supports the following formats to specify libraries:
-   *
-   * * A constant [List] containing [String] constants representing names of
-   *   libraries.
-   * * A single [String] constant whose value is a comma-separated list of
-   *   library names.
-   *
-   * Conceptually, a [MirrorsUsed] annotation with [override] has the same
-   * effect as placing the annotation directly on the import of `dart:mirrors`
-   * in each of the referenced libraries. Thus, if the library had no
-   * [MirrorsUsed] annotation before, its unconditional import of
-   * `dart:mirrors` is overridden by an annotated import.
-   *
-   * Note that, like multiple explicit [MirrorsUsed] annotations, using
-   * override on a library with an existing [MirrorsUsed] annotation is
-   * additive. That is, the overall set of reflective targets is the union
-   * of the reflective targets that arise from the original and the
-   * overriding [MirrorsUsed] annotations.
-   *
-   * The use of [override] is only meaningful for libraries that have an
-   * import of `dart:mirrors` without annotation because otherwise it would
-   * work exactly the same way without the [override] parameter.
-   *
-   * While the annotation will apply to the given target libraries, the
-   * [symbols], [targets] and [metaTargets] are still evaluated in the
-   * scope of the annotation. Thus, to select a target from library `foo`,
-   * a qualified name has to be used or, if the target is visible in the
-   * current scope, its type may be referenced.
-   *
-   * For example, the following code marks all targets in the library `foo`
-   * as reflectable that have a metadata annotation using the `Reflectable`
-   * class from the same library.
-   *
-   *     @MirrorsUsed(metaTargets: "foo.Reflectable", override: "foo")
-   *
-   * However, the following code would require the use of the `Reflectable`
-   * class from the current library, instead.
-   *
-   *     @MirrorsUsed(metaTargets: "Reflectable", override: "foo")
-   *
-   */
-  final override;
-
-  /**
-   * See the documentation for [MirrorsUsed.symbols], [MirrorsUsed.targets],
-   * [MirrorsUsed.metaTargets] and [MirrorsUsed.override] for documentation
-   * of the parameters.
-   */
-  const MirrorsUsed(
-      {this.symbols, this.targets, this.metaTargets, this.override});
-}
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index ea6a330..7dce112 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -24,6 +24,9 @@
 ///
 /// Used to process large quantities of binary or numerical data
 /// more efficiently using a typed view.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// ByteBuffer.
 abstract class ByteBuffer {
   /// Returns the length of this byte buffer, in bytes.
   int get lengthInBytes;
@@ -340,6 +343,9 @@
 }
 
 /// A typed view of a sequence of bytes.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// TypedData.
 abstract class TypedData {
   /// Returns the number of bytes in the representation of each element in this
   /// list.
@@ -377,6 +383,9 @@
 
 /// Describes endianness to be used when accessing or updating a
 /// sequence of bytes.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Endian.
 class Endian {
   final bool _littleEndian;
   const Endian._(this._littleEndian);
@@ -421,6 +430,9 @@
 /// bdata.setFloat32(0, 3.04);
 /// int huh = bdata.getInt32(0); // 0x40428f5c
 /// ```
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// ByteData.
 abstract class ByteData implements TypedData {
   /// Creates a [ByteData] of the specified length (in elements), all of
   /// whose bytes are initially zero.
@@ -704,6 +716,9 @@
 /// Integers stored in the list are truncated to their low eight bits,
 /// interpreted as a signed 8-bit two's complement integer with values in the
 /// range -128 to +127.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Int8List.
 abstract class Int8List implements List<int>, _TypedIntList {
   /// Creates an [Int8List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -814,6 +829,9 @@
 /// Integers stored in the list are truncated to their low eight bits,
 /// interpreted as an unsigned 8-bit integer with values in the
 /// range 0 to 255.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Uint8List.
 abstract class Uint8List implements List<int>, _TypedIntList {
   /// Creates a [Uint8List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -931,6 +949,9 @@
 /// Integers stored in the list are clamped to an unsigned eight bit value.
 /// That is, all values below zero are stored as zero
 /// and all values above 255 are stored as 255.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Uint8ClampedList.
 abstract class Uint8ClampedList implements List<int>, _TypedIntList {
   /// Creates a [Uint8ClampedList] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -1044,6 +1065,9 @@
 /// Integers stored in the list are truncated to their low 16 bits,
 /// interpreted as a signed 16-bit two's complement integer with values in the
 /// range -32768 to +32767.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Int16List.
 abstract class Int16List implements List<int>, _TypedIntList {
   /// Creates an [Int16List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -1166,6 +1190,9 @@
 /// Integers stored in the list are truncated to their low 16 bits,
 /// interpreted as an unsigned 16-bit integer with values in the
 /// range 0 to 65535.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Uint16List.
 abstract class Uint16List implements List<int>, _TypedIntList {
   /// Creates a [Uint16List] of the specified length (in elements), all
   /// of whose elements are initially zero.
@@ -1289,6 +1316,9 @@
 /// Integers stored in the list are truncated to their low 32 bits,
 /// interpreted as a signed 32-bit two's complement integer with values in the
 /// range -2147483648 to 2147483647.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Int32List.
 abstract class Int32List implements List<int>, _TypedIntList {
   /// Creates an [Int32List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -1411,6 +1441,9 @@
 /// Integers stored in the list are truncated to their low 32 bits,
 /// interpreted as an unsigned 32-bit integer with values in the
 /// range 0 to 4294967295.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Uint32List.
 abstract class Uint32List implements List<int>, _TypedIntList {
   /// Creates a [Uint32List] of the specified length (in elements), all
   /// of whose elements are initially zero.
@@ -1534,6 +1567,9 @@
 /// Integers stored in the list are truncated to their low 64 bits,
 /// interpreted as a signed 64-bit two's complement integer with values in the
 /// range -9223372036854775808 to +9223372036854775807.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Int64List.
 abstract class Int64List implements List<int>, _TypedIntList {
   /// Creates an [Int64List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -1656,6 +1692,9 @@
 /// Integers stored in the list are truncated to their low 64 bits,
 /// interpreted as an unsigned 64-bit integer with values in the
 /// range 0 to 18446744073709551615.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Uint64List.
 abstract class Uint64List implements List<int>, _TypedIntList {
   /// Creates a [Uint64List] of the specified length (in elements), all
   /// of whose elements are initially zero.
@@ -1780,6 +1819,9 @@
 /// Double values stored in the list are converted to the nearest
 /// single-precision value. Values read are converted to a double
 /// value with the same value.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float32List.
 abstract class Float32List implements List<double>, _TypedFloatList {
   /// Creates a [Float32List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -1899,6 +1941,9 @@
 /// For long lists, this
 /// implementation can be considerably more space- and time-efficient than
 /// the default [List] implementation.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float64List.
 abstract class Float64List implements List<double>, _TypedFloatList {
   /// Creates a [Float64List] of the specified length (in elements), all of
   /// whose elements are initially zero.
@@ -2014,6 +2059,9 @@
 ///
 /// For long lists, this implementation will be considerably more
 /// space- and time-efficient than the default [List] implementation.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float32x4List.
 abstract class Float32x4List implements List<Float32x4>, TypedData {
   /// Creates a [Float32x4List] of the specified length (in elements),
   /// all of whose elements are initially zero.
@@ -2256,6 +2304,9 @@
 ///
 /// For long lists, this implementation will be considerably more
 /// space- and time-efficient than the default [List] implementation.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float64x2List.
 abstract class Float64x2List implements List<Float64x2>, TypedData {
   /// Creates a [Float64x2List] of the specified length (in elements),
   /// all of whose elements have all lanes set to zero.
@@ -2376,6 +2427,9 @@
 ///
 /// Float32x4 stores 4 32-bit floating point values in "lanes".
 /// The lanes are "x", "y", "z", and "w" respectively.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float32x4.
 abstract class Float32x4 {
   external factory Float32x4(double x, double y, double z, double w);
   external factory Float32x4.splat(double v);
@@ -3097,6 +3151,9 @@
 ///
 /// Float64x2 stores 2 64-bit floating point values in "lanes".
 /// The lanes are "x" and "y" respectively.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// Float64x2.
 abstract class Float64x2 {
   external factory Float64x2(double x, double y);
   external factory Float64x2.splat(double v);
diff --git a/sdk/lib/typed_data/unmodifiable_typed_data.dart b/sdk/lib/typed_data/unmodifiable_typed_data.dart
index 43aaa84..4647798 100644
--- a/sdk/lib/typed_data/unmodifiable_typed_data.dart
+++ b/sdk/lib/typed_data/unmodifiable_typed_data.dart
@@ -5,6 +5,9 @@
 part of dart.typed_data;
 
 /// A read-only view of a [ByteBuffer].
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableByteBufferView.
 class UnmodifiableByteBufferView implements ByteBuffer {
   final ByteBuffer _data;
 
@@ -65,6 +68,9 @@
 }
 
 /// A read-only view of a [ByteData].
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableByteDataView.
 class UnmodifiableByteDataView implements ByteData {
   final ByteData _data;
 
@@ -170,6 +176,9 @@
 }
 
 /// View of a [Uint8List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint8ListView.
 class UnmodifiableUint8ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint8List, Uint8List>
     implements Uint8List {
@@ -180,6 +189,9 @@
 }
 
 /// View of a [Int8List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt8ListView.
 class UnmodifiableInt8ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int8List, Int8List>
     implements Int8List {
@@ -190,6 +202,9 @@
 }
 
 /// View of a [Uint8ClampedList] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint8ClampedListView.
 class UnmodifiableUint8ClampedListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint8ClampedList, Uint8ClampedList>
     implements Uint8ClampedList {
@@ -200,6 +215,9 @@
 }
 
 /// View of a [Uint16List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint16ListView.
 class UnmodifiableUint16ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint16List, Uint16List>
     implements Uint16List {
@@ -210,6 +228,9 @@
 }
 
 /// View of a [Int16List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt16ListView.
 class UnmodifiableInt16ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int16List, Int16List>
     implements Int16List {
@@ -220,6 +241,9 @@
 }
 
 /// View of a [Uint32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint32ListView.
 class UnmodifiableUint32ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint32List, Uint32List>
     implements Uint32List {
@@ -230,6 +254,9 @@
 }
 
 /// View of a [Int32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt32ListView.
 class UnmodifiableInt32ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int32List, Int32List>
     implements Int32List {
@@ -240,6 +267,9 @@
 }
 
 /// View of a [Uint64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableUint64ListView.
 class UnmodifiableUint64ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint64List, Uint64List>
     implements Uint64List {
@@ -250,6 +280,9 @@
 }
 
 /// View of a [Int64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt64ListView.
 class UnmodifiableInt64ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int64List, Int64List>
     implements Int64List {
@@ -260,6 +293,9 @@
 }
 
 /// View of a [Int32x4List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableInt32x4ListView.
 class UnmodifiableInt32x4ListView extends UnmodifiableListBase<Int32x4>
     with _UnmodifiableListMixin<Int32x4, Int32x4List, Int32x4List>
     implements Int32x4List {
@@ -270,6 +306,9 @@
 }
 
 /// View of a [Float32x4List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat32x4ListView.
 class UnmodifiableFloat32x4ListView extends UnmodifiableListBase<Float32x4>
     with _UnmodifiableListMixin<Float32x4, Float32x4List, Float32x4List>
     implements Float32x4List {
@@ -280,6 +319,9 @@
 }
 
 /// View of a [Float64x2List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat64x2ListView.
 class UnmodifiableFloat64x2ListView extends UnmodifiableListBase<Float64x2>
     with _UnmodifiableListMixin<Float64x2, Float64x2List, Float64x2List>
     implements Float64x2List {
@@ -290,6 +332,9 @@
 }
 
 /// View of a [Float32List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat32ListView.
 class UnmodifiableFloat32ListView extends UnmodifiableListBase<double>
     with _UnmodifiableListMixin<double, Float32List, Float32List>
     implements Float32List {
@@ -300,6 +345,9 @@
 }
 
 /// View of a [Float64List] that disallows modification.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// UnmodifiableFloat64ListView.
 class UnmodifiableFloat64ListView extends UnmodifiableListBase<double>
     with _UnmodifiableListMixin<double, Float64List, Float64List>
     implements Float64List {
diff --git a/tools/VERSION b/tools/VERSION
index 02e544a..c27657f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 17
+PRERELEASE 18
 PRERELEASE_PATCH 0
\ No newline at end of file