Version 2.19.0-4.0.dev

Merge commit '54b7f4b72a1701f8f9a0334c94ce6f59732bd261' into 'dev'
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index f6beb54..32a7b10 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -454,7 +454,7 @@
       /// A helper that performs the context rebuild and waits for all watchers
       /// to be fully initialized.
       Future<void> performContextRebuild() async {
-        _destroyAnalysisContexts();
+        await _destroyAnalysisContexts();
         _fileContentCache.invalidateAll();
 
         var watchers = <ResourceWatcher>[];
@@ -610,7 +610,6 @@
 
   /// Clean up and destroy the context associated with the given folder.
   void _destroyAnalysisContext(DriverBasedAnalysisContext context) {
-    context.driver.dispose();
     var rootFolder = context.contextRoot.root;
     var watched = bazelWatchedPathsPerFolder.remove(rootFolder);
     if (watched != null) {
@@ -623,15 +622,16 @@
     driverMap.remove(rootFolder);
   }
 
-  void _destroyAnalysisContexts() {
-    var collection = _collection;
+  Future<void> _destroyAnalysisContexts() async {
+    final collection = _collection;
     if (collection != null) {
       for (final subscription in watcherSubscriptions) {
-        subscription.cancel();
+        await subscription.cancel();
       }
-      for (var analysisContext in collection.contexts) {
+      for (final analysisContext in collection.contexts) {
         _destroyAnalysisContext(analysisContext);
       }
+      await collection.dispose();
       callbacks.afterContextsDestroyed();
     }
   }
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index 6817bb5..5799297 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -72,6 +72,7 @@
   exclude:
     - 'samples/**'
 ''');
+    await pumpEventQueue(times: 5000);
     var file = newFile('$testPackageRootPath/samples/sample.dart', '');
     // attempt to set priority file
     await _setPriorityFile(file);
@@ -90,6 +91,7 @@
   exclude:
     - 'samples/**'
 ''');
+    await pumpEventQueue(times: 5000);
     // attempt to set priority file
     await _setPriorityFile(sampleFile);
     _verifyPriorityFiles(sampleFile);
@@ -107,6 +109,7 @@
   exclude:
     - 'child/samples/**'
 ''');
+    await pumpEventQueue(times: 5000);
     // attempt to set priority file
     await _setPriorityFile(sampleFile);
     _verifyPriorityFiles(sampleFile);
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 1c94ed1..473113c 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -58,7 +58,7 @@
 dart_package(null_safety = True)
 ''');
 
-    await pumpEventQueue();
+    await pumpEventQueue(times: 5000);
     await server.onAnalysisComplete;
 
     // We have null safety enabled, so no errors.
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index 4d289c7..76318ea 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -203,10 +203,6 @@
   }
 
   Future<void> test_OK_genericFunctionType() async {
-    newAnalysisOptionsYamlFile(testPackageRootPath, '''
-analyzer:
-  strong-mode: true
-''');
     addTestFile('''
 class C {
   void caller() {
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 06ad142b..eadd2aa 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -262,11 +262,12 @@
 
     // Send an edit request immediately after the refactor request.
     final req1 = executeCodeAction(codeAction);
-    await replaceFile(100, mainFileUri, 'new test content');
+    final req2 = replaceFile(100, mainFileUri, 'new test content');
 
     // Expect the first to fail because of the modified content.
     await expectLater(
         req1, throwsA(isResponseError(ErrorCodes.ContentModified)));
+    await req2;
   }
 
   Future<void> test_filtersCorrectly() async {
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index d9acebe..fcf0e15 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -167,7 +167,7 @@
   @override
   Future sendNotificationToServer(NotificationMessage notification) async {
     channel.sendNotificationToServer(notification);
-    await pumpEventQueue();
+    await pumpEventQueue(times: 5000);
   }
 
   @override
diff --git a/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart b/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
index 1c1ceb2..6a2db5b 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/directive_uri_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer_utilities/check/check.dart';
+import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../../client/completion_driver_test.dart';
@@ -59,6 +60,7 @@
     required void Function(CompletionResponseForTesting response) validator,
   }) async {
     _configurePackagesFooBar();
+    await pumpEventQueue(times: 5000);
 
     {
       var response = await getTestCodeSuggestions('''
diff --git a/pkg/analyzer/lib/dart/constant/value.dart b/pkg/analyzer/lib/dart/constant/value.dart
index 12c83db..e396610 100644
--- a/pkg/analyzer/lib/dart/constant/value.dart
+++ b/pkg/analyzer/lib/dart/constant/value.dart
@@ -64,6 +64,9 @@
   /// would return `false` from [hasKnownValue].
   DartType? get type;
 
+  /// If this object is the value of a constant variable, the variable.
+  VariableElement? get variable;
+
   /// Return a representation of the value of the field with the given [name].
   ///
   /// Return `null` if either the object being represented does not have a field
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 57556ad..32454a3 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -525,6 +525,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithAugmentation extends DirectiveUriWithSource {
+  /// The library augmentation referenced by the [source].
   LibraryAugmentationElement get augmentation;
 }
 
@@ -532,6 +533,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithLibrary extends DirectiveUriWithSource {
+  /// The library referenced by the [source].
   LibraryElement get library;
 }
 
@@ -540,6 +542,7 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithRelativeUri
     extends DirectiveUriWithRelativeUriString {
+  /// The relative URI, parsed from [relativeUriString].
   Uri get relativeUri;
 }
 
@@ -547,6 +550,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithRelativeUriString extends DirectiveUri {
+  /// The relative URI string specified in code.
   String get relativeUriString;
 }
 
@@ -554,6 +558,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithSource extends DirectiveUriWithRelativeUri {
+  /// The result of resolving [relativeUri] against the enclosing URI.
   Source get source;
 }
 
@@ -561,6 +566,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DirectiveUriWithUnit extends DirectiveUriWithSource {
+  /// The unit referenced by the [source].
   CompilationUnitElement get unit;
 }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index fd8131d..c7cfdc0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -140,16 +140,16 @@
     throw StateError('Unable to find the context to $path');
   }
 
-  void dispose({
+  Future<void> dispose({
     bool forTesting = false,
-  }) {
-    for (var analysisContext in contexts) {
-      analysisContext.driver.dispose();
+  }) async {
+    for (final analysisContext in contexts) {
+      await analysisContext.driver.dispose2();
     }
-    macroExecutor.close();
+    await macroExecutor.close();
     // If there are other collections, they will have to start it again.
     if (!forTesting) {
-      KernelCompilationService.dispose();
+      await KernelCompilationService.dispose();
     }
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 6a3129d..fde98ef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -85,7 +85,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 232;
+  static const int DATA_VERSION = 234;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
@@ -197,6 +197,10 @@
   final _unitElementRequestedFiles =
       <String, List<Completer<SomeUnitElementResult>>>{};
 
+  /// The list of dispose requests, added in [dispose2], almost always empty.
+  /// We expect that at most one is added, at the very end of the life cycle.
+  final List<Completer<void>> _disposeRequests = [];
+
   /// The controller for the [results] stream.
   final _resultController = StreamController<Object>();
 
@@ -397,6 +401,9 @@
 
   @override
   AnalysisDriverPriority get workPriority {
+    if (_disposeRequests.isNotEmpty) {
+      return AnalysisDriverPriority.interactive;
+    }
     if (_resolveForCompletionRequests.isNotEmpty) {
       return AnalysisDriverPriority.completion;
     }
@@ -581,12 +588,21 @@
     return _discoverAvailableFilesTask!.completer.future;
   }
 
+  @Deprecated('Use dispose2() instead')
   @override
   void dispose() {
     _scheduler.remove(this);
     clearLibraryContext();
   }
 
+  @override
+  Future<void> dispose2() async {
+    final completer = Completer<void>();
+    _disposeRequests.add(completer);
+    _scheduler.notify(this);
+    return completer.future;
+  }
+
   /// Return the cached [ResolvedUnitResult] for the Dart file with the given
   /// [path]. If there is no cached result, return `null`. Usually only results
   /// of priority files are cached.
@@ -1649,6 +1665,17 @@
     return _resourceProvider.pathContext.isAbsolute(path);
   }
 
+  Future<void> _maybeDispose() async {
+    if (_disposeRequests.isNotEmpty) {
+      _scheduler.remove(this);
+      clearLibraryContext();
+
+      for (final completer in _disposeRequests.toList()) {
+        completer.complete();
+      }
+    }
+  }
+
   /// We detected that one of the required `dart` libraries is missing.
   /// Return the empty analysis result with the error.
   AnalysisResult _newMissingDartLibraryResult(
@@ -1908,8 +1935,12 @@
   void addFile(String path);
 
   /// Notify the driver that the client is going to stop using it.
+  @Deprecated('Use dispose2() instead')
   void dispose();
 
+  /// Notify the driver that the client is going to stop using it.
+  Future<void> dispose2();
+
   /// Perform a single chunk of work and produce [results].
   Future<void> performWork();
 }
@@ -2055,6 +2086,12 @@
 
       await _hasWork.signal;
 
+      for (final driver in _drivers.toList()) {
+        if (driver is AnalysisDriver) {
+          await driver._maybeDispose();
+        }
+      }
+
       for (var driver in _drivers) {
         if (driver is AnalysisDriver) {
           driver._applyPendingFileChanges();
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index f370099..2fcc9f2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -952,6 +952,8 @@
       } else if (directive is AugmentationImportDirectiveImpl) {
         augmentations.add(
           UnlinkedImportAugmentationDirective(
+            augmentKeywordOffset: directive.augmentKeyword.offset,
+            importKeywordOffset: directive.importKeyword.offset,
             uri: directive.uri.stringValue,
           ),
         );
@@ -966,6 +968,8 @@
         final uriStr = uri.stringValue;
         if (uriStr != null) {
           libraryAugmentationDirective = UnlinkedLibraryAugmentationDirective(
+            augmentKeywordOffset: directive.augmentKeyword.offset,
+            libraryKeywordOffset: directive.libraryKeyword.offset,
             uri: uriStr,
             uriRange: UnlinkedSourceRange(
               offset: uri.offset,
@@ -1831,29 +1835,14 @@
     file._fsState._libraryNameToFiles.add(this);
   }
 
-  /// The list of files that this library consists of, i.e. this library file
-  /// itself, its [parts], and augmentations.
-  List<FileState> get files {
-    final files = [
-      file,
-    ];
+  /// All augmentations referenced by this library, in the depth-first
+  /// pre-order traversal order.
+  List<AugmentationFileStateKind> get allAugmentations {
+    final result = <AugmentationFileStateKind>[];
 
-    // TODO(scheglov) When we include only valid parts, use this instead.
-    final includeOnlyValidParts = 0 > 1;
-    for (final part in parts) {
-      if (part is PartDirectiveWithFile) {
-        if (includeOnlyValidParts) {
-          files.addIfNotNull(part.includedPart?.file);
-        } else {
-          files.add(part.includedFile);
-        }
-      }
-    }
-
-    // TODO(scheglov) Test how augmentations affect signatures.
     void visitAugmentations(LibraryOrAugmentationFileKind kind) {
       if (kind is AugmentationFileStateKind) {
-        files.add(kind.file);
+        result.add(kind);
       }
       for (final import in kind.augmentations) {
         if (import is ImportAugmentationDirectiveWithFile) {
@@ -1866,6 +1855,23 @@
     }
 
     visitAugmentations(this);
+    return result;
+  }
+
+  /// The list of files that this library consists of, i.e. this library file
+  /// itself, its [parts], and augmentations.
+  List<FileState> get files {
+    final files = [
+      file,
+    ];
+
+    for (final part in parts) {
+      if (part is PartDirectiveWithFile) {
+        files.addIfNotNull(part.includedPart?.file);
+      }
+    }
+
+    files.addAll(allAugmentations.map((e) => e.file));
 
     return files;
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index 1cfb843..40aacde 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -139,16 +139,19 @@
 
   @override
   List<_LibraryNode> computeDependencies() {
-    final referencedLibraries = {
-      ...kind.imports
-          .whereType<ImportDirectiveWithFile>()
-          .map((import) => import.importedLibrary)
-          .whereNotNull(),
-      ...kind.exports
-          .whereType<ExportDirectiveWithFile>()
-          .map((export) => export.exportedLibrary)
-          .whereNotNull(),
-    };
+    final referencedLibraries = {kind, ...kind.allAugmentations}
+        .map((container) => [
+              ...container.imports
+                  .whereType<ImportDirectiveWithFile>()
+                  .map((import) => import.importedLibrary),
+              ...container.exports
+                  .whereType<ExportDirectiveWithFile>()
+                  .map((export) => export.exportedLibrary),
+            ])
+        .expand((libraries) => libraries)
+        .whereNotNull()
+        .toSet();
+
     return referencedLibraries.map(walker.getNode).toList();
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
index b487c95..021d3e7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
@@ -161,9 +161,13 @@
 }
 
 class UnlinkedImportAugmentationDirective {
+  final int augmentKeywordOffset;
+  final int importKeywordOffset;
   final String? uri;
 
   UnlinkedImportAugmentationDirective({
+    required this.augmentKeywordOffset,
+    required this.importKeywordOffset,
     required this.uri,
   });
 
@@ -171,11 +175,15 @@
     SummaryDataReader reader,
   ) {
     return UnlinkedImportAugmentationDirective(
+      augmentKeywordOffset: reader.readUInt30(),
+      importKeywordOffset: reader.readUInt30(),
       uri: reader.readOptionalStringUtf8(),
     );
   }
 
   void write(BufferedSink sink) {
+    sink.writeUInt30(augmentKeywordOffset);
+    sink.writeUInt30(importKeywordOffset);
     sink.writeOptionalStringUtf8(uri);
   }
 }
@@ -264,10 +272,14 @@
 }
 
 class UnlinkedLibraryAugmentationDirective {
+  final int augmentKeywordOffset;
+  final int libraryKeywordOffset;
   final String? uri;
   final UnlinkedSourceRange uriRange;
 
   UnlinkedLibraryAugmentationDirective({
+    required this.augmentKeywordOffset,
+    required this.libraryKeywordOffset,
     required this.uri,
     required this.uriRange,
   });
@@ -276,12 +288,16 @@
     SummaryDataReader reader,
   ) {
     return UnlinkedLibraryAugmentationDirective(
+      augmentKeywordOffset: reader.readUInt30(),
+      libraryKeywordOffset: reader.readUInt30(),
       uri: reader.readOptionalStringUtf8(),
       uriRange: UnlinkedSourceRange.read(reader),
     );
   }
 
   void write(BufferedSink sink) {
+    sink.writeUInt30(augmentKeywordOffset);
+    sink.writeUInt30(libraryKeywordOffset);
     sink.writeOptionalStringUtf8(uri);
     uriRange.write(sink);
   }
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 4621e73..5b205c4 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -107,6 +107,9 @@
                 constantInitializer,
                 [dartObject.type, constant.type]);
           }
+
+          // Associate with the variable.
+          dartObject = DartObjectImpl.forVariable(dartObject, constant);
         }
 
         if (dartObject != null) {
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 04506a4..dabfac8 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -159,8 +159,18 @@
   /// The state of the object.
   final InstanceState _state;
 
+  @override
+  final VariableElement? variable;
+
   /// Initialize a newly created object to have the given [type] and [_state].
-  DartObjectImpl(this._typeSystem, this.type, this._state);
+  DartObjectImpl(this._typeSystem, this.type, this._state, {this.variable});
+
+  /// Creates a duplicate instance of [other], tied to [variable].
+  factory DartObjectImpl.forVariable(
+      DartObjectImpl other, VariableElement variable) {
+    return DartObjectImpl(other._typeSystem, other.type, other._state,
+        variable: variable);
+  }
 
   /// Create an object to represent an unknown value.
   factory DartObjectImpl.validWithUnknownValue(
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 4c718a3..cbe272d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3920,7 +3920,7 @@
   @override
   final LibraryOrAugmentationElementImpl augmented;
 
-  LibraryElementLinkedData? linkedData;
+  LibraryAugmentationElementLinkedData? linkedData;
 
   LibraryAugmentationElementImpl({
     required this.augmented,
@@ -3932,6 +3932,12 @@
   List<ExtensionElement> get accessibleExtensions => throw UnimplementedError();
 
   @override
+  List<AugmentationImportElement> get augmentationImports {
+    linkedData?.read(this);
+    return super.augmentationImports;
+  }
+
+  @override
   List<ExportElement2> get exports2 {
     linkedData?.read(this);
     return _exports2;
@@ -4043,6 +4049,12 @@
   List<ExtensionElement> get accessibleExtensions => scope.extensions;
 
   @override
+  List<AugmentationImportElement> get augmentationImports {
+    linkedData?.read(this);
+    return super.augmentationImports;
+  }
+
+  @override
   CompilationUnitElementImpl get enclosingUnit {
     return _definingCompilationUnit;
   }
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index f0c804e..841cead 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -350,10 +350,55 @@
   }
 }
 
-class LibraryElementLinkedData extends ElementLinkedData<LibraryElementImpl> {
+class LibraryAugmentationElementLinkedData
+    extends LibraryOrAugmentationElementLinkedData<
+        LibraryAugmentationElementImpl> {
+  LibraryAugmentationElementLinkedData({
+    required super.reference,
+    required super.libraryReader,
+    required super.unitElement,
+    required super.offset,
+  });
+
+  @override
+  void read(ElementImpl element) {
+    final libraryData = element.library?.linkedData;
+    if (libraryData != null && !libraryData._isLocked) {
+      super.read(element);
+    }
+  }
+}
+
+class LibraryElementLinkedData
+    extends LibraryOrAugmentationElementLinkedData<LibraryElementImpl> {
+  LibraryElementLinkedData({
+    required super.reference,
+    required super.libraryReader,
+    required super.unitElement,
+    required super.offset,
+  });
+
+  @override
+  void _readAdditional(element, reader) {
+    for (final part in element.parts2) {
+      part as PartElementImpl;
+      part.metadata = reader._readAnnotationList(
+        unitElement: unitElement,
+      );
+    }
+
+    element.entryPoint = reader.readElement() as FunctionElement?;
+  }
+}
+
+class LibraryOrAugmentationElementLinkedData<
+    E extends LibraryOrAugmentationElementImpl> extends ElementLinkedData<E> {
   ApplyConstantOffsets? applyConstantOffsets;
 
-  LibraryElementLinkedData({
+  /// When we are applying offsets to a library, we want to lock it.
+  bool _isLocked = false;
+
+  LibraryOrAugmentationElementLinkedData({
     required Reference reference,
     required LibraryReader libraryReader,
     required CompilationUnitElementImpl unitElement,
@@ -364,6 +409,23 @@
     return _libraryReader._elementFactory;
   }
 
+  void lock() {
+    assert(!_isLocked);
+    _isLocked = true;
+  }
+
+  @override
+  void read(ElementImpl element) {
+    if (!_isLocked) {
+      super.read(element);
+    }
+  }
+
+  void unlock() {
+    assert(_isLocked);
+    _isLocked = false;
+  }
+
   @override
   void _read(element, reader) {
     element.metadata = reader._readAnnotationList(
@@ -392,17 +454,14 @@
       }
     }
 
-    for (final part in element.parts2) {
-      part as PartElementImpl;
-      part.metadata = reader._readAnnotationList(
-        unitElement: unitElement,
-      );
-    }
+    // TODO(scheglov) metadata on augmentation imports
 
-    element.entryPoint = reader.readElement() as FunctionElement?;
+    _readAdditional(element, reader);
 
     applyConstantOffsets?.perform();
   }
+
+  void _readAdditional(E element, ResolutionReader reader) {}
 }
 
 class LibraryReader {
@@ -451,33 +510,11 @@
     libraryElement.reference = _reference;
 
     libraryElement.languageVersion = _readLanguageVersion();
-    libraryElement.imports2 = _reader.readTypedList(() {
-      return _readImportElement(
-        libraryElement: libraryElement,
-      );
-    });
-    libraryElement.exports2 = _reader.readTypedList(() {
-      return _readExportElement(
-        libraryElement: libraryElement,
-      );
-    });
-    libraryElement.augmentationImports = _reader.readTypedList(() {
-      return _readAugmentationImportElement(
-        libraryElement: libraryElement,
-      );
-    });
+    _readLibraryOrAugmentationElement(libraryElement);
     LibraryElementFlags.read(_reader, libraryElement);
 
-    for (final import in libraryElement.imports2) {
-      final prefixElement = import.prefix?.element;
-      if (prefixElement is PrefixElementImpl) {
-        libraryElement.encloseElement(prefixElement);
-      }
-    }
-
     libraryElement.definingCompilationUnit = _readUnitElement(
-      libraryElement: libraryElement,
-      librarySource: librarySource,
+      containerSource: librarySource,
       unitSource: librarySource,
     );
 
@@ -516,12 +553,10 @@
 
   LibraryAugmentationElementImpl _readAugmentationElement({
     required LibraryOrAugmentationElementImpl augmented,
-    required LibraryElementImpl libraryElement,
     required Source unitSource,
   }) {
     final definingUnit = _readUnitElement(
-      libraryElement: libraryElement,
-      librarySource: unitSource,
+      containerSource: unitSource,
       unitSource: unitSource,
     );
 
@@ -531,14 +566,24 @@
     );
     augmentation.definingCompilationUnit = definingUnit;
 
+    final resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
+    _readLibraryOrAugmentationElement(augmentation);
+
+    augmentation.linkedData = LibraryAugmentationElementLinkedData(
+      reference: _reference,
+      libraryReader: this,
+      unitElement: definingUnit,
+      offset: resolutionOffset,
+    );
+
     return augmentation;
   }
 
   AugmentationImportElementImpl _readAugmentationImportElement({
-    required LibraryElementImpl libraryElement,
+    required LibraryOrAugmentationElementImpl container,
   }) {
     final uri = _readDirectiveUri(
-      libraryElement: libraryElement,
+      container: container,
     );
     return AugmentationImportElementImpl(
       importKeywordOffset: -1, // TODO(scheglov) implement, test
@@ -635,7 +680,7 @@
   }
 
   DirectiveUri _readDirectiveUri({
-    required LibraryElementImpl libraryElement,
+    required LibraryOrAugmentationElementImpl container,
   }) {
     DirectiveUriWithRelativeUriStringImpl readWithRelativeUriString() {
       final relativeUriString = _reader.readStringReference();
@@ -679,8 +724,7 @@
       case DirectiveUriKind.withAugmentation:
         final parent = readWithSource();
         final augmentation = _readAugmentationElement(
-          augmented: libraryElement,
-          libraryElement: libraryElement,
+          augmented: container,
           unitSource: parent.source,
         );
         return DirectiveUriWithAugmentationImpl(
@@ -699,8 +743,7 @@
       case DirectiveUriKind.withUnit:
         final parent = readWithSource();
         final unitElement = _readUnitElement(
-          libraryElement: libraryElement,
-          librarySource: libraryElement.source,
+          containerSource: container.source,
           unitSource: parent.source,
         );
         return DirectiveUriWithUnitImpl(
@@ -786,10 +829,10 @@
   }
 
   ExportElement2Impl _readExportElement({
-    required LibraryElementImpl libraryElement,
+    required LibraryOrAugmentationElementImpl container,
   }) {
     final uri = _readDirectiveUri(
-      libraryElement: libraryElement,
+      container: container,
     );
     // TODO(scheglov) pass to the constructor
     final combinators = _reader.readTypedList(_readNamespaceCombinator);
@@ -941,10 +984,10 @@
   }
 
   ImportElement2Impl _readImportElement({
-    required LibraryElementImpl libraryElement,
+    required LibraryOrAugmentationElementImpl container,
   }) {
     final uri = _readDirectiveUri(
-      libraryElement: libraryElement,
+      container: container,
     );
     final prefix = _readImportElementPrefix();
     final combinators = _reader.readTypedList(_readNamespaceCombinator);
@@ -1002,6 +1045,35 @@
     return LibraryLanguageVersion(package: package, override: override);
   }
 
+  void _readLibraryOrAugmentationElement(
+    LibraryOrAugmentationElementImpl container,
+  ) {
+    container.imports2 = _reader.readTypedList(() {
+      return _readImportElement(
+        container: container,
+      );
+    });
+
+    container.exports2 = _reader.readTypedList(() {
+      return _readExportElement(
+        container: container,
+      );
+    });
+
+    container.augmentationImports = _reader.readTypedList(() {
+      return _readAugmentationImportElement(
+        container: container,
+      );
+    });
+
+    for (final import in container.imports2) {
+      final prefixElement = import.prefix?.element;
+      if (prefixElement is PrefixElementImpl) {
+        container.encloseElement(prefixElement);
+      }
+    }
+  }
+
   List<MethodElementImpl> _readMethods(
     CompilationUnitElementImpl unitElement,
     ElementImpl enclosingElement,
@@ -1160,7 +1232,7 @@
     required LibraryElementImpl libraryElement,
   }) {
     final uri = _readDirectiveUri(
-      libraryElement: libraryElement,
+      container: libraryElement,
     );
 
     return PartElementImpl(
@@ -1383,15 +1455,14 @@
   }
 
   CompilationUnitElementImpl _readUnitElement({
-    required LibraryElementImpl libraryElement,
-    required Source librarySource,
+    required Source containerSource,
     required Source unitSource,
   }) {
     var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
 
     var unitElement = CompilationUnitElementImpl(
       source: unitSource,
-      librarySource: librarySource,
+      librarySource: containerSource,
       lineInfo: LineInfo([0]),
     );
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index c8b469e..43a2151 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -101,13 +101,7 @@
     _sink._writeStringReference(libraryElement.name);
     _writeFeatureSet(libraryElement.featureSet);
     _writeLanguageVersion(libraryElement.languageVersion);
-    _resolutionSink._writeAnnotationList(libraryElement.metadata);
-    _writeList(libraryElement.imports2, _writeImportElement);
-    _writeList(libraryElement.exports2, _writeExportElement);
-    _writeList(
-      libraryElement.augmentationImports,
-      _writeAugmentationImportElement,
-    );
+    _writeLibraryOrAugmentationElement(libraryElement);
     for (final partElement in libraryElement.parts2) {
       _resolutionSink._writeAnnotationList(partElement.metadata);
     }
@@ -130,6 +124,8 @@
   void _writeAugmentationElement(LibraryAugmentationElement augmentation) {
     augmentation as LibraryAugmentationElementImpl;
     _writeUnitElement(augmentation.definingCompilationUnit);
+    _sink.writeUInt30(_resolutionSink.offset);
+    _writeLibraryOrAugmentationElement(augmentation);
   }
 
   void _writeAugmentationImportElement(AugmentationImportElement element) {
@@ -371,6 +367,18 @@
     }
   }
 
+  void _writeLibraryOrAugmentationElement(
+    LibraryOrAugmentationElementImpl container,
+  ) {
+    _resolutionSink._writeAnnotationList(container.metadata);
+    _writeList(container.imports2, _writeImportElement);
+    _writeList(container.exports2, _writeExportElement);
+    _writeList(
+      container.augmentationImports,
+      _writeAugmentationImportElement,
+    );
+  }
+
   void _writeList<T>(List<T> elements, void Function(T) writeElement) {
     _sink.writeUInt30(elements.length);
     for (var element in elements) {
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 2451694..c21d763 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -21,6 +21,7 @@
 
 class ElementBuilder extends ThrowingAstVisitor<void> {
   final LibraryBuilder _libraryBuilder;
+  final LibraryOrAugmentationElementImpl _container;
   final CompilationUnitElementImpl _unitElement;
 
   var _isFirstLibraryDirective = true;
@@ -34,14 +35,14 @@
 
   ElementBuilder({
     required LibraryBuilder libraryBuilder,
+    required LibraryOrAugmentationElementImpl container,
     required Reference unitReference,
     required CompilationUnitElementImpl unitElement,
   })  : _libraryBuilder = libraryBuilder,
+        _container = container,
         _unitElement = unitElement,
         _enclosingContext = _EnclosingContext(unitReference, unitElement);
 
-  LibraryElementImpl get _libraryElement => _libraryBuilder.element;
-
   Linker get _linker => _libraryBuilder.linker;
 
   void buildDeclarationElements(CompilationUnit unit) {
@@ -58,7 +59,7 @@
     _unitElement.typeAliases = _enclosingContext.typeAliases;
   }
 
-  /// Build exports and imports, metadata into [_libraryElement].
+  /// Build exports and imports, metadata into [_container].
   void buildLibraryElementChildren(CompilationUnit unit) {
     unit.directives.accept(this);
 
@@ -66,12 +67,12 @@
       _isFirstLibraryDirective = false;
       var firstDirective = unit.directives.firstOrNull;
       if (firstDirective != null) {
-        _libraryElement.documentationComment = getCommentNodeRawText(
+        _container.documentationComment = getCommentNodeRawText(
           firstDirective.documentationComment,
         );
         var firstDirectiveMetadata = firstDirective.element?.metadata;
         if (firstDirectiveMetadata != null) {
-          _libraryElement.metadata = firstDirectiveMetadata;
+          _container.metadata = firstDirectiveMetadata;
         }
       }
     }
@@ -80,7 +81,7 @@
   @override
   void visitAugmentationImportDirective(AugmentationImportDirective node) {
     final index = _augmentationDirectiveIndex++;
-    final element = _libraryElement.augmentationImports[index];
+    final element = _container.augmentationImports[index];
     element as AugmentationImportElementImpl;
     element.metadata = _buildAnnotations(node.metadata);
   }
@@ -375,7 +376,7 @@
   @override
   void visitExportDirective(covariant ExportDirectiveImpl node) {
     final index = _exportDirectiveIndex++;
-    final exportElement = _libraryElement.exports2[index];
+    final exportElement = _container.exports2[index];
     exportElement as ExportElement2Impl;
     exportElement.metadata = _buildAnnotations(node.metadata);
     node.element = exportElement;
@@ -742,7 +743,7 @@
   @override
   void visitImportDirective(covariant ImportDirectiveImpl node) {
     final index = _importDirectiveIndex++;
-    final importElement = _libraryElement.imports2[index];
+    final importElement = _container.imports2[index];
     importElement as ImportElement2Impl;
     importElement.metadata = _buildAnnotations(node.metadata);
     node.element = importElement;
@@ -758,11 +759,11 @@
   void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
     if (_isFirstLibraryDirective) {
       _isFirstLibraryDirective = false;
-      node.element = _libraryElement;
-      _libraryElement.documentationComment = getCommentNodeRawText(
+      node.element = _container;
+      _container.documentationComment = getCommentNodeRawText(
         node.documentationComment,
       );
-      _libraryElement.metadata = _buildAnnotations(node.metadata);
+      _container.metadata = _buildAnnotations(node.metadata);
     }
   }
 
@@ -882,15 +883,21 @@
 
   @override
   void visitPartDirective(PartDirective node) {
-    final index = _partDirectiveIndex++;
-    final partElement = _libraryElement.parts2[index];
-    partElement as PartElementImpl;
-    partElement.metadata = _buildAnnotations(node.metadata);
+    final libraryElement = _container;
+    if (libraryElement is LibraryElementImpl) {
+      final index = _partDirectiveIndex++;
+      final partElement = libraryElement.parts2[index];
+      partElement as PartElementImpl;
+      partElement.metadata = _buildAnnotations(node.metadata);
+    }
   }
 
   @override
   void visitPartOfDirective(PartOfDirective node) {
-    _libraryElement.hasPartOfDirective = true;
+    final libraryElement = _container;
+    if (libraryElement is LibraryElementImpl) {
+      libraryElement.hasPartOfDirective = true;
+    }
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 26451c7..95cb3b4 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -67,6 +67,7 @@
       throw StateError('Unexpected recursion.');
     }
     _elementFactory.isApplyingInformativeData = true;
+    libraryElement.linkedData?.lock();
 
     var unitElements = libraryElement.units;
     for (var i = 0; i < unitElements.length; i++) {
@@ -139,6 +140,7 @@
       }
     }
 
+    libraryElement.linkedData?.unlock();
     _elementFactory.isApplyingInformativeData = false;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 0ad9d076..7c5be86 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -33,6 +33,7 @@
     required super.reference,
     required super.node,
     required super.element,
+    required super.container,
   });
 }
 
@@ -149,6 +150,7 @@
     for (var linkingUnit in units) {
       var elementBuilder = ElementBuilder(
         libraryBuilder: this,
+        container: linkingUnit.container,
         unitReference: linkingUnit.reference,
         unitElement: linkingUnit.element,
       );
@@ -239,6 +241,7 @@
 
     final elementBuilder = ElementBuilder(
       libraryBuilder: this,
+      container: element,
       unitReference: unitReference,
       unitElement: unitElement,
     );
@@ -348,6 +351,7 @@
 
     ElementBuilder(
       libraryBuilder: this,
+      container: element,
       unitReference: unitReference,
       unitElement: unitElement,
     ).buildDeclarationElements(unitNode);
@@ -359,6 +363,7 @@
       LinkingUnit(
         reference: unitReference,
         node: unitNode,
+        container: element,
         element: unitElement,
       ),
     );
@@ -438,17 +443,9 @@
             reference.getChild('@augmentation').getChild(importedFile.uriStr);
         _bindReference(unitReference, unitElement);
 
-        units.add(
-          DefiningLinkingUnit(
-            reference: unitReference,
-            node: unitNode,
-            element: unitElement,
-          ),
-        );
-
         final augmentation = LibraryAugmentationElementImpl(
           augmented: augmentedElement,
-          nameOffset: -1, // TODO(scheglov) fix it
+          nameOffset: importedAugmentation.directive.libraryKeywordOffset,
         );
         augmentation.definingCompilationUnit = unitElement;
 
@@ -463,6 +460,15 @@
           source: importedFile.source,
           augmentation: augmentation,
         );
+
+        units.add(
+          DefiningLinkingUnit(
+            reference: unitReference,
+            node: unitNode,
+            element: unitElement,
+            container: augmentation,
+          ),
+        );
       } else {
         uri = DirectiveUriWithSourceImpl(
           relativeUriString: state.uri.relativeUriStr,
@@ -487,7 +493,7 @@
     }
 
     return AugmentationImportElementImpl(
-      importKeywordOffset: -1, // TODO(scheglov) fix it
+      importKeywordOffset: state.directive.importKeywordOffset,
       uri: uri,
     );
   }
@@ -764,6 +770,7 @@
           reference: unitReference,
           node: libraryUnitNode,
           element: unitElement,
+          container: libraryElement,
         ),
       );
 
@@ -796,6 +803,7 @@
             LinkingUnit(
               reference: unitReference,
               node: partUnitNode,
+              container: libraryElement,
               element: unitElement,
             ),
           );
@@ -861,11 +869,13 @@
 class LinkingUnit {
   final Reference reference;
   final ast.CompilationUnitImpl node;
+  final LibraryOrAugmentationElementImpl container;
   final CompilationUnitElementImpl element;
 
   LinkingUnit({
     required this.reference,
     required this.node,
+    required this.container,
     required this.element,
   });
 }
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index e4a67c3..bc1414f 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -66,6 +66,7 @@
     var x_result = findElement.topVar('x').evaluationResult;
     assertDartObjectText(x_result.value, r'''
 dynamic <unknown>
+  variable: self::@variable::x
 ''');
   }
 
@@ -404,12 +405,14 @@
 E
   _name: String v1
   index: int 0
+  variable: self::@variable::x1
 ''');
 
     _assertTopVarConstValue('x2', r'''
 E
   _name: String v2
   index: int 1
+  variable: self::@variable::x2
 ''');
   }
 
@@ -430,7 +433,9 @@
     _name: String v1
     a: int 42
     index: int 0
+    variable: self::@enum::E::@field::v1
   index: int 1
+  variable: self::@enum::E::@field::v2
 ''');
   }
 
@@ -452,6 +457,7 @@
   _name: String v1
   f: double 10.0
   index: int 0
+  variable: self::@variable::x1
 ''');
 
     _assertTopVarConstValue('x2', r'''
@@ -459,6 +465,7 @@
   _name: String v2
   f: int 20
   index: int 1
+  variable: self::@variable::x2
 ''');
   }
 
@@ -482,6 +489,7 @@
   _name: String v1
   f: int 10
   index: int 0
+  variable: self::@variable::x1
 ''');
 
     _assertTopVarConstValue('x2', r'''
@@ -489,6 +497,7 @@
   _name: String v2
   f: int 20
   index: int 1
+  variable: self::@variable::x2
 ''');
 
     _assertTopVarConstValue('x3', r'''
@@ -496,6 +505,7 @@
   _name: String v3
   f: String abc
   index: int 2
+  variable: self::@variable::x3
 ''');
   }
 
@@ -594,6 +604,7 @@
     a: int 1
     b: int 2
   c: int 3
+  variable: self::@variable::x
 ''');
   }
 
@@ -620,6 +631,7 @@
     a: int 1
     b: int 2
   c: int 3
+  variable: self::@variable::x
 ''');
   }
 
@@ -644,6 +656,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -668,6 +681,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -692,6 +706,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -716,6 +731,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -740,6 +756,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -764,6 +781,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -788,6 +806,7 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
 ''');
   }
 
@@ -812,6 +831,47 @@
   (super): A
     a: int 1
   b: int 2
+  variable: self::@variable::x
+''');
+  }
+
+  test_variable_alias() async {
+    await resolveTestCode('''
+const a = 42;
+const b = a;
+''');
+
+    final a_result = findElement.topVar('a').evaluationResult;
+    assertDartObjectText(a_result.value, r'''
+int 42
+  variable: self::@variable::a
+''');
+
+    final b_result = findElement.topVar('b').evaluationResult;
+    assertDartObjectText(b_result.value, r'''
+int 42
+  variable: self::@variable::b
+''');
+  }
+
+  test_variable_list_elements() async {
+    await resolveTestCode('''
+const a = 0;
+const b = 2;
+const c = [a, 1, b];
+''');
+
+    final b_result = findElement.topVar('c').evaluationResult;
+    assertDartObjectText(b_result.value, r'''
+List
+  elementType: int
+  elements
+    int 0
+      variable: self::@variable::a
+    int 1
+    int 2
+      variable: self::@variable::b
+  variable: self::@variable::c
 ''');
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
index e73428f..b484abe 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -64,7 +64,7 @@
     assertErrorsInList(await _computeTestFileErrors(), []);
 
     // Configure `strict-casts: true`.
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
     writeTestPackageAnalysisOptionsFile(
       AnalysisOptionsFileConfig(
         strictCasts: true,
@@ -155,7 +155,7 @@
     // Dispose the collection, with its driver.
     // The next analysis will recreate it.
     // We will reuse the byte store, so can reuse summaries.
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     newFile(testFilePath, r'''
 class A {
@@ -193,7 +193,7 @@
     // Dispose the collection, with its driver.
     // The next analysis will recreate it.
     // We will reuse the byte store, so can reuse summaries.
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     newFile(testFilePath, r'''
 void f() {
@@ -299,7 +299,7 @@
 
     // We will recreate it with new pubspec.yaml content.
     // But we will reuse the byte store, so can reuse summaries.
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     // Add dependency on `package:aaa`.
     writeTestPackagePubspecYamlFile(
@@ -341,7 +341,7 @@
 
     // We will recreate it with new analysis options.
     // But we will reuse the byte store, so can reuse summaries.
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     // Configure to run a lint.
     writeTestPackageAnalysisOptionsFile(
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index f158a29..0e05ff1 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -1491,6 +1491,150 @@
 ''');
   }
 
+  test_newFile_library_augmentations_imports() {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+    final c = newFile('$testPackageLibPath/c.dart', r'''
+import augment 'b.dart';
+''');
+
+    fileStateFor(c);
+
+    // `a.dart` is imported by the augmentation `b.dart`, so it becomes a
+    // dependency for the library `c.dart` cycle.
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: library_0
+        imports
+          library_3 dart:core synthetic
+        cycle_0
+          dependencies: dart:core
+          libraries: library_0
+          apiSignature_0
+          users: cycle_1
+      referencingFiles: file_1
+      unlinkedKey: k00
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: augmentation_1
+        augmented: library_2
+        library: library_2
+        imports
+          library_0
+          library_3 dart:core synthetic
+      referencingFiles: file_2
+      unlinkedKey: k01
+  /home/test/lib/c.dart
+    uri: package:test/c.dart
+    current
+      id: file_2
+      kind: library_2
+        imports
+          library_3 dart:core synthetic
+        augmentations
+          augmentation_1
+        cycle_1
+          dependencies: cycle_0 dart:core
+          libraries: library_2
+          apiSignature_1
+      unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+  }
+
+  test_newFile_library_augmentations_imports2() {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+    newFile('$testPackageLibPath/c.dart', r'''
+library augment 'd.dart';
+import augment 'b.dart';
+''');
+
+    final d = newFile('$testPackageLibPath/d.dart', r'''
+import augment 'c.dart';
+''');
+
+    fileStateFor(d);
+
+    // `a.dart` is transitively imported by augmentations into `d.dart`, so it
+    // becomes a dependency for the library `d.dart` cycle.
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: library_0
+        imports
+          library_4 dart:core synthetic
+        cycle_0
+          dependencies: dart:core
+          libraries: library_0
+          apiSignature_0
+          users: cycle_1
+      referencingFiles: file_1
+      unlinkedKey: k00
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: augmentation_1
+        augmented: augmentation_2
+        library: library_3
+        imports
+          library_0
+          library_4 dart:core synthetic
+      referencingFiles: file_2
+      unlinkedKey: k01
+  /home/test/lib/c.dart
+    uri: package:test/c.dart
+    current
+      id: file_2
+      kind: augmentation_2
+        augmented: library_3
+        library: library_3
+        imports
+          library_4 dart:core synthetic
+        augmentations
+          augmentation_1
+      referencingFiles: file_3
+      unlinkedKey: k02
+  /home/test/lib/d.dart
+    uri: package:test/d.dart
+    current
+      id: file_3
+      kind: library_3
+        imports
+          library_4 dart:core synthetic
+        augmentations
+          augmentation_2
+        cycle_1
+          dependencies: cycle_0 dart:core
+          libraries: library_3
+          apiSignature_1
+      unlinkedKey: k03
+libraryCycles
+elementFactory
+''');
+  }
+
   test_newFile_library_augmentations_invalidUri_cannotParse() async {
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import augment 'da:';
@@ -1711,7 +1855,7 @@
     sdkSummaryFile = await _writeSdkSummary();
     this.librarySummaryFiles = librarySummaryFiles;
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 export 'dart:async';
@@ -1804,7 +1948,7 @@
     sdkSummaryFile = await _writeSdkSummary();
     this.librarySummaryFiles = librarySummaryFiles;
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 export 'package:foo/foo2.dart';
@@ -2235,7 +2379,7 @@
     sdkSummaryFile = await _writeSdkSummary();
     this.librarySummaryFiles = librarySummaryFiles;
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import 'dart:async';
@@ -2327,7 +2471,7 @@
     sdkSummaryFile = await _writeSdkSummary();
     this.librarySummaryFiles = librarySummaryFiles;
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import 'package:foo/foo2.dart';
@@ -4063,6 +4207,90 @@
 ''');
   }
 
+  test_refresh_augmentation_renameClass() {
+    final a = newFile('$testPackageLibPath/a.dart', r'''
+library augment 'b.dart';
+class A {}
+''');
+
+    final b = newFile('$testPackageLibPath/b.dart', r'''
+import augment 'a.dart';
+''');
+
+    fileStateFor(b);
+
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: augmentation_0
+        augmented: library_1
+        library: library_1
+        imports
+          library_2 dart:core synthetic
+      referencingFiles: file_1
+      unlinkedKey: k00
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: library_1
+        imports
+          library_2 dart:core synthetic
+        augmentations
+          augmentation_0
+        cycle_0
+          dependencies: dart:core
+          libraries: library_1
+          apiSignature_0
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+
+    newFile(a.path, r'''
+library augment 'b.dart';
+class A2 {}
+''');
+    fileStateFor(a).refresh();
+
+    // The augmentation `a.dart` has a different unlinked key, and its
+    // refresh invalidated the library cycle `b.dart`, which has a differrent
+    // signature now.
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: augmentation_7
+        augmented: library_1
+        library: library_1
+        imports
+          library_2 dart:core synthetic
+      referencingFiles: file_1
+      unlinkedKey: k02
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: library_1
+        imports
+          library_2 dart:core synthetic
+        augmentations
+          augmentation_7
+        cycle_2
+          dependencies: dart:core
+          libraries: library_1
+          apiSignature_1
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+  }
+
   test_refresh_augmentation_to_library() async {
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import augment 'b.dart';
@@ -4480,6 +4708,124 @@
 ''');
   }
 
+  test_refresh_library_importedBy_augmentation() {
+    final a = newFile('$testPackageLibPath/a.dart', r'''
+class A {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'c.dart';
+import 'a.dart';
+''');
+
+    final c = newFile('$testPackageLibPath/c.dart', r'''
+import augment 'b.dart';
+''');
+
+    fileStateFor(c);
+
+    // `a.dart` is imported by the augmentation `b.dart`, so it is a dependency
+    // of `c.dart`.
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: library_0
+        imports
+          library_3 dart:core synthetic
+        cycle_0
+          dependencies: dart:core
+          libraries: library_0
+          apiSignature_0
+          users: cycle_1
+      referencingFiles: file_1
+      unlinkedKey: k00
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: augmentation_1
+        augmented: library_2
+        library: library_2
+        imports
+          library_0
+          library_3 dart:core synthetic
+      referencingFiles: file_2
+      unlinkedKey: k01
+  /home/test/lib/c.dart
+    uri: package:test/c.dart
+    current
+      id: file_2
+      kind: library_2
+        imports
+          library_3 dart:core synthetic
+        augmentations
+          augmentation_1
+        cycle_1
+          dependencies: cycle_0 dart:core
+          libraries: library_2
+          apiSignature_1
+      unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+
+    newFile(a.path, r'''
+class A2 {}
+''');
+    fileStateFor(a).refresh();
+
+    // Updated `a.dart` invalidates the library cycle for `c.dart`, both
+    // have now different signatures.
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/a.dart
+    uri: package:test/a.dart
+    current
+      id: file_0
+      kind: library_8
+        imports
+          library_3 dart:core synthetic
+        cycle_3
+          dependencies: dart:core
+          libraries: library_8
+          apiSignature_2
+          users: cycle_4
+      referencingFiles: file_1
+      unlinkedKey: k03
+  /home/test/lib/b.dart
+    uri: package:test/b.dart
+    current
+      id: file_1
+      kind: augmentation_1
+        augmented: library_2
+        library: library_2
+        imports
+          library_8
+          library_3 dart:core synthetic
+      referencingFiles: file_2
+      unlinkedKey: k01
+  /home/test/lib/c.dart
+    uri: package:test/c.dart
+    current
+      id: file_2
+      kind: library_2
+        imports
+          library_3 dart:core synthetic
+        augmentations
+          augmentation_1
+        cycle_4
+          dependencies: cycle_3 dart:core
+          libraries: library_2
+          apiSignature_3
+      unlinkedKey: k02
+libraryCycles
+elementFactory
+''');
+  }
+
   test_refresh_library_removePart_partOfName() async {
     newFile('$testPackageLibPath/a.dart', r'''
 part of my;
@@ -5304,8 +5650,8 @@
 
     // `a.dart` is still a part.
     // ...but the unlinked signature of `a.dart` is different.
-    // API signatures of both `b.dart` and `c.dart` changed.
-    // Even though `a.dart` is not a valid part of `c.dart`.
+    // The API signatures of `b.dart` is changed, because `a.dart` is its part.
+    // But `c.dart` still has the previous API signature.
     assertDriverStateString(testFile, r'''
 files
   /home/test/lib/a.dart
@@ -5342,7 +5688,7 @@
         cycle_4
           dependencies: dart:core
           libraries: library_7
-          apiSignature_3
+          apiSignature_1
       unlinkedKey: k01
 libraryCycles
 elementFactory
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 40c4384..d0708d1 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -395,19 +395,11 @@
     var session = contextFor(testFilePath).currentSession;
     var parsedLibrary = session.getParsedLibraryValid(test.path);
 
-    expect(parsedLibrary.units, hasLength(3));
+    expect(parsedLibrary.units, hasLength(1));
     expect(
       parsedLibrary.units[0].path,
       convertPath('/home/test/lib/test.dart'),
     );
-    expect(
-      parsedLibrary.units[1].path,
-      convertPath('/home/test/lib/a.dart'),
-    );
-    expect(
-      parsedLibrary.units[2].path,
-      convertPath('/home/test/lib/c.dart'),
-    );
   }
 
   test_getParsedLibrary_invalidPath_notAbsolute() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 222e523..ef1870b 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -212,10 +212,10 @@
     return _contextFor(path);
   }
 
-  void disposeAnalysisContextCollection() {
+  Future<void> disposeAnalysisContextCollection() async {
     final analysisContextCollection = _analysisContextCollection;
     if (analysisContextCollection != null) {
-      analysisContextCollection.dispose(
+      await analysisContextCollection.dispose(
         forTesting: true,
       );
       _analysisContextCollection = null;
@@ -258,7 +258,7 @@
 
   @mustCallSuper
   Future<void> tearDown() async {
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
     KernelCompilationService.disposeDelayed(
       const Duration(milliseconds: 500),
     );
@@ -492,7 +492,7 @@
     await resolveTestCode(code);
     assertNoErrorsInResult();
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     writeTestPackageAnalysisOptionsFile(
       AnalysisOptionsFileConfig(
@@ -539,7 +539,7 @@
     await resolveTestCode(code);
     assertNoErrorsInResult();
 
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     writeTestPackageAnalysisOptionsFile(
       AnalysisOptionsFileConfig(
diff --git a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
index 8124576..ec37e39 100644
--- a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
+++ b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart
@@ -2,20 +2,27 @@
 // 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 'dart:collection';
-
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:collection/collection.dart';
 
 /// Prints [DartObjectImpl] as a tree, with values and fields.
 class DartObjectPrinter {
   final StringBuffer sink;
+  final String selfUriStr;
 
-  DartObjectPrinter(this.sink);
+  String indent = '';
 
-  void write(DartObjectImpl? object, String indent) {
+  DartObjectPrinter({
+    required this.sink,
+    required this.selfUriStr,
+  });
+
+  void write(DartObjectImpl? object) {
     if (object != null) {
-      var type = object.type;
+      final type = object.type;
       if (object.isUnknown) {
         sink.write(
           type.getDisplayString(
@@ -33,34 +40,86 @@
         sink.write('String ');
         sink.writeln(object.toStringValue());
       } else if (type.isDartCoreList) {
-        var newIndent = '$indent  ';
+        type as InterfaceType;
         sink.writeln('List');
-        sink.write(newIndent);
-        sink.writeln(
-            'elementType: ${(type as InterfaceType).typeArguments[0]}');
-        var elements = object.toListValue()!;
-        for (int i = 0; i < elements.length; i++) {
-          sink.write(newIndent);
-          write(elements[i] as DartObjectImpl, newIndent);
-        }
-      } else if (object.isUserDefinedObject) {
-        var newIndent = '$indent  ';
-        var typeStr = type.getDisplayString(withNullability: true);
-        sink.writeln(typeStr);
-        var fields = object.fields;
-        if (fields != null) {
-          var sortedFields = SplayTreeMap.of(fields);
-          for (var entry in sortedFields.entries) {
-            sink.write(newIndent);
-            sink.write('${entry.key}: ');
-            write(entry.value, newIndent);
+        _withIndent(() {
+          _writelnWithIndent('elementType: ${type.typeArguments[0]}');
+          final elements = object.toListValue()!;
+          if (elements.isNotEmpty) {
+            _writelnWithIndent('elements');
+            _withIndent(() {
+              for (final element in elements) {
+                sink.write(indent);
+                write(element as DartObjectImpl);
+              }
+            });
           }
-        }
+        });
+      } else if (object.isUserDefinedObject) {
+        final typeStr = type.getDisplayString(withNullability: true);
+        sink.writeln(typeStr);
+        _withIndent(() {
+          final fields = object.fields;
+          if (fields != null) {
+            final sortedFields = fields.entries.sortedBy((e) => e.key);
+            for (final entry in sortedFields) {
+              sink.write(indent);
+              sink.write('${entry.key}: ');
+              write(entry.value);
+            }
+          }
+        });
       } else {
         throw UnimplementedError();
       }
+      _writeVariable(object);
     } else {
       sink.writeln('<null>');
     }
   }
+
+  String _referenceToString(Reference reference) {
+    final parent = reference.parent!;
+    if (parent.parent == null) {
+      final libraryUriStr = reference.name;
+      if (libraryUriStr == selfUriStr) {
+        return 'self';
+      }
+      return libraryUriStr;
+    }
+
+    // Ignore the unit, skip to the library.
+    if (parent.name == '@unit') {
+      return _referenceToString(parent.parent!);
+    }
+
+    var name = reference.name;
+    if (name.isEmpty) {
+      name = '•';
+    }
+    return '${_referenceToString(parent)}::$name';
+  }
+
+  void _withIndent(void Function() f) {
+    var savedIndent = indent;
+    indent = '$savedIndent  ';
+    f();
+    indent = savedIndent;
+  }
+
+  void _writelnWithIndent(String line) {
+    sink.write(indent);
+    sink.writeln(line);
+  }
+
+  void _writeVariable(DartObjectImpl object) {
+    final variable = object.variable;
+    if (variable is VariableElementImpl) {
+      _withIndent(() {
+        final reference = variable.reference!;
+        final referenceStr = _referenceToString(reference);
+        _writelnWithIndent('variable: $referenceStr');
+      });
+    }
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index 8da2b07..08b5846 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -39,6 +39,7 @@
 ''');
     _assertAnnotationValueText(annotation, '''
 int 42
+  variable: self::@variable::a
 ''');
   }
 
@@ -67,6 +68,7 @@
     var annotationElement = annotation.elementAnnotation!;
     _assertElementAnnotationValueText(annotationElement, r'''
 int 42
+  variable: self::@variable::foo
 ''');
   }
 
@@ -102,6 +104,7 @@
     var annotationElement = annotation.elementAnnotation!;
     _assertElementAnnotationValueText(annotationElement, r'''
 int 42
+  variable: self::@variable::foo
 ''');
   }
 
@@ -128,6 +131,7 @@
 E
   _name: String v
   index: int 0
+  variable: self::@enum::E::@field::v
 ''');
   }
 
@@ -413,6 +417,7 @@
     _assertElementAnnotationValueText(
         findElement.function('f').metadata[0], r'''
 int 42
+  variable: package:test/a.dart::@class::A::@field::foo
 ''');
   }
 
@@ -446,6 +451,7 @@
     _assertElementAnnotationValueText(
         findElement.function('f').metadata[0], r'''
 int 42
+  variable: package:test/a.dart::@variable::foo
 ''');
   }
 
@@ -707,6 +713,7 @@
 ''');
     _assertAnnotationValueText(annotation, '''
 int 42
+  variable: self::@class::A::@field::foo
 ''');
   }
 
@@ -1678,6 +1685,7 @@
 ''');
     _assertAnnotationValueText(annotation, '''
 int 42
+  variable: package:test/a.dart::@class::A::@field::foo
 ''');
   }
 
@@ -1979,6 +1987,7 @@
 ''');
     _assertAnnotationValueText(annotation, '''
 int 42
+  variable: self::@class::A::@field::foo
 ''');
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index d80f3d2..7ff2297 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -119,7 +119,10 @@
 
   void assertDartObjectText(DartObject? object, String expected) {
     var buffer = StringBuffer();
-    DartObjectPrinter(buffer).write(object as DartObjectImpl?, '');
+    DartObjectPrinter(
+      sink: buffer,
+      selfUriStr: '${result.libraryElement.source.uri}',
+    ).write(object as DartObjectImpl?);
     var actual = buffer.toString();
     if (actual != expected) {
       print(buffer);
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 9fd06aa..c9bab89 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -40,6 +40,110 @@
 }
 
 abstract class ElementsTest extends ElementsBaseTest {
+  test_augmentation_augmentationImports_augmentation() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+import augment 'b.dart';
+class A {}
+''');
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'a.dart';
+class B {}
+''');
+    final library = await buildLibrary(r'''
+import augment 'a.dart';
+class C {}
+''');
+    checkElementText(library, r'''
+library
+  augmentationImports
+    package:test/a.dart
+      augmentationImports
+        package:test/b.dart
+          definingUnit
+            classes
+              class B @32
+                constructors
+                  synthetic @-1
+      definingUnit
+        classes
+          class A @60
+            constructors
+              synthetic @-1
+  definingUnit
+    classes
+      class C @31
+        constructors
+          synthetic @-1
+''');
+  }
+
+  test_augmentation_libraryExports_library() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+export 'dart:async';
+''');
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+export 'dart:collection';
+export 'dart:math';
+''');
+    final library = await buildLibrary(r'''
+import 'dart:io';
+import augment 'a.dart';
+import augment 'b.dart';
+''');
+    checkElementText(library, r'''
+library
+  imports
+    dart:io
+  augmentationImports
+    package:test/a.dart
+      exports
+        dart:async
+      definingUnit
+    package:test/b.dart
+      exports
+        dart:collection
+        dart:math
+      definingUnit
+  definingUnit
+''');
+  }
+
+  test_augmentation_libraryImports_library() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+import 'dart:async';
+''');
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+import 'dart:collection';
+import 'dart:math';
+''');
+    final library = await buildLibrary(r'''
+import 'dart:io';
+import augment 'a.dart';
+import augment 'b.dart';
+''');
+    checkElementText(library, r'''
+library
+  imports
+    dart:io
+  augmentationImports
+    package:test/a.dart
+      imports
+        dart:async
+      definingUnit
+    package:test/b.dart
+      imports
+        dart:collection
+        dart:math
+      definingUnit
+  definingUnit
+''');
+  }
+
   test_class_abstract() async {
     var library = await buildLibrary('abstract class C {}');
     checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index dedd656..c6edd7f 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -1766,27 +1766,27 @@
 ''';
     await _assertNoErrors(
         build(declared: "MyFuture", downwards: "Future", upwards: "Future"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await _assertNoErrors(
         build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await _assertNoErrors(
         build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await _assertNoErrors(build(
         declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await _assertNoErrors(
         build(declared: "Future", downwards: "Future", upwards: "MyFuture"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await _assertNoErrors(
         build(declared: "Future", downwards: "Future", upwards: "Future"));
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
   }
 
   test_futureThen_downwardsMethodTarget() async {
@@ -1860,7 +1860,7 @@
         error(HintCode.UNNECESSARY_CAST, 480, 47),
       ],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertErrorsInCode(
       build(declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"),
@@ -1871,7 +1871,7 @@
         error(HintCode.UNNECESSARY_CAST, 484, 49),
       ],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertErrorsInCode(
       build(declared: "Future", downwards: "Future", upwards: "Future"),
@@ -1882,7 +1882,7 @@
         error(HintCode.UNNECESSARY_CAST, 480, 47),
       ],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
   }
 
   test_futureThen_upwardsFromBlock() async {
@@ -1927,12 +1927,12 @@
     await assertNoErrorsInCode(
       build(downwards: "Future", upwards: "Future", expectedInfo: ''),
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertNoErrorsInCode(
       build(downwards: "Future", upwards: "MyFuture"),
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
   }
 
   test_futureUnion_downwards() async {
@@ -1975,7 +1975,7 @@
         error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 338, 4),
       ],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertErrorsInCode(
       build(
@@ -1985,7 +1985,7 @@
       ),
       [],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertErrorsInCode(
       build(
@@ -1998,7 +1998,7 @@
         error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 336, 4),
       ],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
 
     await assertErrorsInCode(
       build(
@@ -2008,7 +2008,7 @@
       ),
       [],
     );
-    disposeAnalysisContextCollection();
+    await disposeAnalysisContextCollection();
   }
 
   test_futureUnion_downwardsGenericMethodWithFutureReturn() async {
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index 3f7bb5d..a721865 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -258,7 +258,7 @@
       await beforeContextCollectionDispose(
         contextCollection: currentContextCollection,
       );
-      currentContextCollection.dispose();
+      await currentContextCollection.dispose();
     }
 
     final includedPaths = parameters.roots.map((e) => e.root).toList();
diff --git a/pkg/dartdev/test/commands/language_server_test.dart b/pkg/dartdev/test/commands/language_server_test.dart
index 06d75dc..8429677 100644
--- a/pkg/dartdev/test/commands/language_server_test.dart
+++ b/pkg/dartdev/test/commands/language_server_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 'dart:async';
 import 'dart:convert';
 import 'dart:io';
 
@@ -31,9 +32,6 @@
 
     process = await project.start(args);
 
-    final Stream<String> inStream =
-        process!.stdout.transform<String>(utf8.decoder);
-
     // Send an LSP init.
     final String message = jsonEncode({
       'jsonrpc': '2.0',
@@ -51,12 +49,10 @@
     process!.stdin.write('\r\n');
     process!.stdin.write(message);
 
-    List<String> responses = await inStream.take(2).toList();
-    expect(responses, hasLength(2));
+    // Expect
+    final response = await _readLspMessage(process!.stdout);
 
-    expect(responses[0], startsWith('Content-Length: '));
-
-    final json = jsonDecode(responses[1]);
+    final json = jsonDecode(response);
     expect(json['id'], 1);
     expect(json['result'], isNotNull);
     final result = json['result'];
@@ -99,3 +95,42 @@
     process = null;
   });
 }
+
+/// Reads the first LSP message from [stream].
+Future<String> _readLspMessage(Stream<List<int>> stream) {
+  // Headers are complete if there are 2x '\r\n\'. The '\r' is part of the LSP
+  // spec for headers and included on all platforms, not just Windows.
+  const lspHeaderBodySeperator = '\r\n\r\n';
+  final contentLengthRegExp = RegExp(r'Content-Length: (\d+)\r\n');
+
+  final completer = Completer<String>();
+  final buffer = StringBuffer();
+  late final StreamSubscription<String> inSubscription;
+  inSubscription = stream.transform<String>(utf8.decoder).listen(
+    (data) {
+      // Collect the output into the buffer.
+      buffer.write(data);
+
+      // Check whether the buffer has a complete message.
+      final bufferString = buffer.toString();
+
+      // To know if we have a complete message, we need to check we have the
+      // headers, extract the content-length, then check we have that many
+      // bytes in the body.
+      if (bufferString.contains(lspHeaderBodySeperator)) {
+        final parts = bufferString.split(lspHeaderBodySeperator);
+        final headers = parts[0];
+        final body = parts[1];
+        final length =
+            int.parse(contentLengthRegExp.firstMatch(headers)!.group(1)!);
+        // Check if we're already had the full payload.
+        if (body.length >= length) {
+          completer.complete(body.substring(0, length));
+          inSubscription.cancel();
+        }
+      }
+    },
+  );
+
+  return completer.future;
+}
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 727e2cd..71f07cb 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 9.2.0
+- Update to version `3.59` of the spec.
+- Add `abstract` flag to `FuncRef`.
+
 ## 9.1.0
 - Remove `required` keyword from most of the named parameters in the
   constructors of the Dart API objects.
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 8aee343..cf92a35 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.58
+version=3.59
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 1533b40..45dd4ee 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.58.0';
+const String vmServiceVersion = '3.59.0';
 
 /// @optional
 const String optional = 'optional';
@@ -4675,6 +4675,9 @@
   /// Is this function implicitly defined (e.g., implicit getter/setter)?
   bool? implicit;
 
+  /// Is this function an abstract method?
+  bool? isAbstract;
+
   /// The location of this function in the source code.
   ///
   /// Note: this may not agree with the location of `owner` if this is a
@@ -4689,6 +4692,7 @@
     this.isStatic,
     this.isConst,
     this.implicit,
+    this.isAbstract,
     required String id,
     this.location,
   }) : super(
@@ -4702,6 +4706,7 @@
     isStatic = json['static'] ?? false;
     isConst = json['const'] ?? false;
     implicit = json['implicit'] ?? false;
+    isAbstract = json['abstract'] ?? false;
     location = createServiceObject(json['location'], const ['SourceLocation'])
         as SourceLocation?;
   }
@@ -4719,6 +4724,7 @@
       'static': isStatic,
       'const': isConst,
       'implicit': implicit,
+      'abstract': isAbstract,
     });
     _setIfNotNull(json, 'location', location?.toJson());
     return json;
@@ -4730,7 +4736,7 @@
 
   String toString() => '[FuncRef ' //
       'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
-      'isConst: ${isConst}, implicit: ${implicit}]';
+      'isConst: ${isConst}, implicit: ${implicit}, isAbstract: ${isAbstract}]';
 }
 
 /// A `Func` represents a Dart language function.
@@ -4759,6 +4765,9 @@
   /// Is this function implicitly defined (e.g., implicit getter/setter)?
   bool? implicit;
 
+  /// Is this function an abstract method?
+  bool? isAbstract;
+
   /// The location of this function in the source code.
   ///
   /// Note: this may not agree with the location of `owner` if this is a
@@ -4780,6 +4789,7 @@
     this.isStatic,
     this.isConst,
     this.implicit,
+    this.isAbstract,
     this.signature,
     required String id,
     this.location,
@@ -4795,6 +4805,7 @@
     isStatic = json['static'] ?? false;
     isConst = json['const'] ?? false;
     implicit = json['implicit'] ?? false;
+    isAbstract = json['abstract'] ?? false;
     location = createServiceObject(json['location'], const ['SourceLocation'])
         as SourceLocation?;
     signature = createServiceObject(json['signature'], const ['InstanceRef'])
@@ -4815,6 +4826,7 @@
       'static': isStatic,
       'const': isConst,
       'implicit': implicit,
+      'abstract': isAbstract,
       'signature': signature?.toJson(),
     });
     _setIfNotNull(json, 'location', location?.toJson());
@@ -4828,7 +4840,7 @@
 
   String toString() => '[Func ' //
       'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
-      'isConst: ${isConst}, implicit: ${implicit}, signature: ${signature}]';
+      'isConst: ${isConst}, implicit: ${implicit}, isAbstract: ${isAbstract}, signature: ${signature}]';
 }
 
 /// `InstanceRef` is a reference to an `Instance`.
@@ -6322,7 +6334,9 @@
     return json;
   }
 
-  String toString() => '[LogRecord]';
+  String toString() => '[LogRecord ' //
+      'message: ${message}, time: ${time}, level: ${level}, sequenceNumber: ${sequenceNumber}, ' //
+      'loggerName: ${loggerName}, zone: ${zone}, error: ${error}, stackTrace: ${stackTrace}]';
 }
 
 class MapAssociation {
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 0f11496..e7c8f3b 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -1,5 +1,5 @@
 name: vm_service
-version: 9.1.0
+version: 9.2.0
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index ee8df6c..5475adc 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -1611,7 +1611,8 @@
     // toString()
     Iterable<TypeField> toStringFields =
         getAllFields().where((f) => !f.optional);
-    if (toStringFields.length <= 7) {
+    const maxFieldsShownInToString = 8;
+    if (toStringFields.length <= maxFieldsShownInToString) {
       String properties = toStringFields
           .map(
               (TypeField f) => "${f.generatableName}: \${${f.generatableName}}")
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index a1f0582..774c855 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -11,12 +11,17 @@
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-class _DummyClass {
+abstract class _DummyAbstractBaseClass {
+  void dummyFunction(int a, [bool b = false]);
+}
+
+class _DummyClass extends _DummyAbstractBaseClass {
   static var dummyVar = 11;
   final List<String> dummyList = new List<String>.filled(20, '');
   static var dummyVarWithInit = foo();
   late String dummyLateVarWithInit = 'bar';
   late String dummyLateVar;
+  @override
   void dummyFunction(int a, [bool b = false]) {}
   void dummyGenericFunction<K, V>(K a, {required V param}) {}
   static List foo() => List<String>.filled(20, '');
@@ -889,6 +894,7 @@
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'], isNull);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 3);
@@ -923,6 +929,7 @@
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'].length, 2);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 3);
@@ -943,6 +950,60 @@
     expect(result['_deoptimizations'], isZero);
   },
 
+  // abstract function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var result = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': evalResult['class']['id'],
+    });
+    expect(result['type'], equals('Class'));
+    expect(result['id'], startsWith('classes/'));
+    expect(result['name'], equals('_DummyClass'));
+    expect(result['abstract'], equals(false));
+
+    // Get the super class.
+    var superClass = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': result['super']['id'],
+    });
+    expect(superClass['type'], equals('Class'));
+    expect(superClass['id'], startsWith('classes/'));
+    expect(superClass['name'], equals('_DummyAbstractBaseClass'));
+    expect(superClass['abstract'], equals(true));
+
+    // Find the abstract dummyFunction on the super class.
+    var funcId = superClass['functions']
+        .firstWhere((f) => f['name'] == 'dummyFunction')['id'];
+    var funcResult = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': funcId,
+    });
+
+    expect(funcResult['type'], equals('Function'));
+    expect(funcResult['id'], equals(funcId));
+    expect(funcResult['name'], equals('dummyFunction'));
+    expect(funcResult['_kind'], equals('RegularFunction'));
+    expect(funcResult['static'], equals(false));
+    expect(funcResult['const'], equals(false));
+    expect(funcResult['implicit'], equals(false));
+    expect(funcResult['abstract'], equals(true));
+    expect(funcResult['signature']['typeParameters'], isNull);
+    expect(funcResult['signature']['returnType'], isNotNull);
+    expect(funcResult['signature']['parameters'].length, 3);
+    expect(funcResult['signature']['parameters'][1]['parameterType']['name'],
+        equals('int'));
+    expect(funcResult['signature']['parameters'][1]['fixed'], isTrue);
+    expect(funcResult['signature']['parameters'][2]['parameterType']['name'],
+        equals('bool'));
+    expect(funcResult['signature']['parameters'][2]['fixed'], isFalse);
+    expect(funcResult['location']['type'], equals('SourceLocation'));
+    expect(funcResult['code']['type'], equals('@Code'));
+    expect(funcResult['_optimizable'], equals(true));
+    expect(funcResult['_inlinable'], equals(true));
+    expect(funcResult['_usageCounter'], isZero);
+    expect(funcResult['_optimizedCallSiteCount'], isZero);
+    expect(funcResult['_deoptimizations'], isZero);
+  },
+
   // invalid function.
   (Isolate isolate) async {
     // Call eval to get a class id.
@@ -1002,6 +1063,7 @@
     expect(result['static'], equals(true));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'], isNull);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 0);
@@ -1030,6 +1092,7 @@
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'], isNull);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 1);
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 2e89731..bf51c64 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'], 57);
+    expect(result['minor'], 59);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
index 9c45a9e..20c65ff 100644
--- a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
@@ -11,10 +11,15 @@
 import 'service_test_common.dart';
 import 'test_helper.dart';
 
-class _DummyClass {
+abstract class _DummyAbstractBaseClass {
+  void dummyFunction(int a, [bool b = false]);
+}
+
+class _DummyClass extends _DummyAbstractBaseClass {
   static var dummyVar = 11;
   final List<String> dummyList = new List<String>.filled(20, null);
   static var dummyVarWithInit = foo();
+  @override
   void dummyFunction(int a, [bool b = false]) {}
   void dummyGenericFunction<K, V>(K a, {V param}) {}
   static List foo() => List<String>.filled(20, '');
@@ -886,6 +891,7 @@
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'], isNull);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 3);
@@ -920,6 +926,7 @@
     expect(result['static'], equals(false));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'].length, 2);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 3);
@@ -940,6 +947,60 @@
     expect(result['_deoptimizations'], isZero);
   },
 
+  // abstract function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var result = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': evalResult['class']['id'],
+    });
+    expect(result['type'], equals('Class'));
+    expect(result['id'], startsWith('classes/'));
+    expect(result['name'], equals('_DummyClass'));
+    expect(result['abstract'], equals(false));
+
+    // Get the super class.
+    var superClass = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': result['super']['id'],
+    });
+    expect(superClass['type'], equals('Class'));
+    expect(superClass['id'], startsWith('classes/'));
+    expect(superClass['name'], equals('_DummyAbstractBaseClass'));
+    expect(superClass['abstract'], equals(true));
+
+    // Find the abstract dummyFunction on the super class.
+    var funcId = superClass['functions']
+        .firstWhere((f) => f['name'] == 'dummyFunction')['id'];
+    var funcResult = await isolate.invokeRpcNoUpgrade('getObject', {
+      'objectId': funcId,
+    });
+
+    expect(funcResult['type'], equals('Function'));
+    expect(funcResult['id'], equals(funcId));
+    expect(funcResult['name'], equals('dummyFunction'));
+    expect(funcResult['_kind'], equals('RegularFunction'));
+    expect(funcResult['static'], equals(false));
+    expect(funcResult['const'], equals(false));
+    expect(funcResult['implicit'], equals(false));
+    expect(funcResult['abstract'], equals(true));
+    expect(funcResult['signature']['typeParameters'], isNull);
+    expect(funcResult['signature']['returnType'], isNotNull);
+    expect(funcResult['signature']['parameters'].length, 3);
+    expect(funcResult['signature']['parameters'][1]['parameterType']['name'],
+        equals('int'));
+    expect(funcResult['signature']['parameters'][1]['fixed'], isTrue);
+    expect(funcResult['signature']['parameters'][2]['parameterType']['name'],
+        equals('bool'));
+    expect(funcResult['signature']['parameters'][2]['fixed'], isFalse);
+    expect(funcResult['location']['type'], equals('SourceLocation'));
+    expect(funcResult['code']['type'], equals('@Code'));
+    expect(funcResult['_optimizable'], equals(true));
+    expect(funcResult['_inlinable'], equals(true));
+    expect(funcResult['_usageCounter'], isZero);
+    expect(funcResult['_optimizedCallSiteCount'], isZero);
+    expect(funcResult['_deoptimizations'], isZero);
+  },
+
   // invalid function.
   (Isolate isolate) async {
     // Call eval to get a class id.
@@ -1032,6 +1093,7 @@
     expect(result['static'], equals(true));
     expect(result['const'], equals(false));
     expect(result['implicit'], equals(false));
+    expect(result['abstract'], equals(false));
     expect(result['signature']['typeParameters'], isNull);
     expect(result['signature']['returnType'], isNotNull);
     expect(result['signature']['parameters'].length, 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 451c93e..4bb45af 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(57));
+    expect(result['minor'], equals(59));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 8af3c49..c6f1d55 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -5194,12 +5194,16 @@
     // if (controller.add(<expr>)) {
     //   return;
     // }
-    // suspend();
+    // if (suspend()) {
+    //   return;
+    // }
     //
     // Generate the following code for yield* <expr>:
     //
     // _AsyncStarStreamController controller = :suspend_state._functionData;
-    // controller.addStream(<expr>);
+    // if (controller.addStream(<expr>)) {
+    //   return;
+    // }
     // if (suspend()) {
     //   return;
     // }
@@ -5215,31 +5219,25 @@
     instructions +=
         StaticCall(TokenPosition::kNoSource, add_method, 2, ICData::kNoRebind);
 
-    if (is_yield_star) {
-      // Discard result of _AsyncStarStreamController.addStream().
-      instructions += Drop();
-      // Suspend and test value passed to the resumed async* body.
-      instructions += NullConstant();
-      instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
-    } else {
-      // Test value returned by _AsyncStarStreamController.add().
-    }
+    TargetEntryInstr *return1, *continue1;
+    instructions += BranchIfTrue(&return1, &continue1, false);
+    JoinEntryInstr* return_join = BuildJoinEntry();
+    Fragment(return1) + Goto(return_join);
+    instructions = Fragment(instructions.entry, continue1);
 
-    TargetEntryInstr* exit;
-    TargetEntryInstr* continue_execution;
-    instructions += BranchIfTrue(&exit, &continue_execution, false);
+    // Suspend and test value passed to the resumed async* body.
+    instructions += NullConstant();
+    instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
 
-    Fragment do_exit(exit);
-    do_exit += TranslateFinallyFinalizers(nullptr, -1);
-    do_exit += NullConstant();
-    do_exit += Return(TokenPosition::kNoSource);
+    TargetEntryInstr *return2, *continue2;
+    instructions += BranchIfTrue(&return2, &continue2, false);
+    Fragment(return2) + Goto(return_join);
+    instructions = Fragment(instructions.entry, continue2);
 
-    instructions = Fragment(instructions.entry, continue_execution);
-    if (!is_yield_star) {
-      instructions += NullConstant();
-      instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);
-      instructions += Drop();
-    }
+    Fragment do_return(return_join);
+    do_return += TranslateFinallyFinalizers(nullptr, -1);
+    do_return += NullConstant();
+    do_return += Return(TokenPosition::kNoSource);
 
   } else if (parsed_function()->function().IsSyncGenerator()) {
     // In the sync* functions, generate the following code for yield <expr>:
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1d11933..41da4b4 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -341,6 +341,7 @@
   jsobj.AddProperty("static", is_static());
   jsobj.AddProperty("const", is_const());
   jsobj.AddProperty("implicit", IsImplicitGetterOrSetter());
+  jsobj.AddProperty("abstract", is_abstract());
   jsobj.AddProperty("_intrinsic", is_intrinsic());
   jsobj.AddProperty("_native", is_native());
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index b168abc..2df9119 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -5890,7 +5890,7 @@
         "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
         "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
         "\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
-        "\"implicit\":false,"
+        "\"implicit\":false,\"abstract\":false,"
         "\"_intrinsic\":false,\"_native\":false,"
         "\"location\":{\"type\":\"SourceLocation\","
         "\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index b8e3124..38a0bf6 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 57
+#define SERVICE_PROTOCOL_MINOR_VERSION 59
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 4c873ec..622ea1d 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,4 +1,4 @@
-# Dart VM Service Protocol 3.58
+# Dart VM Service Protocol 3.59
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
@@ -2596,6 +2596,9 @@
   // Is this function implicitly defined (e.g., implicit getter/setter)?
   bool implicit;
 
+  // Is this function an abstract method?
+  bool abstract;
+
   // The location of this function in the source code.
   //
   // Note: this may not agree with the location of `owner` if this is a function
@@ -2628,6 +2631,9 @@
   // Is this function implicitly defined (e.g., implicit getter/setter)?
   bool implicit;
 
+  // Is this function an abstract method?
+  bool abstract;
+
   // The location of this function in the source code.
   //
   // Note: this may not agree with the location of `owner` if this is a function
@@ -4372,5 +4378,6 @@
 3.56 | Added optional `line` and `column` properties to `SourceLocation`. Added a new `SourceReportKind`, `BranchCoverage`, which reports branch level coverage information.
 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`.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index 34a00bf..22ef9de 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -603,7 +603,7 @@
       "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
       "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
-      "\"implicit\":false,"
+      "\"implicit\":false,\"abstract\":false,"
       "\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
@@ -687,8 +687,8 @@
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
-      "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
-      "false,"
+      "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
+      "false,\"_intrinsic\":false,"
       "\"_native\":false,"
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -723,8 +723,8 @@
       "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
       "},\"_kind\":\"RegularFunction\","
-      "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
-      "false,"
+      "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
+      "false,\"_intrinsic\":false,"
       "\"_native\":false,"
       "\"location\":{\"type\":\"SourceLocation\","
       "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -782,7 +782,7 @@
       "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
       "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
       "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
-      "false,\"_"
+      "false,\"abstract\":false,\"_"
       "intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
       "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
       "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index c0d480e..4e27366 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -46,13 +46,6 @@
   bool isSuspendedAtYield = false;
   _Future? cancellationFuture = null;
 
-  /// Argument passed to the generator when it is resumed after an addStream.
-  ///
-  /// `true` if the generator should exit after `yield*` resumes.
-  /// `false` if the generator should continue after `yield*` resumes.
-  /// `null` otherwies.
-  bool? continuationArgument = null;
-
   Stream<T> get stream {
     final Stream<T> local = controller.stream;
     if (local is _StreamImpl<T>) {
@@ -64,9 +57,7 @@
   void runBody() {
     isScheduled = false;
     isSuspendedAtYield = false;
-    final bool? argument = continuationArgument;
-    continuationArgument = null;
-    asyncStarBody!(argument);
+    asyncStarBody!(!controller.hasListener);
   }
 
   void scheduleGenerator() {
@@ -77,16 +68,8 @@
     scheduleMicrotask(runBody);
   }
 
-  // Adds element to stream, returns true if the caller should terminate
-  // execution of the generator.
-  //
-  // TODO(hausner): Per spec, the generator should be suspended before
-  // exiting when the stream is closed. We could add a getter like this:
-  // get isCancelled => controller.hasListener;
-  // The generator would translate a 'yield e' statement to
-  // controller.add(e);
-  // suspend;
-  // if (controller.isCancelled) return;
+  // Adds element to stream.
+  // Returns true if the caller should terminate execution of the generator.
   @pragma("vm:entry-point", "call")
   bool add(T event) {
     if (!onListenReceived) _fatal("yield before stream is listened to");
@@ -104,40 +87,23 @@
   // Adds the elements of stream into this controller's stream.
   // The generator will be scheduled again when all of the
   // elements of the added stream have been consumed.
+  // Returns true if the caller should terminate execution of the generator.
   @pragma("vm:entry-point", "call")
-  void addStream(Stream<T> stream) {
+  bool addStream(Stream<T> stream) {
     if (!onListenReceived) _fatal("yield before stream is listened to");
-
-    if (exitAfterYieldStarIfCancelled()) return;
+    if (!controller.hasListener) {
+      return true;
+    }
 
     isAdding = true;
     final whenDoneAdding = controller.addStream(stream, cancelOnError: false);
     whenDoneAdding.then((_) {
       isAdding = false;
-      if (exitAfterYieldStarIfCancelled()) return;
-      resumeNormallyAfterYieldStar();
-    });
-  }
-
-  /// Schedules the generator to exit after `yield*` if stream was cancelled.
-  ///
-  /// Returns `true` if generator is told to exit and `false` otherwise.
-  bool exitAfterYieldStarIfCancelled() {
-    // If consumer cancelled subscription we should tell async* generator to
-    // finish (i.e. run finally clauses and return).
-    if (!controller.hasListener) {
-      continuationArgument = true;
       scheduleGenerator();
-      return true;
-    }
-    return false;
-  }
+      if (!isScheduled) isSuspendedAtYield = true;
+    });
 
-  /// Schedules the generator to resume normally after `yield*`.
-  void resumeNormallyAfterYieldStar() {
-    continuationArgument = false;
-    scheduleGenerator();
-    if (!isScheduled) isSuspendedAtYield = true;
+    return false;
   }
 
   void addError(Object error, StackTrace stackTrace) {
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 3da1875..b6a2a6d 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -194,7 +194,7 @@
   ///
   /// The result `r` of this operation satisfies:
   /// `this == (this ~/ other) * other + r`.
-  /// As a consequence, the remainder `r` has the same sign as the divider
+  /// As a consequence, the remainder `r` has the same sign as the dividend
   /// `this`.
   ///
   /// The result is an [int], as described by [int.remainder],
diff --git a/tests/language/language_precompiled.status b/tests/language/language_precompiled.status
index 4850aa0..dc151ee 100644
--- a/tests/language/language_precompiled.status
+++ b/tests/language/language_precompiled.status
@@ -15,8 +15,6 @@
 
 [ $compiler == dartkp && $runtime == dart_precompiled ]
 async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
 
 [ $runtime == dart_precompiled && $minified ]
 enum/duplicate_test/*: Skip # Uses Enum.toString()
diff --git a/tests/language/language_vm.status b/tests/language/language_vm.status
index 2d01341..2112263 100644
--- a/tests/language/language_vm.status
+++ b/tests/language/language_vm.status
@@ -18,8 +18,6 @@
 
 [ $runtime == vm ]
 async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
 
 [ $arch == arm64 && $runtime == vm ]
 class/large_class_declaration_test: SkipSlow # Uses too much memory.
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 4850aa0..dc151ee 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -15,8 +15,6 @@
 
 [ $compiler == dartkp && $runtime == dart_precompiled ]
 async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
 
 [ $runtime == dart_precompiled && $minified ]
 enum/duplicate_test/*: Skip # Uses Enum.toString()
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 2d01341..2112263 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -18,8 +18,6 @@
 
 [ $runtime == vm ]
 async_star/async_star_await_for_test: RuntimeError
-async_star/async_star_cancel_test: RuntimeError
-async_star/async_star_test: RuntimeError
 
 [ $arch == arm64 && $runtime == vm ]
 class/large_class_declaration_test: SkipSlow # Uses too much memory.
diff --git a/tools/VERSION b/tools/VERSION
index 62109bd..184c75e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 3
+PRERELEASE 4
 PRERELEASE_PATCH 0
\ No newline at end of file