Version 2.14.0-213.0.dev

Merge commit 'cbe818faccdc6b650eb4f4aa062a100acee814c3' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70d7ff1..4722f5c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
 
 ### Core libraries
 
+### `dart:html`
+
+* [#44319][]: `convertNativeToDart_Dictionary()` now converts objects
+  recursively, this fixes APIs like MediaStreamTrack.getCapabilities
+  that convert between Maps and browser Dictionaries.
+
+[44319]: (https://github.com/dart-lang/sdk/issues/44319)
+
 #### `dart:async`
 
 * The uncaught error handlers of `Zone`s are now run in the parent zone
diff --git a/DEPS b/DEPS
index 9e9e23d..2359e52 100644
--- a/DEPS
+++ b/DEPS
@@ -145,7 +145,7 @@
   "pub_rev": "3c14d86a67db7207bbc9f654ac49ee60e08e5240",
   "pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
-  "root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
+  "root_certificates_rev": "ef7b563890e219a93579b61584f9ffa64c7c8d9c",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
   "shelf_static_rev": "fa30419055279a00c9e428439b1abe362d18f25d",
   "shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index cfbdb7f..8277894 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -92,6 +92,13 @@
         // to ensure that we can return the suggestions from other providers.
         return;
       }
+      var containingNode = request.target.containingNode;
+      if (containingNode is PropertyAccess &&
+          containingNode.operator.lexeme == '?.') {
+        // After a null-safe operator we know that the member will only be
+        // invoked on a non-null value.
+        type = containingLibrary.typeSystem.promoteToNonNull(type);
+      }
       _addExtensionMembers(containingLibrary, type);
       expression.staticType;
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index af11a44..256edee 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -725,6 +725,15 @@
     }
   }
 
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    var variables = node.variables;
+    if (variables.isNotEmpty && entity == variables[0] && node.type == null) {
+      _addSuggestion(Keyword.DYNAMIC);
+      _addSuggestion(Keyword.VOID);
+    }
+  }
+
   void _addClassBodyKeywords() {
     _addSuggestions([
       Keyword.CONST,
diff --git a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
index df4a4aa..0bcf127 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
@@ -10,16 +10,17 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ArgumentListCompletionTest);
-    defineReflectiveTests(AsExpressionTest);
-    defineReflectiveTests(AssertStatementTest);
+    defineReflectiveTests(AsExpressionCompletionTest);
+    defineReflectiveTests(AssertStatementCompletionTest);
     defineReflectiveTests(ConstructorCompletionTest);
-    defineReflectiveTests(ExpressionFunctionBodyTest);
+    defineReflectiveTests(ExpressionFunctionBodyCompletionTest);
     defineReflectiveTests(ExtensionCompletionTest);
-    defineReflectiveTests(GenericTypeAliasTest);
-    defineReflectiveTests(PropertyAccessorCompletionTest);
+    defineReflectiveTests(GenericTypeAliasCompletionTest);
+    defineReflectiveTests(PropertyAccessCompletionTest);
     defineReflectiveTests(RedirectedConstructorCompletionTest);
     defineReflectiveTests(RedirectingConstructorInvocationCompletionTest);
     defineReflectiveTests(SuperConstructorInvocationCompletionTest);
+    defineReflectiveTests(VariableDeclarationListCompletionTest);
   });
 }
 
@@ -73,7 +74,7 @@
 }
 
 @reflectiveTest
-class AsExpressionTest extends CompletionTestCase {
+class AsExpressionCompletionTest extends CompletionTestCase {
   Future<void> test_type_dynamic() async {
     addTestFile('''
 void f(Object o) {
@@ -86,7 +87,7 @@
 }
 
 @reflectiveTest
-class AssertStatementTest extends CompletionTestCase {
+class AssertStatementCompletionTest extends CompletionTestCase {
   @failingTest
   Future<void> test_message() async {
     addTestFile('''
@@ -119,7 +120,7 @@
 }
 
 @reflectiveTest
-class ExpressionFunctionBodyTest extends CompletionTestCase {
+class ExpressionFunctionBodyCompletionTest extends CompletionTestCase {
   Future<void> test_voidReturn_localFunction() async {
     addTestFile('''
 class C {
@@ -294,8 +295,8 @@
 }
 
 @reflectiveTest
-class GenericTypeAliasTest extends CompletionTestCase {
-  Future<void> test_constructor_abstract() async {
+class GenericTypeAliasCompletionTest extends CompletionTestCase {
+  Future<void> test_returnType_void() async {
     addTestFile('''
 typedef F = ^
 ''');
@@ -305,7 +306,23 @@
 }
 
 @reflectiveTest
-class PropertyAccessorCompletionTest extends CompletionTestCase {
+class PropertyAccessCompletionTest extends CompletionTestCase {
+  Future<void> test_nullSafe_extension() async {
+    addTestFile('''
+void f(C c) {
+  c.a?.^;
+}
+class C {
+  C? get a => null;
+}
+extension on C {
+  int get b => 0;
+}
+''');
+    await getSuggestions();
+    assertHasCompletion('b');
+  }
+
   Future<void> test_setter_deprecated() async {
     addTestFile('''
 void f(C c) {
@@ -544,3 +561,16 @@
     assertHasNoCompletion('');
   }
 }
+
+@reflectiveTest
+class VariableDeclarationListCompletionTest extends CompletionTestCase {
+  Future<void> test_type_voidAfterFinal() async {
+    addTestFile('''
+class C {
+  final ^
+}
+''');
+    await getSuggestions();
+    assertHasCompletion('void');
+  }
+}
diff --git a/pkg/analysis_server/tool/code_completion/visitors.dart b/pkg/analysis_server/tool/code_completion/visitors.dart
index e681cc4..5a17c5e 100644
--- a/pkg/analysis_server/tool/code_completion/visitors.dart
+++ b/pkg/analysis_server/tool/code_completion/visitors.dart
@@ -158,9 +158,12 @@
           .getLocation(entity.offset)
           .columnNumber;
 
+      bool isKeyword() => kind == protocol.CompletionSuggestionKind.KEYWORD;
+
       // Some special cases in the if and if-else blocks, 'import' from the
       // DAS is "import '';" which we want to be sure to match.
-      if (entity.toString() == 'async') {
+      var lexeme = entity.toString();
+      if (lexeme == 'async') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -169,7 +172,7 @@
             ASYNC_STAR,
             kind,
             elementKind));
-      } else if (entity.toString() == 'default') {
+      } else if (lexeme == 'default') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -178,7 +181,7 @@
             DEFAULT_COLON,
             kind,
             elementKind));
-      } else if (entity.toString() == 'deferred') {
+      } else if (lexeme == 'deferred') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -187,7 +190,7 @@
             DEFERRED_AS,
             kind,
             elementKind));
-      } else if (entity.toString() == 'export') {
+      } else if (lexeme == 'export' && isKeyword()) {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -196,7 +199,7 @@
             EXPORT_STATEMENT,
             kind,
             elementKind));
-      } else if (entity.toString() == 'import') {
+      } else if (lexeme == 'import' && isKeyword()) {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -205,7 +208,7 @@
             IMPORT_STATEMENT,
             kind,
             elementKind));
-      } else if (entity.toString() == 'part') {
+      } else if (lexeme == 'part' && isKeyword()) {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -214,7 +217,7 @@
             PART_STATEMENT,
             kind,
             elementKind));
-      } else if (entity.toString() == 'sync') {
+      } else if (lexeme == 'sync') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
@@ -223,7 +226,7 @@
             SYNC_STAR,
             kind,
             elementKind));
-      } else if (entity.toString() == 'yield') {
+      } else if (lexeme == 'yield') {
         expectedCompletions.add(ExpectedCompletion.specialCompletionString(
             filePath,
             entity,
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 39ab9db..2934d49 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -82,7 +82,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 = 150;
+  static const int DATA_VERSION = 154;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 399b192..605628f 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -9,9 +9,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 
 export 'package:analyzer/src/dart/ast/constant_evaluator.dart';
@@ -21,1133 +19,6 @@
 typedef ExceptionInDelegateHandler = void Function(
     AstNode node, AstVisitor visitor, dynamic exception, StackTrace stackTrace);
 
-/// An AST visitor that will clone any AST structure that it visits. The cloner
-/// will only clone the structure, it will not preserve any resolution results
-/// or properties associated with the nodes.
-class AstCloner implements AstVisitor<AstNode> {
-  /// A flag indicating whether tokens should be cloned while cloning an AST
-  /// structure.
-  final bool cloneTokens;
-
-  /// Mapping from original tokes to cloned.
-  final Map<Token, Token> _clonedTokens = Map<Token, Token>.identity();
-
-  /// The next original token to clone.
-  Token? _nextToClone;
-
-  /// The last cloned token.
-  Token? _lastCloned;
-
-  /// The offset of the last cloned token.
-  int _lastClonedOffset = -1;
-
-  /// Initialize a newly created AST cloner to optionally clone tokens while
-  /// cloning AST nodes if [cloneTokens] is `true`.
-  ///
-  /// TODO(brianwilkerson) Change this to be a named parameter.
-  AstCloner([this.cloneTokens = false]);
-
-  /// Return a clone of the given [node].
-  E cloneNode<E extends AstNode>(E node) {
-    return node.accept(this) as E;
-  }
-
-  /// Return a list containing cloned versions of the nodes in the given list of
-  /// [nodes].
-  List<E> cloneNodeList<E extends AstNode>(List<E> nodes) {
-    int count = nodes.length;
-    List<E> clonedNodes = <E>[];
-    for (int i = 0; i < count; i++) {
-      clonedNodes.add((nodes[i]).accept(this) as E);
-    }
-    return clonedNodes;
-  }
-
-  /// Return a clone of the given [node].
-  E? cloneNullableNode<E extends AstNode>(E? node) {
-    if (node == null) {
-      return null;
-    }
-    return node.accept(this) as E;
-  }
-
-  /// Clone the given [token] if tokens are supposed to be cloned.
-  Token? cloneNullableToken(Token? token) {
-    if (cloneTokens) {
-      if (token == null) {
-        return null;
-      }
-      if (_lastClonedOffset <= token.offset) {
-        _cloneTokens(_nextToClone ?? token, token.offset);
-      }
-      return _clonedTokens[token];
-    } else {
-      return token;
-    }
-  }
-
-  /// Clone the given [token] if tokens are supposed to be cloned.
-  Token cloneToken(Token token) {
-    if (cloneTokens) {
-      if (_lastClonedOffset <= token.offset) {
-        _cloneTokens(_nextToClone ?? token, token.offset);
-      }
-      return _clonedTokens[token] ?? _cloneSyntheticToken(token);
-    } else {
-      return token;
-    }
-  }
-
-  /// Clone the given [tokens] if tokens are supposed to be cloned.
-  List<Token> cloneTokenList(List<Token> tokens) {
-    if (cloneTokens) {
-      return tokens.map(cloneToken).toList();
-    }
-    return tokens;
-  }
-
-  @override
-  AdjacentStrings visitAdjacentStrings(AdjacentStrings node) =>
-      astFactory.adjacentStrings(cloneNodeList(node.strings));
-
-  @override
-  AnnotationImpl visitAnnotation(Annotation node) => astFactory.annotation(
-      atSign: cloneToken(node.atSign),
-      name: cloneNode(node.name),
-      typeArguments: cloneNullableNode(node.typeArguments),
-      period: cloneNullableToken(node.period),
-      constructorName: cloneNullableNode(node.constructorName),
-      arguments: cloneNullableNode(node.arguments));
-
-  @override
-  ArgumentList visitArgumentList(ArgumentList node) => astFactory.argumentList(
-      cloneToken(node.leftParenthesis),
-      cloneNodeList(node.arguments),
-      cloneToken(node.rightParenthesis));
-
-  @override
-  AsExpression visitAsExpression(AsExpression node) => astFactory.asExpression(
-      cloneNode(node.expression),
-      cloneToken(node.asOperator),
-      cloneNode(node.type));
-
-  @override
-  AstNode visitAssertInitializer(AssertInitializer node) =>
-      astFactory.assertInitializer(
-          cloneToken(node.assertKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.condition),
-          cloneNullableToken(node.comma),
-          cloneNullableNode(node.message),
-          cloneToken(node.rightParenthesis));
-
-  @override
-  AstNode visitAssertStatement(AssertStatement node) =>
-      astFactory.assertStatement(
-          cloneToken(node.assertKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.condition),
-          cloneNullableToken(node.comma),
-          cloneNullableNode(node.message),
-          cloneToken(node.rightParenthesis),
-          cloneToken(node.semicolon));
-
-  @override
-  AssignmentExpression visitAssignmentExpression(AssignmentExpression node) =>
-      astFactory.assignmentExpression(cloneNode(node.leftHandSide),
-          cloneToken(node.operator), cloneNode(node.rightHandSide));
-
-  @override
-  AwaitExpression visitAwaitExpression(AwaitExpression node) =>
-      astFactory.awaitExpression(
-          cloneToken(node.awaitKeyword), cloneNode(node.expression));
-
-  @override
-  BinaryExpression visitBinaryExpression(BinaryExpression node) =>
-      astFactory.binaryExpression(cloneNode(node.leftOperand),
-          cloneToken(node.operator), cloneNode(node.rightOperand));
-
-  @override
-  Block visitBlock(Block node) => astFactory.block(cloneToken(node.leftBracket),
-      cloneNodeList(node.statements), cloneToken(node.rightBracket));
-
-  @override
-  BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) =>
-      astFactory.blockFunctionBody(cloneNullableToken(node.keyword),
-          cloneNullableToken(node.star), cloneNode(node.block));
-
-  @override
-  BooleanLiteral visitBooleanLiteral(BooleanLiteral node) =>
-      astFactory.booleanLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  BreakStatement visitBreakStatement(BreakStatement node) =>
-      astFactory.breakStatement(cloneToken(node.breakKeyword),
-          cloneNullableNode(node.label), cloneToken(node.semicolon));
-
-  @override
-  CascadeExpression visitCascadeExpression(CascadeExpression node) =>
-      astFactory.cascadeExpression(
-          cloneNode(node.target), cloneNodeList(node.cascadeSections));
-
-  @override
-  CatchClause visitCatchClause(CatchClause node) => astFactory.catchClause(
-      cloneNullableToken(node.onKeyword),
-      cloneNullableNode(node.exceptionType),
-      cloneNullableToken(node.catchKeyword),
-      cloneNullableToken(node.leftParenthesis),
-      cloneNullableNode(node.exceptionParameter),
-      cloneNullableToken(node.comma),
-      cloneNullableNode(node.stackTraceParameter),
-      cloneNullableToken(node.rightParenthesis),
-      cloneNode(node.body));
-
-  @override
-  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
-    var copy = astFactory.classDeclaration(
-        cloneNullableNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneNullableToken(node.abstractKeyword),
-        cloneToken(node.classKeyword),
-        cloneNode(node.name),
-        cloneNullableNode(node.typeParameters),
-        cloneNullableNode(node.extendsClause),
-        cloneNullableNode(node.withClause),
-        cloneNullableNode(node.implementsClause),
-        cloneToken(node.leftBracket),
-        cloneNodeList(node.members),
-        cloneToken(node.rightBracket));
-    copy.nativeClause = cloneNullableNode(node.nativeClause);
-    return copy;
-  }
-
-  @override
-  ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) {
-    cloneNullableToken(node.abstractKeyword);
-    return astFactory.classTypeAlias(
-        cloneNullableNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.typedefKeyword),
-        cloneNode(node.name),
-        cloneNullableNode(node.typeParameters),
-        cloneToken(node.equals),
-        cloneNullableToken(node.abstractKeyword),
-        cloneNode(node.superclass),
-        cloneNode(node.withClause),
-        cloneNullableNode(node.implementsClause),
-        cloneToken(node.semicolon));
-  }
-
-  @override
-  Comment visitComment(Comment node) {
-    if (node.isDocumentation) {
-      return astFactory.documentationComment(
-          cloneTokenList(node.tokens), cloneNodeList(node.references));
-    } else if (node.isBlock) {
-      return astFactory.blockComment(cloneTokenList(node.tokens));
-    }
-    return astFactory.endOfLineComment(cloneTokenList(node.tokens));
-  }
-
-  @override
-  CommentReference visitCommentReference(CommentReference node) {
-    // Comment references have a token stream
-    // separate from the compilation unit's token stream.
-    // Clone the tokens in that stream here and add them to _clondedTokens
-    // for use when cloning the comment reference.
-    Token? token = node.beginToken;
-    Token lastCloned = Token.eof(-1);
-    while (token != null) {
-      Token clone = token.copy();
-      _clonedTokens[token] = clone;
-      lastCloned.setNext(clone);
-      lastCloned = clone;
-      if (token.isEof) {
-        break;
-      }
-      token = token.next;
-    }
-    return astFactory.commentReference(
-        cloneNullableToken(node.newKeyword), cloneNode(node.identifier));
-  }
-
-  @override
-  CompilationUnit visitCompilationUnit(CompilationUnit node) {
-    var clone = astFactory.compilationUnit(
-        beginToken: cloneToken(node.beginToken),
-        scriptTag: cloneNullableNode(node.scriptTag),
-        directives: cloneNodeList(node.directives),
-        declarations: cloneNodeList(node.declarations),
-        endToken: cloneToken(node.endToken),
-        featureSet: node.featureSet);
-    clone.lineInfo = node.lineInfo;
-    return clone;
-  }
-
-  @override
-  ConditionalExpression visitConditionalExpression(
-          ConditionalExpression node) =>
-      astFactory.conditionalExpression(
-          cloneNode(node.condition),
-          cloneToken(node.question),
-          cloneNode(node.thenExpression),
-          cloneToken(node.colon),
-          cloneNode(node.elseExpression));
-
-  @override
-  Configuration visitConfiguration(Configuration node) =>
-      astFactory.configuration(
-          cloneToken(node.ifKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.name),
-          cloneNullableToken(node.equalToken),
-          cloneNullableNode(node.value),
-          cloneToken(node.rightParenthesis),
-          cloneNode(node.uri));
-
-  @override
-  ConstructorDeclaration visitConstructorDeclaration(
-          ConstructorDeclaration node) =>
-      astFactory.constructorDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNullableToken(node.externalKeyword),
-          cloneNullableToken(node.constKeyword),
-          cloneNullableToken(node.factoryKeyword),
-          cloneNode(node.returnType),
-          cloneNullableToken(node.period),
-          cloneNullableNode(node.name),
-          cloneNode(node.parameters),
-          cloneNullableToken(node.separator),
-          cloneNodeList(node.initializers),
-          cloneNullableNode(node.redirectedConstructor),
-          cloneNode(node.body));
-
-  @override
-  ConstructorFieldInitializer visitConstructorFieldInitializer(
-          ConstructorFieldInitializer node) =>
-      astFactory.constructorFieldInitializer(
-          cloneNullableToken(node.thisKeyword),
-          cloneNullableToken(node.period),
-          cloneNode(node.fieldName),
-          cloneToken(node.equals),
-          cloneNode(node.expression));
-
-  @override
-  ConstructorNameImpl visitConstructorName(ConstructorName node) =>
-      astFactory.constructorName(cloneNode(node.type),
-          cloneNullableToken(node.period), cloneNullableNode(node.name));
-
-  @override
-  AstNode visitConstructorReference(ConstructorReference node) => astFactory
-      .constructorReference(constructorName: cloneNode(node.constructorName));
-
-  @override
-  ContinueStatement visitContinueStatement(ContinueStatement node) =>
-      astFactory.continueStatement(cloneToken(node.continueKeyword),
-          cloneNullableNode(node.label), cloneToken(node.semicolon));
-
-  @override
-  DeclaredIdentifier visitDeclaredIdentifier(DeclaredIdentifier node) =>
-      astFactory.declaredIdentifier(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNullableToken(node.keyword),
-          cloneNullableNode(node.type),
-          cloneNode(node.identifier));
-
-  @override
-  DefaultFormalParameter visitDefaultFormalParameter(
-          covariant DefaultFormalParameterImpl node) =>
-      astFactory.defaultFormalParameter(
-          cloneNode(node.parameter),
-          node.kind,
-          cloneNullableToken(node.separator),
-          cloneNullableNode(node.defaultValue));
-
-  @override
-  DoStatement visitDoStatement(DoStatement node) => astFactory.doStatement(
-      cloneToken(node.doKeyword),
-      cloneNode(node.body),
-      cloneToken(node.whileKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.rightParenthesis),
-      cloneToken(node.semicolon));
-
-  @override
-  DottedName visitDottedName(DottedName node) =>
-      astFactory.dottedName(cloneNodeList(node.components));
-
-  @override
-  DoubleLiteral visitDoubleLiteral(DoubleLiteral node) =>
-      astFactory.doubleLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  EmptyFunctionBody visitEmptyFunctionBody(EmptyFunctionBody node) =>
-      astFactory.emptyFunctionBody(cloneToken(node.semicolon));
-
-  @override
-  EmptyStatement visitEmptyStatement(EmptyStatement node) =>
-      astFactory.emptyStatement(cloneToken(node.semicolon));
-
-  @override
-  AstNode visitEnumConstantDeclaration(EnumConstantDeclaration node) =>
-      astFactory.enumConstantDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNode(node.name));
-
-  @override
-  EnumDeclaration visitEnumDeclaration(EnumDeclaration node) =>
-      astFactory.enumDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.enumKeyword),
-          cloneNode(node.name),
-          cloneToken(node.leftBracket),
-          cloneNodeList(node.constants),
-          cloneToken(node.rightBracket));
-
-  @override
-  ExportDirective visitExportDirective(ExportDirective node) {
-    var directive = astFactory.exportDirective(
-        cloneNullableNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.keyword),
-        cloneNode(node.uri),
-        cloneNodeList(node.configurations),
-        cloneNodeList(node.combinators),
-        cloneToken(node.semicolon));
-    directive.selectedUriContent = node.selectedUriContent;
-    directive.selectedSource = node.selectedSource;
-    directive.uriSource = node.uriSource;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  ExpressionFunctionBody visitExpressionFunctionBody(
-          ExpressionFunctionBody node) =>
-      astFactory.expressionFunctionBody(
-          cloneNullableToken(node.keyword),
-          cloneToken(node.functionDefinition),
-          cloneNode(node.expression),
-          cloneNullableToken(node.semicolon));
-
-  @override
-  ExpressionStatement visitExpressionStatement(ExpressionStatement node) =>
-      astFactory.expressionStatement(
-          cloneNode(node.expression), cloneNullableToken(node.semicolon));
-
-  @override
-  ExtendsClause visitExtendsClause(ExtendsClause node) =>
-      astFactory.extendsClause(
-          cloneToken(node.extendsKeyword), cloneNode(node.superclass));
-
-  @override
-  ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
-      astFactory.extensionDeclaration(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          extensionKeyword: cloneToken(node.extensionKeyword),
-          name: cloneNullableNode(node.name),
-          typeParameters: cloneNullableNode(node.typeParameters),
-          onKeyword: cloneToken(node.onKeyword),
-          extendedType: cloneNode(node.extendedType),
-          leftBracket: cloneToken(node.leftBracket),
-          members: cloneNodeList(node.members),
-          rightBracket: cloneToken(node.rightBracket));
-
-  @override
-  ExtensionOverride visitExtensionOverride(ExtensionOverride node) =>
-      astFactory.extensionOverride(
-          extensionName: cloneNode(node.extensionName),
-          typeArguments: cloneNullableNode(node.typeArguments),
-          argumentList: cloneNode(node.argumentList));
-
-  @override
-  FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
-      astFactory.fieldDeclaration2(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          abstractKeyword: cloneNullableToken(node.abstractKeyword),
-          covariantKeyword: cloneNullableToken(node.covariantKeyword),
-          externalKeyword: cloneNullableToken(node.externalKeyword),
-          staticKeyword: cloneNullableToken(node.staticKeyword),
-          fieldList: cloneNode(node.fields),
-          semicolon: cloneToken(node.semicolon));
-
-  @override
-  FieldFormalParameter visitFieldFormalParameter(FieldFormalParameter node) =>
-      astFactory.fieldFormalParameter2(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          covariantKeyword: cloneNullableToken(node.covariantKeyword),
-          keyword: cloneNullableToken(node.keyword),
-          type: cloneNullableNode(node.type),
-          thisKeyword: cloneToken(node.thisKeyword),
-          period: cloneToken(node.period),
-          identifier: cloneNode(node.identifier),
-          typeParameters: cloneNullableNode(node.typeParameters),
-          parameters: cloneNullableNode(node.parameters),
-          question: cloneNullableToken(node.question));
-
-  @override
-  ForEachPartsWithDeclaration visitForEachPartsWithDeclaration(
-          ForEachPartsWithDeclaration node) =>
-      astFactory.forEachPartsWithDeclaration(
-          loopVariable: cloneNode(node.loopVariable),
-          inKeyword: cloneToken(node.inKeyword),
-          iterable: cloneNode(node.iterable));
-
-  @override
-  ForEachPartsWithIdentifier visitForEachPartsWithIdentifier(
-          ForEachPartsWithIdentifier node) =>
-      astFactory.forEachPartsWithIdentifier(
-          identifier: cloneNode(node.identifier),
-          inKeyword: cloneToken(node.inKeyword),
-          iterable: cloneNode(node.iterable));
-
-  @override
-  ForElement visitForElement(ForElement node) => astFactory.forElement(
-      awaitKeyword: cloneNullableToken(node.awaitKeyword),
-      forKeyword: cloneToken(node.forKeyword),
-      leftParenthesis: cloneToken(node.leftParenthesis),
-      forLoopParts: cloneNode(node.forLoopParts),
-      rightParenthesis: cloneToken(node.rightParenthesis),
-      body: cloneNode(node.body));
-
-  @override
-  FormalParameterList visitFormalParameterList(FormalParameterList node) =>
-      astFactory.formalParameterList(
-          cloneToken(node.leftParenthesis),
-          cloneNodeList(node.parameters),
-          cloneNullableToken(node.leftDelimiter),
-          cloneNullableToken(node.rightDelimiter),
-          cloneToken(node.rightParenthesis));
-
-  @override
-  ForPartsWithDeclarations visitForPartsWithDeclarations(
-          ForPartsWithDeclarations node) =>
-      astFactory.forPartsWithDeclarations(
-          variables: cloneNode(node.variables),
-          leftSeparator: cloneToken(node.leftSeparator),
-          condition: cloneNullableNode(node.condition),
-          rightSeparator: cloneToken(node.rightSeparator),
-          updaters: cloneNodeList(node.updaters));
-
-  @override
-  ForPartsWithExpression visitForPartsWithExpression(
-          ForPartsWithExpression node) =>
-      astFactory.forPartsWithExpression(
-          initialization: cloneNullableNode(node.initialization),
-          leftSeparator: cloneToken(node.leftSeparator),
-          condition: cloneNullableNode(node.condition),
-          rightSeparator: cloneToken(node.rightSeparator),
-          updaters: cloneNodeList(node.updaters));
-
-  @override
-  ForStatement visitForStatement(ForStatement node) => astFactory.forStatement(
-      awaitKeyword: cloneNullableToken(node.awaitKeyword),
-      forKeyword: cloneToken(node.forKeyword),
-      leftParenthesis: cloneToken(node.leftParenthesis),
-      forLoopParts: cloneNode(node.forLoopParts),
-      rightParenthesis: cloneToken(node.rightParenthesis),
-      body: cloneNode(node.body));
-
-  @override
-  FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) =>
-      astFactory.functionDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNullableToken(node.externalKeyword),
-          cloneNullableNode(node.returnType),
-          cloneNullableToken(node.propertyKeyword),
-          cloneNode(node.name),
-          cloneNode(node.functionExpression));
-
-  @override
-  FunctionDeclarationStatement visitFunctionDeclarationStatement(
-          FunctionDeclarationStatement node) =>
-      astFactory
-          .functionDeclarationStatement(cloneNode(node.functionDeclaration));
-
-  @override
-  FunctionExpression visitFunctionExpression(FunctionExpression node) =>
-      astFactory.functionExpression(cloneNullableNode(node.typeParameters),
-          cloneNullableNode(node.parameters), cloneNode(node.body));
-
-  @override
-  FunctionExpressionInvocation visitFunctionExpressionInvocation(
-          FunctionExpressionInvocation node) =>
-      astFactory.functionExpressionInvocation(cloneNode(node.function),
-          cloneNullableNode(node.typeArguments), cloneNode(node.argumentList));
-
-  @override
-  AstNode visitFunctionReference(FunctionReference node) =>
-      astFactory.functionReference(
-          function: cloneNode(node.function),
-          typeArguments: cloneNullableNode(node.typeArguments));
-
-  @override
-  FunctionTypeAlias visitFunctionTypeAlias(FunctionTypeAlias node) =>
-      astFactory.functionTypeAlias(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.typedefKeyword),
-          cloneNullableNode(node.returnType),
-          cloneNode(node.name),
-          cloneNullableNode(node.typeParameters),
-          cloneNode(node.parameters),
-          cloneToken(node.semicolon));
-
-  @override
-  FunctionTypedFormalParameter visitFunctionTypedFormalParameter(
-          FunctionTypedFormalParameter node) =>
-      astFactory.functionTypedFormalParameter2(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          covariantKeyword: cloneNullableToken(node.covariantKeyword),
-          returnType: cloneNullableNode(node.returnType),
-          identifier: cloneNode(node.identifier),
-          typeParameters: cloneNullableNode(node.typeParameters),
-          parameters: cloneNode(node.parameters),
-          question: cloneNullableToken(node.question));
-
-  @override
-  AstNode visitGenericFunctionType(GenericFunctionType node) =>
-      astFactory.genericFunctionType(
-          cloneNullableNode(node.returnType),
-          cloneToken(node.functionKeyword),
-          cloneNullableNode(node.typeParameters),
-          cloneNode(node.parameters),
-          question: cloneNullableToken(node.question));
-
-  @override
-  AstNode visitGenericTypeAlias(GenericTypeAlias node) =>
-      astFactory.genericTypeAlias(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.typedefKeyword),
-          cloneNode(node.name),
-          cloneNullableNode(node.typeParameters),
-          cloneToken(node.equals),
-          cloneNode(node.type),
-          cloneToken(node.semicolon));
-
-  @override
-  HideCombinator visitHideCombinator(HideCombinator node) =>
-      astFactory.hideCombinator(
-          cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
-
-  @override
-  IfElement visitIfElement(IfElement node) => astFactory.ifElement(
-      ifKeyword: cloneToken(node.ifKeyword),
-      leftParenthesis: cloneToken(node.leftParenthesis),
-      condition: cloneNode(node.condition),
-      rightParenthesis: cloneToken(node.rightParenthesis),
-      thenElement: cloneNode(node.thenElement),
-      elseKeyword: cloneNullableToken(node.elseKeyword),
-      elseElement: cloneNullableNode(node.elseElement));
-
-  @override
-  IfStatement visitIfStatement(IfStatement node) => astFactory.ifStatement(
-      cloneToken(node.ifKeyword),
-      cloneToken(node.leftParenthesis),
-      cloneNode(node.condition),
-      cloneToken(node.rightParenthesis),
-      cloneNode(node.thenStatement),
-      cloneNullableToken(node.elseKeyword),
-      cloneNullableNode(node.elseStatement));
-
-  @override
-  ImplementsClause visitImplementsClause(ImplementsClause node) =>
-      astFactory.implementsClause(
-          cloneToken(node.implementsKeyword), cloneNodeList(node.interfaces));
-
-  @override
-  ImportDirective visitImportDirective(ImportDirective node) {
-    var directive = astFactory.importDirective(
-        cloneNullableNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.keyword),
-        cloneNode(node.uri),
-        cloneNodeList(node.configurations),
-        cloneNullableToken(node.deferredKeyword),
-        cloneNullableToken(node.asKeyword),
-        cloneNullableNode(node.prefix),
-        cloneNodeList(node.combinators),
-        cloneToken(node.semicolon));
-    directive.selectedUriContent = node.selectedUriContent;
-    directive.selectedSource = node.selectedSource;
-    directive.uriSource = node.uriSource;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  IndexExpression visitIndexExpression(IndexExpression node) {
-    var period = node.period;
-    if (period == null) {
-      return astFactory.indexExpressionForTarget2(
-          target: cloneNode(node.target!),
-          leftBracket: cloneToken(node.leftBracket),
-          index: cloneNode(node.index),
-          rightBracket: cloneToken(node.rightBracket));
-    } else {
-      return astFactory.indexExpressionForCascade2(
-          period: cloneToken(period),
-          leftBracket: cloneToken(node.leftBracket),
-          index: cloneNode(node.index),
-          rightBracket: cloneToken(node.rightBracket));
-    }
-  }
-
-  @override
-  InstanceCreationExpressionImpl visitInstanceCreationExpression(
-          InstanceCreationExpression node) =>
-      astFactory.instanceCreationExpression(cloneNullableToken(node.keyword),
-          cloneNode(node.constructorName), cloneNode(node.argumentList));
-
-  @override
-  IntegerLiteralImpl visitIntegerLiteral(IntegerLiteral node) =>
-      astFactory.integerLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  InterpolationExpressionImpl visitInterpolationExpression(
-          InterpolationExpression node) =>
-      astFactory.interpolationExpression(cloneToken(node.leftBracket),
-          cloneNode(node.expression), cloneNullableToken(node.rightBracket));
-
-  @override
-  InterpolationString visitInterpolationString(InterpolationString node) =>
-      astFactory.interpolationString(cloneToken(node.contents), node.value);
-
-  @override
-  IsExpression visitIsExpression(IsExpression node) => astFactory.isExpression(
-      cloneNode(node.expression),
-      cloneToken(node.isOperator),
-      cloneNullableToken(node.notOperator),
-      cloneNode(node.type));
-
-  @override
-  Label visitLabel(Label node) =>
-      astFactory.label(cloneNode(node.label), cloneToken(node.colon));
-
-  @override
-  LabeledStatement visitLabeledStatement(LabeledStatement node) => astFactory
-      .labeledStatement(cloneNodeList(node.labels), cloneNode(node.statement));
-
-  @override
-  LibraryDirective visitLibraryDirective(LibraryDirective node) =>
-      astFactory.libraryDirective(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.libraryKeyword),
-          cloneNode(node.name),
-          cloneToken(node.semicolon));
-
-  @override
-  LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) =>
-      astFactory.libraryIdentifier(cloneNodeList(node.components));
-
-  @override
-  ListLiteralImpl visitListLiteral(ListLiteral node) => astFactory.listLiteral(
-      cloneNullableToken(node.constKeyword),
-      cloneNullableNode(node.typeArguments),
-      cloneToken(node.leftBracket),
-      cloneNodeList(node.elements),
-      cloneToken(node.rightBracket));
-
-  @override
-  MapLiteralEntry visitMapLiteralEntry(MapLiteralEntry node) =>
-      astFactory.mapLiteralEntry(cloneNode(node.key),
-          cloneToken(node.separator), cloneNode(node.value));
-
-  @override
-  MethodDeclaration visitMethodDeclaration(MethodDeclaration node) =>
-      astFactory.methodDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNullableToken(node.externalKeyword),
-          cloneNullableToken(node.modifierKeyword),
-          cloneNullableNode(node.returnType),
-          cloneNullableToken(node.propertyKeyword),
-          cloneNullableToken(node.operatorKeyword),
-          cloneNode(node.name),
-          cloneNullableNode(node.typeParameters),
-          cloneNullableNode(node.parameters),
-          cloneNode(node.body));
-
-  @override
-  MethodInvocation visitMethodInvocation(MethodInvocation node) =>
-      astFactory.methodInvocation(
-          cloneNullableNode(node.target),
-          cloneNullableToken(node.operator),
-          cloneNode(node.methodName),
-          cloneNullableNode(node.typeArguments),
-          cloneNode(node.argumentList));
-
-  @override
-  AstNode visitMixinDeclaration(MixinDeclaration node) =>
-      astFactory.mixinDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.mixinKeyword),
-          cloneNode(node.name),
-          cloneNullableNode(node.typeParameters),
-          cloneNullableNode(node.onClause),
-          cloneNullableNode(node.implementsClause),
-          cloneToken(node.leftBracket),
-          cloneNodeList(node.members),
-          cloneToken(node.rightBracket));
-
-  @override
-  NamedExpression visitNamedExpression(NamedExpression node) => astFactory
-      .namedExpression(cloneNode(node.name), cloneNode(node.expression));
-
-  @override
-  AstNode visitNativeClause(NativeClause node) => astFactory.nativeClause(
-      cloneToken(node.nativeKeyword), cloneNullableNode(node.name));
-
-  @override
-  NativeFunctionBody visitNativeFunctionBody(NativeFunctionBody node) =>
-      astFactory.nativeFunctionBody(cloneToken(node.nativeKeyword),
-          cloneNullableNode(node.stringLiteral), cloneToken(node.semicolon));
-
-  @override
-  NullLiteral visitNullLiteral(NullLiteral node) =>
-      astFactory.nullLiteral(cloneToken(node.literal));
-
-  @override
-  AstNode visitOnClause(OnClause node) => astFactory.onClause(
-      cloneToken(node.onKeyword), cloneNodeList(node.superclassConstraints));
-
-  @override
-  ParenthesizedExpression visitParenthesizedExpression(
-          ParenthesizedExpression node) =>
-      astFactory.parenthesizedExpression(cloneToken(node.leftParenthesis),
-          cloneNode(node.expression), cloneToken(node.rightParenthesis));
-
-  @override
-  PartDirective visitPartDirective(PartDirective node) {
-    var directive = astFactory.partDirective(
-        cloneNullableNode(node.documentationComment),
-        cloneNodeList(node.metadata),
-        cloneToken(node.partKeyword),
-        cloneNode(node.uri),
-        cloneToken(node.semicolon));
-    directive.uriSource = node.uriSource;
-    directive.uriContent = node.uriContent;
-    return directive;
-  }
-
-  @override
-  PartOfDirective visitPartOfDirective(PartOfDirective node) =>
-      astFactory.partOfDirective(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneToken(node.partKeyword),
-          cloneToken(node.ofKeyword),
-          cloneNullableNode(node.uri),
-          cloneNullableNode(node.libraryName),
-          cloneToken(node.semicolon));
-
-  @override
-  PostfixExpression visitPostfixExpression(PostfixExpression node) => astFactory
-      .postfixExpression(cloneNode(node.operand), cloneToken(node.operator));
-
-  @override
-  PrefixedIdentifier visitPrefixedIdentifier(PrefixedIdentifier node) =>
-      astFactory.prefixedIdentifier(cloneNode(node.prefix),
-          cloneToken(node.period), cloneNode(node.identifier));
-
-  @override
-  PrefixExpression visitPrefixExpression(PrefixExpression node) => astFactory
-      .prefixExpression(cloneToken(node.operator), cloneNode(node.operand));
-
-  @override
-  PropertyAccess visitPropertyAccess(PropertyAccess node) =>
-      astFactory.propertyAccess(cloneNullableNode(node.target),
-          cloneToken(node.operator), cloneNode(node.propertyName));
-
-  @override
-  RedirectingConstructorInvocationImpl visitRedirectingConstructorInvocation(
-          RedirectingConstructorInvocation node) =>
-      astFactory.redirectingConstructorInvocation(
-          cloneToken(node.thisKeyword),
-          cloneNullableToken(node.period),
-          cloneNullableNode(node.constructorName),
-          cloneNode(node.argumentList));
-
-  @override
-  RethrowExpression visitRethrowExpression(RethrowExpression node) =>
-      astFactory.rethrowExpression(cloneToken(node.rethrowKeyword));
-
-  @override
-  ReturnStatement visitReturnStatement(ReturnStatement node) =>
-      astFactory.returnStatement(cloneToken(node.returnKeyword),
-          cloneNullableNode(node.expression), cloneToken(node.semicolon));
-
-  @override
-  ScriptTag visitScriptTag(ScriptTag node) =>
-      astFactory.scriptTag(cloneToken(node.scriptTag));
-
-  @override
-  SetOrMapLiteralImpl visitSetOrMapLiteral(SetOrMapLiteral node) {
-    var result = astFactory.setOrMapLiteral(
-        constKeyword: cloneNullableToken(node.constKeyword),
-        typeArguments: cloneNullableNode(node.typeArguments),
-        leftBracket: cloneToken(node.leftBracket),
-        elements: cloneNodeList(node.elements),
-        rightBracket: cloneToken(node.rightBracket));
-    if (node.isMap) {
-      result.becomeMap();
-    } else if (node.isSet) {
-      result.becomeSet();
-    }
-    return result;
-  }
-
-  @override
-  ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory
-      .showCombinator(cloneToken(node.keyword), cloneNodeList(node.shownNames));
-
-  @override
-  SimpleFormalParameter visitSimpleFormalParameter(
-          SimpleFormalParameter node) =>
-      astFactory.simpleFormalParameter2(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          covariantKeyword: cloneNullableToken(node.covariantKeyword),
-          keyword: cloneNullableToken(node.keyword),
-          type: cloneNullableNode(node.type),
-          identifier: cloneNullableNode(node.identifier));
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) =>
-      astFactory.simpleIdentifier(cloneToken(node.token),
-          isDeclaration: node.inDeclarationContext());
-
-  @override
-  SimpleStringLiteral visitSimpleStringLiteral(SimpleStringLiteral node) =>
-      astFactory.simpleStringLiteral(cloneToken(node.literal), node.value);
-
-  @override
-  SpreadElement visitSpreadElement(SpreadElement node) =>
-      astFactory.spreadElement(
-          spreadOperator: cloneToken(node.spreadOperator),
-          expression: cloneNode(node.expression));
-
-  @override
-  StringInterpolation visitStringInterpolation(StringInterpolation node) =>
-      astFactory.stringInterpolation(cloneNodeList(node.elements));
-
-  @override
-  SuperConstructorInvocationImpl visitSuperConstructorInvocation(
-          SuperConstructorInvocation node) =>
-      astFactory.superConstructorInvocation(
-          cloneToken(node.superKeyword),
-          cloneNullableToken(node.period),
-          cloneNullableNode(node.constructorName),
-          cloneNode(node.argumentList));
-
-  @override
-  SuperExpression visitSuperExpression(SuperExpression node) =>
-      astFactory.superExpression(cloneToken(node.superKeyword));
-
-  @override
-  SwitchCase visitSwitchCase(SwitchCase node) => astFactory.switchCase(
-      cloneNodeList(node.labels),
-      cloneToken(node.keyword),
-      cloneNode(node.expression),
-      cloneToken(node.colon),
-      cloneNodeList(node.statements));
-
-  @override
-  SwitchDefault visitSwitchDefault(SwitchDefault node) =>
-      astFactory.switchDefault(
-          cloneNodeList(node.labels),
-          cloneToken(node.keyword),
-          cloneToken(node.colon),
-          cloneNodeList(node.statements));
-
-  @override
-  SwitchStatement visitSwitchStatement(SwitchStatement node) =>
-      astFactory.switchStatement(
-          cloneToken(node.switchKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.expression),
-          cloneToken(node.rightParenthesis),
-          cloneToken(node.leftBracket),
-          cloneNodeList(node.members),
-          cloneToken(node.rightBracket));
-
-  @override
-  SymbolLiteral visitSymbolLiteral(SymbolLiteral node) =>
-      astFactory.symbolLiteral(
-          cloneToken(node.poundSign), cloneTokenList(node.components));
-
-  @override
-  ThisExpression visitThisExpression(ThisExpression node) =>
-      astFactory.thisExpression(cloneToken(node.thisKeyword));
-
-  @override
-  ThrowExpression visitThrowExpression(ThrowExpression node) =>
-      astFactory.throwExpression(
-          cloneToken(node.throwKeyword), cloneNode(node.expression));
-
-  @override
-  TopLevelVariableDeclaration visitTopLevelVariableDeclaration(
-          TopLevelVariableDeclaration node) =>
-      astFactory.topLevelVariableDeclaration(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNode(node.variables),
-          cloneToken(node.semicolon),
-          externalKeyword: cloneNullableToken(node.externalKeyword));
-
-  @override
-  TryStatement visitTryStatement(TryStatement node) => astFactory.tryStatement(
-      cloneToken(node.tryKeyword),
-      cloneNode(node.body),
-      cloneNodeList(node.catchClauses),
-      cloneNullableToken(node.finallyKeyword),
-      cloneNullableNode(node.finallyBlock));
-
-  @override
-  TypeArgumentList visitTypeArgumentList(TypeArgumentList node) =>
-      astFactory.typeArgumentList(cloneToken(node.leftBracket),
-          cloneNodeList(node.arguments), cloneToken(node.rightBracket));
-
-  @override
-  TypeLiteral visitTypeLiteral(TypeLiteral node) =>
-      astFactory.typeLiteral(typeName: cloneNode(node.typeName));
-
-  @override
-  TypeNameImpl visitTypeName(TypeName node) => astFactory.typeName(
-      cloneNode(node.name), cloneNullableNode(node.typeArguments),
-      question: cloneNullableToken(node.question));
-
-  @override
-  TypeParameter visitTypeParameter(TypeParameter node) =>
-      // TODO (kallentu) : Clean up TypeParameterImpl and AstFactoryImpl casting
-      // once variance is added to the interface.
-      astFactory.typeParameter2(
-          comment: cloneNullableNode(node.documentationComment),
-          metadata: cloneNodeList(node.metadata),
-          name: cloneNode(node.name),
-          extendsKeyword: cloneNullableToken(node.extendsKeyword),
-          bound: cloneNullableNode(node.bound),
-          varianceKeyword:
-              cloneNullableToken((node as TypeParameterImpl).varianceKeyword));
-
-  @override
-  TypeParameterList visitTypeParameterList(TypeParameterList node) =>
-      astFactory.typeParameterList(cloneToken(node.leftBracket),
-          cloneNodeList(node.typeParameters), cloneToken(node.rightBracket));
-
-  @override
-  VariableDeclaration visitVariableDeclaration(VariableDeclaration node) =>
-      astFactory.variableDeclaration(cloneNode(node.name),
-          cloneNullableToken(node.equals), cloneNullableNode(node.initializer));
-
-  @override
-  VariableDeclarationList visitVariableDeclarationList(
-          VariableDeclarationList node) =>
-      astFactory.variableDeclarationList(
-          cloneNullableNode(node.documentationComment),
-          cloneNodeList(node.metadata),
-          cloneNullableToken(node.keyword),
-          cloneNullableNode(node.type),
-          cloneNodeList(node.variables));
-
-  @override
-  VariableDeclarationStatement visitVariableDeclarationStatement(
-          VariableDeclarationStatement node) =>
-      astFactory.variableDeclarationStatement(
-          cloneNode(node.variables), cloneToken(node.semicolon));
-
-  @override
-  WhileStatement visitWhileStatement(WhileStatement node) =>
-      astFactory.whileStatement(
-          cloneToken(node.whileKeyword),
-          cloneToken(node.leftParenthesis),
-          cloneNode(node.condition),
-          cloneToken(node.rightParenthesis),
-          cloneNode(node.body));
-
-  @override
-  WithClause visitWithClause(WithClause node) => astFactory.withClause(
-      cloneToken(node.withKeyword), cloneNodeList(node.mixinTypes));
-
-  @override
-  YieldStatement visitYieldStatement(YieldStatement node) =>
-      astFactory.yieldStatement(
-          cloneToken(node.yieldKeyword),
-          cloneNullableToken(node.star),
-          cloneNode(node.expression),
-          cloneToken(node.semicolon));
-
-  /// Clones a synthetic token that isn't linked up to the rest of the token
-  /// list.
-  Token _cloneSyntheticToken(Token token) {
-    assert(token.isSynthetic);
-    assert(token.next == null);
-    assert(token.previous == null);
-    return token.copy();
-  }
-
-  /// Clone all token starting from the given [token] up to a token that has
-  /// offset greater then [stopAfter], and put mapping from originals to clones
-  /// into [_clonedTokens].
-  ///
-  /// We cannot clone tokens as we visit nodes because not every token is a part
-  /// of a node, E.g. commas in argument lists are not represented in AST. But
-  /// we need to the sequence of tokens that is identical to the original one.
-  void _cloneTokens(Token? token, int stopAfter) {
-    if (token == null) {
-      return;
-    }
-    Token nonComment(Token token) {
-      return token is CommentToken ? token.parent! : token;
-    }
-
-    token = nonComment(token);
-    _lastCloned ??= Token.eof(-1);
-    while (token != null) {
-      Token clone = token.copy();
-      {
-        CommentToken? c1 = token.precedingComments;
-        CommentToken? c2 = clone.precedingComments;
-        while (c1 != null && c2 != null) {
-          _clonedTokens[c1] = c2;
-          c1 = c1.next as CommentToken?;
-          c2 = c2.next as CommentToken?;
-        }
-      }
-      _clonedTokens[token] = clone;
-      _lastCloned!.setNext(clone);
-      _lastCloned = clone;
-      if (token.type == TokenType.EOF) {
-        break;
-      }
-      if (token.offset > stopAfter) {
-        _nextToClone = token.next;
-        _lastClonedOffset = token.offset;
-        break;
-      }
-      token = token.next;
-    }
-  }
-
-  /// Return a clone of the given [node].
-  static AstNode clone(AstNode node) {
-    return node.accept(AstCloner())!;
-  }
-}
-
 /// An AstVisitor that compares the structure of two AstNodes to see whether
 /// they are equal.
 class AstComparator implements AstVisitor<bool> {
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index ad2fd4f..ff75f88 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -68,7 +68,7 @@
     this._resolver,
     this._migratableAstInfoProvider, {
     required InvocationInferenceHelper inferenceHelper,
-  })   : _typeType = _resolver.typeProvider.typeType,
+  })  : _typeType = _resolver.typeProvider.typeType,
         _inheritance = _resolver.inheritance,
         _definingLibrary = _resolver.definingLibrary,
         _definingLibraryUri = _resolver.definingLibrary.source.uri,
@@ -185,6 +185,24 @@
     return type is InterfaceType && type.isDartCoreFunction;
   }
 
+  /// Record that the static type of the given node is the given type.
+  ///
+  /// @param expression the node whose type is to be recorded
+  /// @param type the static type of the node
+  ///
+  /// TODO(scheglov) this is duplicate
+  void _recordStaticType(ExpressionImpl expression, DartType type) {
+    var hooks = _resolver.migrationResolutionHooks;
+    if (hooks != null) {
+      type = hooks.modifyExpressionType(expression, type);
+    }
+
+    expression.staticType = type;
+    if (_resolver.typeSystem.isBottom(type)) {
+      _resolver.flowAnalysis?.flow?.handleExit();
+    }
+  }
+
   void _reportInstanceAccessToStaticMember(
     SimpleIdentifier nameNode,
     ExecutableElement element,
@@ -786,7 +804,7 @@
     DartType getterReturnType,
   ) {
     var targetType = _resolveTypeParameter(getterReturnType);
-    node.methodName.staticType = targetType;
+    _recordStaticType(node.methodName, targetType);
 
     ExpressionImpl functionExpression;
     var target = node.target;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index bd69138..7679722 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -86,7 +86,7 @@
   /// Helper for resolving properties on types.
   final TypePropertyResolver _typePropertyResolver;
 
-  late final MethodInvocationResolver _methodInvocationResolver;
+  final MethodInvocationResolver _methodInvocationResolver;
 
   /// Initialize a newly created visitor to work for the given [_resolver] to
   /// resolve the nodes in a compilation unit.
@@ -94,13 +94,12 @@
       {MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()})
       : _definingLibrary = _resolver.definingLibrary,
-        _typePropertyResolver = _resolver.typePropertyResolver {
-    _methodInvocationResolver = MethodInvocationResolver(
-      _resolver,
-      migratableAstInfoProvider,
-      inferenceHelper: _resolver.inferenceHelper,
-    );
-  }
+        _typePropertyResolver = _resolver.typePropertyResolver,
+        _methodInvocationResolver = MethodInvocationResolver(
+          _resolver,
+          migratableAstInfoProvider,
+          inferenceHelper: _resolver.inferenceHelper,
+        );
 
   /// Return `true` iff the current enclosing function is a constant constructor
   /// declaration.
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 9850164..9b4fa31 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -287,6 +287,7 @@
       rightOperand,
     );
     node.staticElement = _reader.readElement() as MethodElement?;
+    node.staticInvokeType = _reader.readOptionalFunctionType();
     _readExpressionResolution(node);
     return node;
   }
@@ -352,12 +353,11 @@
     return node;
   }
 
-  SimpleIdentifier _readDeclarationName() {
+  SimpleIdentifierImpl _readDeclarationName() {
     var name = _reader.readStringReference();
-    var node = astFactory.simpleIdentifier(
+    return astFactory.simpleIdentifier(
       StringToken(TokenType.STRING, name, -1),
     );
-    return node;
   }
 
   DeclaredIdentifier _readDeclaredIdentifier() {
@@ -413,6 +413,7 @@
     if (parameter is SimpleFormalParameterImpl) {
       parameter.declaredElement = element;
     }
+    node.identifier?.staticElement = element;
     element.type = nonDefaultElement.type;
 
     return node;
@@ -856,9 +857,11 @@
   }
 
   NullLiteral _readNullLiteral() {
-    return astFactory.nullLiteral(
+    var node = astFactory.nullLiteral(
       Tokens.null_(),
     );
+    _readExpressionResolution(node);
+    return node;
   }
 
   AstNode? _readOptionalNode() {
@@ -1031,6 +1034,7 @@
     element.parameterKind = node.kind;
     element.type = actualType;
     node.declaredElement = element;
+    identifier?.staticElement = element;
 
     return node;
   }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 3578bc6..7e73650 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -114,6 +114,7 @@
     _writeByte(binaryToken.index);
 
     _sink.writeElement(node.staticElement);
+    _sink.writeType(node.staticInvokeType);
     _storeExpression(node);
   }
 
@@ -493,6 +494,7 @@
   @override
   void visitNullLiteral(NullLiteral node) {
     _writeByte(Tag.NullLiteral);
+    _storeExpression(node);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 2346e51..9133c5f 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -1378,6 +1378,11 @@
     throw UnimplementedError('memberFlags: $memberFlags');
   }
 
+  FunctionType? readOptionalFunctionType() {
+    var type = readType();
+    return type is FunctionType ? type : null;
+  }
+
   List<DartType>? readOptionalTypeList() {
     if (_reader.readBool()) {
       return _readTypeList();
@@ -1632,15 +1637,7 @@
   }
 
   InterfaceType _readInterfaceType() {
-    var element = _readRawElement() as ClassElement;
-    var typeArguments = _readTypeList();
-    var nullability = _readNullability();
-    var type = InterfaceTypeImpl(
-      element: element,
-      typeArguments: typeArguments,
-      nullabilitySuffix: nullability,
-    );
-    return type;
+    return readType() as InterfaceType;
   }
 
   List<InterfaceType> _readInterfaceTypeList() {
@@ -1670,10 +1667,7 @@
   }
 
   InterfaceType? _readOptionalInterfaceType() {
-    var hasSuperType = _reader.readByte() != 0;
-    if (hasSuperType) {
-      return _readInterfaceType();
-    }
+    return readType() as InterfaceType?;
   }
 
   Element? _readRawElement() {
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index e16d25e..96a536b 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -132,9 +132,9 @@
     _resolutionSink._writeAnnotationList(element.metadata);
 
     _writeTypeParameters(element.typeParameters, () {
-      _resolutionSink.writeOptionalInterfaceType(element.supertype);
-      _resolutionSink._writeInterfaceTypeList(element.mixins);
-      _resolutionSink._writeInterfaceTypeList(element.interfaces);
+      _resolutionSink.writeType(element.supertype);
+      _resolutionSink._writeTypeList(element.mixins);
+      _resolutionSink._writeTypeList(element.interfaces);
 
       if (!element.isMixinApplication) {
         var membersOffset = _sink.offset;
@@ -303,8 +303,8 @@
     _resolutionSink._writeAnnotationList(element.metadata);
 
     _writeTypeParameters(element.typeParameters, () {
-      _resolutionSink._writeInterfaceTypeList(element.superclassConstraints);
-      _resolutionSink._writeInterfaceTypeList(element.interfaces);
+      _resolutionSink._writeTypeList(element.superclassConstraints);
+      _resolutionSink._writeTypeList(element.interfaces);
 
       _writeList(
         element.accessors.where((e) => !e.isSynthetic).toList(),
@@ -528,25 +528,6 @@
     }
   }
 
-  void writeInterfaceType(InterfaceType type) {
-    _writeElement(type.element);
-    var typeArguments = type.typeArguments;
-    writeUInt30(typeArguments.length);
-    for (var i = 0; i < typeArguments.length; ++i) {
-      writeType(typeArguments[i]);
-    }
-    _writeNullabilitySuffix(type.nullabilitySuffix);
-  }
-
-  void writeOptionalInterfaceType(InterfaceType? type) {
-    if (type != null) {
-      writeByte(1);
-      writeInterfaceType(type);
-    } else {
-      writeByte(0);
-    }
-  }
-
   void writeOptionalTypeList(List<DartType>? types) {
     if (types != null) {
       writeBool(true);
@@ -694,13 +675,6 @@
     _writeNullabilitySuffix(type.nullabilitySuffix);
   }
 
-  void _writeInterfaceTypeList(List<InterfaceType> types) {
-    writeUInt30(types.length);
-    for (var type in types) {
-      writeInterfaceType(type);
-    }
-  }
-
   void _writeNode(AstNode node) {
     var astWriter = AstBinaryWriter(
       sink: this,
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index a96e330..a3e1768 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -413,6 +413,7 @@
     _setupApplyConstantOffsetsForTypeAlias(
       element,
       info.constantOffsets,
+      aliasedFormalParameters: info.parameters,
     );
   }
 
@@ -432,6 +433,8 @@
     _setupApplyConstantOffsetsForTypeAlias(
       element,
       info.constantOffsets,
+      aliasedFormalParameters: info.aliasedFormalParameters,
+      aliasedTypeParameters: info.aliasedTypeParameters,
     );
   }
 
@@ -590,8 +593,10 @@
 
   void _setupApplyConstantOffsetsForTypeAlias(
     TypeAliasElementImpl element,
-    Uint32List constantOffsets,
-  ) {
+    Uint32List constantOffsets, {
+    List<_InfoFormalParameter>? aliasedFormalParameters,
+    List<_InfoTypeParameter>? aliasedTypeParameters,
+  }) {
     var linkedData = element.linkedData as TypeAliasElementLinkedData;
     linkedData.applyConstantOffsets = ApplyConstantOffsets(
       constantOffsets,
@@ -603,6 +608,18 @@
         if (aliasedElement is FunctionTypedElementImpl) {
           applier.applyToTypeParameters(aliasedElement.typeParameters);
           applier.applyToFormalParameters(aliasedElement);
+          if (aliasedTypeParameters != null) {
+            _applyToTypeParameters(
+              aliasedElement.typeParameters,
+              aliasedTypeParameters,
+            );
+          }
+          if (aliasedFormalParameters != null) {
+            _applyToFormalParameters(
+              aliasedElement.parameters,
+              aliasedFormalParameters,
+            );
+          }
         }
       },
     );
@@ -953,6 +970,8 @@
   final int nameOffset;
   final String? documentationComment;
   final List<_InfoTypeParameter> typeParameters;
+  final List<_InfoTypeParameter> aliasedTypeParameters;
+  final List<_InfoFormalParameter> aliasedFormalParameters;
   final Uint32List constantOffsets;
 
   factory _InfoGenericTypeAlias(SummaryDataReader reader) {
@@ -964,6 +983,12 @@
       typeParameters: reader.readTypedList(
         () => _InfoTypeParameter(reader),
       ),
+      aliasedTypeParameters: reader.readTypedList(
+        () => _InfoTypeParameter(reader),
+      ),
+      aliasedFormalParameters: reader.readTypedList(
+        () => _InfoFormalParameter(reader),
+      ),
       constantOffsets: reader.readUInt30List(),
     );
   }
@@ -974,6 +999,8 @@
     required this.nameOffset,
     required this.documentationComment,
     required this.typeParameters,
+    required this.aliasedTypeParameters,
+    required this.aliasedFormalParameters,
     required this.constantOffsets,
   });
 }
@@ -1213,11 +1240,19 @@
     });
 
     sink.writeList2<GenericTypeAlias>(unit.declarations, (node) {
+      var aliasedType = node.type;
       sink.writeUInt30(node.offset);
       sink.writeUInt30(node.length);
       sink.writeUInt30(node.name.offset);
       _writeDocumentationComment(node);
       _writeTypeParameters(node.typeParameters);
+      if (aliasedType is GenericFunctionType) {
+        _writeTypeParameters(aliasedType.typeParameters);
+        _writeFormalParameters(aliasedType.parameters);
+      } else {
+        _writeTypeParameters(null);
+        _writeFormalParameters(null);
+      }
       _writeOffsets(
         metadata: node.metadata,
         typeParameters: node.typeParameters,
@@ -1663,6 +1698,17 @@
       token.offset = offset;
     }
   }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    super.visitSimpleFormalParameter(node);
+
+    var element = node.declaredElement;
+    var identifier = node.identifier;
+    if (element is ParameterElementImpl && identifier != null) {
+      element.nameOffset = identifier.offset;
+    }
+  }
 }
 
 abstract class _OffsetsAstVisitor extends RecursiveAstVisitor<void> {
@@ -1739,6 +1785,12 @@
   }
 
   @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    _tokenOrNull(node.functionKeyword);
+    super.visitGenericFunctionType(node);
+  }
+
+  @override
   void visitIndexExpression(IndexExpression node) {
     _tokenOrNull(node.leftBracket);
     _tokenOrNull(node.rightBracket);
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 60aba02a..589c79a 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -2,18 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
@@ -21,11 +16,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'test_support.dart';
-
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(AstClonerTest);
     defineReflectiveTests(BooleanArrayTest);
     defineReflectiveTests(ExceptionHandlingDelegatingAstVisitorTest);
     defineReflectiveTests(LineInfoTest);
@@ -65,1227 +57,6 @@
 }
 
 @reflectiveTest
-class AstClonerTest {
-  void test_visitAdjacentStrings() {
-    _assertCloneExpression("'a' 'b'");
-  }
-
-  void test_visitAnnotation_constant() {
-    _assertCloneUnitMember('@A main() {}');
-  }
-
-  void test_visitAnnotation_constructor() {
-    _assertCloneUnitMember('@A.c() main() {}');
-  }
-
-  void test_visitAnnotation_constructor_generic() {
-    _assertCloneUnitMember('@A<int>.c() main() {}',
-        featureSet: FeatureSet.forTesting(
-            sdkVersion: '2.12',
-            additionalFeatures: [Feature.generic_metadata]));
-  }
-
-  void test_visitAnnotation_withComment() {
-    CompilationUnitMember clazz =
-        _parseUnitMember('/** comment */ @deprecated class A {}');
-    Annotation annotation = clazz.metadata.single;
-    _assertClone(annotation);
-  }
-
-  void test_visitArgumentList() {
-    _assertCloneExpression('m(a, b)');
-  }
-
-  void test_visitAsExpression() {
-    _assertCloneExpression('e as T');
-  }
-
-  void test_visitAssertStatement() {
-    _assertCloneStatement('assert(a);');
-  }
-
-  void test_visitAssignmentExpression() {
-    _assertCloneStatement('a = b;');
-  }
-
-  void test_visitAwaitExpression() {
-    _assertCloneStatement('await a;');
-  }
-
-  void test_visitBinaryExpression() {
-    _assertCloneExpression('a + b');
-  }
-
-  void test_visitBlock_empty() {
-    _assertCloneStatement('{}');
-  }
-
-  void test_visitBlock_nonEmpty() {
-    _assertCloneStatement('{ print(1); print(2); }');
-  }
-
-  void test_visitBlockFunctionBody() {
-    _assertCloneUnitMember('main() {}');
-  }
-
-  void test_visitBooleanLiteral_false() {
-    _assertCloneExpression('false');
-  }
-
-  void test_visitBooleanLiteral_true() {
-    _assertCloneExpression('true');
-  }
-
-  void test_visitBreakStatement_label() {
-    _assertCloneStatement('l: while(true) { break l; }');
-  }
-
-  void test_visitBreakStatement_noLabel() {
-    _assertCloneStatement('while(true) { break; }');
-  }
-
-  void test_visitCascadeExpression_field() {
-    _assertCloneExpression('a..b..c');
-  }
-
-  void test_visitCascadeExpression_index() {
-    _assertCloneExpression('a..[0]..[1]');
-  }
-
-  void test_visitCascadeExpression_method() {
-    _assertCloneExpression('a..b()..c()');
-  }
-
-  void test_visitCatchClause_catch_noStack() {
-    _assertCloneStatement('try {} catch (e) {}');
-  }
-
-  void test_visitCatchClause_catch_stack() {
-    _assertCloneStatement('try {} catch (e, s) {}');
-  }
-
-  void test_visitCatchClause_on() {
-    _assertCloneStatement('try {} on E {}');
-  }
-
-  void test_visitCatchClause_on_catch() {
-    _assertCloneStatement('try {} on E catch (e) {}');
-  }
-
-  void test_visitClassDeclaration_abstract() {
-    _assertCloneUnitMember('abstract class C {}');
-  }
-
-  void test_visitClassDeclaration_empty() {
-    _assertCloneUnitMember('class C {}');
-  }
-
-  void test_visitClassDeclaration_extends() {
-    _assertCloneUnitMember('class C extends A {}');
-  }
-
-  void test_visitClassDeclaration_extends_implements() {
-    _assertCloneUnitMember('class C extends A implements B {}');
-  }
-
-  void test_visitClassDeclaration_extends_with() {
-    _assertCloneUnitMember('class C extends A with M {}');
-  }
-
-  void test_visitClassDeclaration_extends_with_implements() {
-    _assertCloneUnitMember('class C extends A with M implements B {}');
-  }
-
-  void test_visitClassDeclaration_implements() {
-    _assertCloneUnitMember('class C implements B {}');
-  }
-
-  void test_visitClassDeclaration_multipleMember() {
-    _assertCloneUnitMember('class C { var a;  var b; }');
-  }
-
-  void test_visitClassDeclaration_parameters() {
-    _assertCloneUnitMember('class C<E> {}');
-  }
-
-  void test_visitClassDeclaration_parameters_extends() {
-    _assertCloneUnitMember('class C<E> extends A {}');
-  }
-
-  void test_visitClassDeclaration_parameters_extends_implements() {
-    _assertCloneUnitMember('class C<E> extends A implements B {}');
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with() {
-    _assertCloneUnitMember('class C<E> extends A with M {}');
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with_implements() {
-    _assertCloneUnitMember('class C<E> extends A with M implements B {}');
-  }
-
-  void test_visitClassDeclaration_parameters_implements() {
-    _assertCloneUnitMember('class C<E> implements B {}');
-  }
-
-  void test_visitClassDeclaration_singleMember() {
-    _assertCloneUnitMember('class C { var a; }');
-  }
-
-  void test_visitClassDeclaration_withMetadata() {
-    _assertCloneUnitMember('@deprecated class C {}');
-  }
-
-  void test_visitClassTypeAlias_abstract() {
-    _assertCloneUnitMember('abstract class C = S with M1;');
-  }
-
-  void test_visitClassTypeAlias_abstract_implements() {
-    _assertCloneUnitMember('abstract class C = S with M1 implements I;');
-  }
-
-  void test_visitClassTypeAlias_generic() {
-    _assertCloneUnitMember('class C<E> = S<E> with M1<E>;');
-  }
-
-  void test_visitClassTypeAlias_implements() {
-    _assertCloneUnitMember('class C = S with M1 implements I;');
-  }
-
-  void test_visitClassTypeAlias_minimal() {
-    _assertCloneUnitMember('class C = S with M1;');
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract() {
-    _assertCloneUnitMember('abstract class C = S<E> with M1;');
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract_implements() {
-    _assertCloneUnitMember('abstract class C = S<E> with M1 implements I;');
-  }
-
-  void test_visitClassTypeAlias_parameters_implements() {
-    _assertCloneUnitMember('class C = S<E> with M1 implements I;');
-  }
-
-  void test_visitClassTypeAlias_withMetadata() {
-    _assertCloneUnitMember('@deprecated class C = S with M;');
-  }
-
-  void test_visitComment() {
-    _assertCloneUnitMember('main() { print(1);  /* comment */  print(2); }');
-  }
-
-  void test_visitComment_beginToken() {
-    _assertCloneUnitMember('/** comment */ main() {}');
-  }
-
-  void test_visitCommentReference() {
-    _assertCloneUnitMember('/** ref [a]. */ main(a) {}');
-  }
-
-  void test_visitCompilationUnit_declaration() {
-    _assertCloneUnitMember('var a;');
-  }
-
-  void test_visitCompilationUnit_directive() {
-    _assertCloneUnit('library l;');
-  }
-
-  void test_visitCompilationUnit_directive_declaration() {
-    _assertCloneUnit('library l;  var a;');
-  }
-
-  void test_visitCompilationUnit_directive_withComment() {
-    _assertCloneUnit(r'''
-/// aaa
-/// bbb
-library l;''');
-  }
-
-  void test_visitCompilationUnit_empty() {
-    _assertCloneUnit('');
-  }
-
-  void test_visitCompilationUnit_script() {
-    _assertCloneUnit('#!/bin/dartvm');
-  }
-
-  void test_visitCompilationUnit_script_declaration() {
-    _assertCloneUnit('#!/bin/dartvm \n var a;');
-  }
-
-  void test_visitCompilationUnit_script_directive() {
-    _assertCloneUnit('#!/bin/dartvm \n library l;');
-  }
-
-  void test_visitCompilationUnit_script_directives_declarations() {
-    _assertCloneUnit('#!/bin/dartvm \n library l;  var a;');
-  }
-
-  void test_visitConditionalExpression() {
-    _assertCloneExpression('a ? b : c');
-  }
-
-  void test_visitConstructorDeclaration_const() {
-    _assertCloneUnitMember('class C { const C(); }');
-  }
-
-  void test_visitConstructorDeclaration_external() {
-    _assertCloneUnitMember('class C { external C(); }');
-  }
-
-  void test_visitConstructorDeclaration_minimal() {
-    _assertCloneUnitMember('class C { C() {} }');
-  }
-
-  void test_visitConstructorDeclaration_multipleInitializers() {
-    _assertCloneUnitMember('class C { C() : a = b, c = d {} }');
-  }
-
-  void test_visitConstructorDeclaration_multipleParameters() {
-    _assertCloneUnitMember('class C { C(var a, var b) {} }');
-  }
-
-  void test_visitConstructorDeclaration_named() {
-    _assertCloneUnitMember('class C { C.m() {} }');
-  }
-
-  void test_visitConstructorDeclaration_singleInitializer() {
-    _assertCloneUnitMember('class C { C() : a = b {} }');
-  }
-
-  void test_visitConstructorDeclaration_withMetadata() {
-    _assertCloneUnitMember('class C { @deprecated C() {} }');
-  }
-
-  void test_visitConstructorFieldInitializer_withoutThis() {
-    _assertCloneUnitMember('class C { C() : a = b {} }');
-  }
-
-  void test_visitConstructorFieldInitializer_withThis() {
-    _assertCloneUnitMember('class C { C() : this.a = b {} }');
-  }
-
-  void test_visitConstructorName_named_prefix() {
-    _assertCloneExpression('new p.C.n()');
-  }
-
-  void test_visitConstructorName_unnamed_noPrefix() {
-    _assertCloneExpression('new C()');
-  }
-
-  void test_visitConstructorName_unnamed_prefix() {
-    _assertCloneExpression('new p.C()');
-  }
-
-  void test_visitContinueStatement_label() {
-    _assertCloneStatement('l: while (true) { continue l; }');
-  }
-
-  void test_visitContinueStatement_noLabel() {
-    _assertCloneStatement('while (true) { continue; }');
-  }
-
-  void test_visitDefaultFormalParameter_named_noValue() {
-    _assertCloneUnitMember('main({p}) {}');
-  }
-
-  void test_visitDefaultFormalParameter_named_value() {
-    _assertCloneUnitMember('main({p: 0}) {}');
-  }
-
-  void test_visitDefaultFormalParameter_positional_noValue() {
-    _assertCloneUnitMember('main([p]) {}');
-  }
-
-  void test_visitDefaultFormalParameter_positional_value() {
-    _assertCloneUnitMember('main([p = 0]) {}');
-  }
-
-  void test_visitDoStatement() {
-    _assertCloneStatement('do {} while (c);');
-  }
-
-  void test_visitDoubleLiteral() {
-    _assertCloneExpression('4.2');
-  }
-
-  void test_visitEmptyFunctionBody() {
-    _assertCloneUnitMember('main() {}');
-  }
-
-  void test_visitEmptyStatement() {
-    _assertCloneUnitMember('main() { ; }');
-  }
-
-  void test_visitExportDirective_combinator() {
-    _assertCloneUnit('export "a.dart" show A;');
-  }
-
-  void test_visitExportDirective_combinators() {
-    _assertCloneUnit('export "a.dart" show A hide B;');
-  }
-
-  void test_visitExportDirective_minimal() {
-    _assertCloneUnit('export "a.dart";');
-  }
-
-  void test_visitExportDirective_withMetadata() {
-    _assertCloneUnit('@deprecated export "a.dart";');
-  }
-
-  void test_visitExpressionFunctionBody() {
-    _assertCloneUnitMember('main() => a;');
-  }
-
-  void test_visitExpressionStatement() {
-    _assertCloneStatement('a;');
-  }
-
-  void test_visitExtendsClause() {
-    _assertCloneUnitMember('class A extends B {}');
-  }
-
-  void test_visitFieldDeclaration_instance() {
-    _assertCloneUnitMember('class C { var a; }');
-  }
-
-  void test_visitFieldDeclaration_static() {
-    _assertCloneUnitMember('class C { static var a; }');
-  }
-
-  void test_visitFieldDeclaration_withMetadata() {
-    _assertCloneUnitMember('class C { @deprecated var a; }');
-  }
-
-  void test_visitFieldFormalParameter_functionTyped() {
-    _assertCloneUnitMember('class C { C(A this.a(b)); }');
-  }
-
-  void test_visitFieldFormalParameter_keyword() {
-    _assertCloneUnitMember('class C { C(var this.a); }');
-  }
-
-  void test_visitFieldFormalParameter_keywordAndType() {
-    _assertCloneUnitMember('class C { C(final A this.a); }');
-  }
-
-  void test_visitFieldFormalParameter_type() {
-    _assertCloneUnitMember('class C { C(A this.a); }');
-  }
-
-  void test_visitForEachStatement_await() {
-    _assertCloneStatement('await for (var a in b) {}');
-  }
-
-  void test_visitForEachStatement_declared() {
-    _assertCloneStatement('for (var a in b) {}');
-  }
-
-  void test_visitForEachStatement_variable() {
-    _assertCloneStatement('for (a in b) {}');
-  }
-
-  void test_visitForEachStatement_variable_await() {
-    _assertCloneUnitMember('main(s) async { await for (a in s) {} }');
-  }
-
-  void test_visitFormalParameterList_empty() {
-    _assertCloneUnitMember('main() {}');
-  }
-
-  void test_visitFormalParameterList_n() {
-    _assertCloneUnitMember('main({a: 0}) {}');
-  }
-
-  void test_visitFormalParameterList_nn() {
-    _assertCloneUnitMember('main({a: 0, b: 1}) {}');
-  }
-
-  void test_visitFormalParameterList_p() {
-    _assertCloneUnitMember('main([a = 0]) {}');
-  }
-
-  void test_visitFormalParameterList_pp() {
-    _assertCloneUnitMember('main([a = 0, b = 1]) {}');
-  }
-
-  void test_visitFormalParameterList_r() {
-    _assertCloneUnitMember('main(a) {}');
-  }
-
-  void test_visitFormalParameterList_rn() {
-    _assertCloneUnitMember('main(a, {b: 1}) {}');
-  }
-
-  void test_visitFormalParameterList_rnn() {
-    _assertCloneUnitMember('main(a, {b: 1, c: 2}) {}');
-  }
-
-  void test_visitFormalParameterList_rp() {
-    _assertCloneUnitMember('main(a, [b = 1]) {}');
-  }
-
-  void test_visitFormalParameterList_rpp() {
-    _assertCloneUnitMember('main(a, [b = 1, c = 2]) {}');
-  }
-
-  void test_visitFormalParameterList_rr() {
-    _assertCloneUnitMember('main(a, b) {}');
-  }
-
-  void test_visitFormalParameterList_rrn() {
-    _assertCloneUnitMember('main(a, b, {c: 3}) {}');
-  }
-
-  void test_visitFormalParameterList_rrnn() {
-    _assertCloneUnitMember('main(a, b, {c: 3, d: 4}) {}');
-  }
-
-  void test_visitFormalParameterList_rrp() {
-    _assertCloneUnitMember('main(a, b, [c = 3]) {}');
-  }
-
-  void test_visitFormalParameterList_rrpp() {
-    _assertCloneUnitMember('main(a, b, [c = 3, d = 4]) {}');
-  }
-
-  void test_visitForStatement_c() {
-    _assertCloneStatement('for (; c;) {}');
-  }
-
-  void test_visitForStatement_cu() {
-    _assertCloneStatement('for (; c; u) {}');
-  }
-
-  void test_visitForStatement_e() {
-    _assertCloneStatement('for (e; ;) {}');
-  }
-
-  void test_visitForStatement_ec() {
-    _assertCloneStatement('for (e; c;) {}');
-  }
-
-  void test_visitForStatement_ecu() {
-    _assertCloneStatement('for (e; c; u) {}');
-  }
-
-  void test_visitForStatement_eu() {
-    _assertCloneStatement('for (e; ; u) {}');
-  }
-
-  void test_visitForStatement_i() {
-    _assertCloneStatement('for (var i; ;) {}');
-  }
-
-  void test_visitForStatement_ic() {
-    _assertCloneStatement('for (var i; c;) {}');
-  }
-
-  void test_visitForStatement_icu() {
-    _assertCloneStatement('for (var i; c; u) {}');
-  }
-
-  void test_visitForStatement_iu() {
-    _assertCloneStatement('for (var i; ; u) {}');
-  }
-
-  void test_visitForStatement_u() {
-    _assertCloneStatement('for (; ; u) {}');
-  }
-
-  void test_visitFunctionDeclaration_getter() {
-    _assertCloneUnitMember('get f {}');
-  }
-
-  void test_visitFunctionDeclaration_normal() {
-    _assertCloneUnitMember('f() {}');
-  }
-
-  void test_visitFunctionDeclaration_setter() {
-    _assertCloneUnitMember('set f(x) {}');
-  }
-
-  void test_visitFunctionDeclaration_withMetadata() {
-    _assertCloneUnitMember('@deprecated f() {}');
-  }
-
-  void test_visitFunctionDeclarationStatement() {
-    _assertCloneStatement('f() {}');
-  }
-
-  void test_visitFunctionExpressionInvocation() {
-    _assertCloneStatement('{ () {}(); }');
-  }
-
-  void test_visitFunctionTypeAlias_generic() {
-    _assertCloneUnitMember('typedef A F<B>();');
-  }
-
-  void test_visitFunctionTypeAlias_nonGeneric() {
-    _assertCloneUnitMember('typedef A F();');
-  }
-
-  void test_visitFunctionTypeAlias_withMetadata() {
-    _assertCloneUnitMember('@deprecated typedef A F();');
-  }
-
-  void test_visitFunctionTypedFormalParameter_noType() {
-    _assertCloneUnitMember('main( f() ) {}');
-  }
-
-  void test_visitFunctionTypedFormalParameter_type() {
-    _assertCloneUnitMember('main( T f() ) {}');
-  }
-
-  void test_visitIfStatement_withElse() {
-    _assertCloneStatement('if (c) {} else {}');
-  }
-
-  void test_visitIfStatement_withoutElse() {
-    _assertCloneStatement('if (c) {}');
-  }
-
-  void test_visitImplementsClause_multiple() {
-    _assertCloneUnitMember('class A implements B, C {}');
-  }
-
-  void test_visitImplementsClause_single() {
-    _assertCloneUnitMember('class A implements B {}');
-  }
-
-  void test_visitImportDirective_combinator() {
-    _assertCloneUnit('import "a.dart" show A;');
-  }
-
-  void test_visitImportDirective_combinators() {
-    _assertCloneUnit('import "a.dart" show A hide B;');
-  }
-
-  void test_visitImportDirective_minimal() {
-    _assertCloneUnit('import "a.dart";');
-  }
-
-  void test_visitImportDirective_prefix() {
-    _assertCloneUnit('import "a.dart" as p;');
-  }
-
-  void test_visitImportDirective_prefix_combinator() {
-    _assertCloneUnit('import "a.dart" as p show A;');
-  }
-
-  void test_visitImportDirective_prefix_combinators() {
-    _assertCloneUnit('import "a.dart" as p show A hide B;');
-  }
-
-  void test_visitImportDirective_withMetadata() {
-    _assertCloneUnit('@deprecated import "a.dart";');
-  }
-
-  void test_visitImportHideCombinator_multiple() {
-    _assertCloneUnit('import "a.dart" hide a, b;');
-  }
-
-  void test_visitImportHideCombinator_single() {
-    _assertCloneUnit('import "a.dart" hide a;');
-  }
-
-  void test_visitImportShowCombinator_multiple() {
-    _assertCloneUnit('import "a.dart" show a, b;');
-  }
-
-  void test_visitImportShowCombinator_single() {
-    _assertCloneUnit('import "a.dart" show a;');
-  }
-
-  void test_visitIndexExpression() {
-    _assertCloneExpression('a[i]');
-  }
-
-  void test_visitInstanceCreationExpression_const() {
-    _assertCloneExpression('const C()');
-  }
-
-  void test_visitInstanceCreationExpression_named() {
-    _assertCloneExpression('new C.c()');
-  }
-
-  void test_visitInstanceCreationExpression_unnamed() {
-    _assertCloneExpression('new C()');
-  }
-
-  void test_visitIntegerLiteral() {
-    _assertCloneExpression('42');
-  }
-
-  void test_visitInterpolationExpression_expression() {
-    _assertCloneExpression(r'"${c}"');
-  }
-
-  void test_visitInterpolationExpression_identifier() {
-    _assertCloneExpression(r'"$c"');
-  }
-
-  void test_visitIsExpression_negated() {
-    _assertCloneExpression('a is! C');
-  }
-
-  void test_visitIsExpression_normal() {
-    _assertCloneExpression('a is C');
-  }
-
-  void test_visitLabel() {
-    _assertCloneStatement('a: return;');
-  }
-
-  void test_visitLabeledStatement_multiple() {
-    _assertCloneStatement('a: b: return;');
-  }
-
-  void test_visitLabeledStatement_single() {
-    _assertCloneStatement('a: return;');
-  }
-
-  void test_visitLibraryDirective() {
-    _assertCloneUnit('library l;');
-  }
-
-  void test_visitLibraryDirective_withMetadata() {
-    _assertCloneUnit('@deprecated library l;');
-  }
-
-  void test_visitLibraryIdentifier_multiple() {
-    _assertCloneUnit('library a.b.c;');
-  }
-
-  void test_visitLibraryIdentifier_single() {
-    _assertCloneUnit('library a;');
-  }
-
-  void test_visitListLiteral_const() {
-    _assertCloneExpression('const []');
-  }
-
-  void test_visitListLiteral_empty() {
-    _assertCloneExpression('[]');
-  }
-
-  void test_visitListLiteral_nonEmpty() {
-    _assertCloneExpression('[a, b, c]');
-  }
-
-  void test_visitMapLiteral_const() {
-    _assertCloneExpression('const {}');
-  }
-
-  void test_visitMapLiteral_empty() {
-    _assertCloneExpression('{}');
-  }
-
-  void test_visitMapLiteral_nonEmpty() {
-    _assertCloneExpression('{a: a, b: b, c: c}');
-  }
-
-  void test_visitMethodDeclaration_external() {
-    _assertCloneUnitMember('class C { external m(); }');
-  }
-
-  void test_visitMethodDeclaration_external_returnType() {
-    _assertCloneUnitMember('class C { T m(); }');
-  }
-
-  void test_visitMethodDeclaration_getter() {
-    _assertCloneUnitMember('class C { get m {} }');
-  }
-
-  void test_visitMethodDeclaration_getter_returnType() {
-    _assertCloneUnitMember('class C { T get m {} }');
-  }
-
-  void test_visitMethodDeclaration_minimal() {
-    _assertCloneUnitMember('class C { m() {} }');
-  }
-
-  void test_visitMethodDeclaration_multipleParameters() {
-    _assertCloneUnitMember('class C { m(var a, var b) {} }');
-  }
-
-  void test_visitMethodDeclaration_operator() {
-    _assertCloneUnitMember('class C { operator+() {} }');
-  }
-
-  void test_visitMethodDeclaration_operator_returnType() {
-    _assertCloneUnitMember('class C { T operator+() {} }');
-  }
-
-  void test_visitMethodDeclaration_returnType() {
-    _assertCloneUnitMember('class C { T m() {} }');
-  }
-
-  void test_visitMethodDeclaration_setter() {
-    _assertCloneUnitMember('class C { set m(var v) {} }');
-  }
-
-  void test_visitMethodDeclaration_setter_returnType() {
-    _assertCloneUnitMember('class C { T set m(v) {} }');
-  }
-
-  void test_visitMethodDeclaration_static() {
-    _assertCloneUnitMember('class C { static m() {} }');
-  }
-
-  void test_visitMethodDeclaration_static_returnType() {
-    _assertCloneUnitMember('class C { static T m() {} }');
-  }
-
-  void test_visitMethodDeclaration_withMetadata() {
-    _assertCloneUnitMember('class C { @deprecated m() {} }');
-  }
-
-  void test_visitMethodInvocation_noTarget() {
-    _assertCloneExpression('m()');
-  }
-
-  void test_visitMethodInvocation_target() {
-    _assertCloneExpression('t.m()');
-  }
-
-  void test_visitNamedExpression() {
-    _assertCloneExpression('m(a: b)');
-  }
-
-  void test_visitNativeClause() {
-    _assertCloneUnitMember('f() native "code";');
-  }
-
-  void test_visitNativeFunctionBody() {
-    _assertCloneUnitMember('f() native "str";');
-  }
-
-  void test_visitNullLiteral() {
-    _assertCloneExpression('null');
-  }
-
-  void test_visitParenthesizedExpression() {
-    _assertCloneExpression('(a)');
-  }
-
-  void test_visitPartDirective() {
-    _assertCloneUnit('part "a.dart";');
-  }
-
-  void test_visitPartDirective_withMetadata() {
-    _assertCloneUnit('@deprecated part "a.dart";');
-  }
-
-  void test_visitPartOfDirective() {
-    _assertCloneUnit('part of l;');
-  }
-
-  void test_visitPartOfDirective_withMetadata() {
-    _assertCloneUnit('@deprecated part of l;');
-  }
-
-  void test_visitPositionalFormalParameter() {
-    _assertCloneUnitMember('main([var p = 0]) {}');
-  }
-
-  void test_visitPostfixExpression() {
-    _assertCloneExpression('a++');
-  }
-
-  void test_visitPrefixedIdentifier() {
-    _assertCloneExpression('a.b');
-  }
-
-  void test_visitPrefixExpression() {
-    _assertCloneExpression('-a');
-  }
-
-  void test_visitPropertyAccess() {
-    _assertCloneExpression('a.b.c');
-  }
-
-  void test_visitRedirectingConstructorInvocation_named() {
-    _assertCloneUnitMember('class A { factory A() = B.b; }');
-  }
-
-  void test_visitRedirectingConstructorInvocation_unnamed() {
-    _assertCloneUnitMember('class A { factory A() = B; }');
-  }
-
-  void test_visitRethrowExpression() {
-    _assertCloneStatement('rethrow;');
-  }
-
-  void test_visitReturnStatement_expression() {
-    _assertCloneStatement('return a;');
-  }
-
-  void test_visitReturnStatement_noExpression() {
-    _assertCloneStatement('return;');
-  }
-
-  void test_visitScriptTag() {
-    _assertCloneUnit('#!/bin/dart.exe');
-  }
-
-  void test_visitSimpleFormalParameter_keyword() {
-    _assertCloneUnitMember('main(var a) {}');
-  }
-
-  void test_visitSimpleFormalParameter_keyword_type() {
-    _assertCloneUnitMember('main(final A a) {}');
-  }
-
-  void test_visitSimpleFormalParameter_type() {
-    _assertCloneUnitMember('main(A a) {}');
-  }
-
-  void test_visitSimpleIdentifier() {
-    _assertCloneExpression('a');
-  }
-
-  void test_visitSimpleStringLiteral() {
-    _assertCloneExpression("'a'");
-  }
-
-  void test_visitStringInterpolation() {
-    _assertCloneExpression(r"'a${e}b'");
-  }
-
-  void test_visitSuperConstructorInvocation() {
-    _assertCloneUnitMember('class C { C() : super(); }');
-  }
-
-  void test_visitSuperConstructorInvocation_named() {
-    _assertCloneUnitMember('class C { C() : super.c(); }');
-  }
-
-  void test_visitSuperExpression() {
-    _assertCloneUnitMember('class C { m() { super.m(); } }');
-  }
-
-  void test_visitSwitchCase_multipleLabels() {
-    _assertCloneStatement('switch (v) {l1: l2: case a: {} }');
-  }
-
-  void test_visitSwitchCase_multipleStatements() {
-    _assertCloneStatement('switch (v) { case a: {} {} }');
-  }
-
-  void test_visitSwitchCase_noLabels() {
-    _assertCloneStatement('switch (v) { case a: {} }');
-  }
-
-  void test_visitSwitchCase_singleLabel() {
-    _assertCloneStatement('switch (v) { l1: case a: {} }');
-  }
-
-  void test_visitSwitchDefault_multipleLabels() {
-    _assertCloneStatement('switch (v) { l1: l2: default: {} }');
-  }
-
-  void test_visitSwitchDefault_multipleStatements() {
-    _assertCloneStatement('switch (v) { default: {} {} }');
-  }
-
-  void test_visitSwitchDefault_noLabels() {
-    _assertCloneStatement('switch (v) { default: {} }');
-  }
-
-  void test_visitSwitchDefault_singleLabel() {
-    _assertCloneStatement('switch (v) { l1: default: {} }');
-  }
-
-  void test_visitSwitchStatement() {
-    _assertCloneStatement('switch (a) { case b: {} default: {} }');
-  }
-
-  void test_visitSymbolLiteral_multiple() {
-    _assertCloneExpression('#a.b.c');
-  }
-
-  void test_visitSymbolLiteral_single() {
-    _assertCloneExpression('#a');
-  }
-
-  void test_visitThisExpression() {
-    _assertCloneExpression('this');
-  }
-
-  void test_visitThrowStatement() {
-    _assertCloneStatement('throw e;');
-  }
-
-  void test_visitTopLevelVariableDeclaration_multiple() {
-    _assertCloneUnitMember('var a;');
-  }
-
-  void test_visitTopLevelVariableDeclaration_single() {
-    _assertCloneUnitMember('var a, b;');
-  }
-
-  void test_visitTryStatement_catch() {
-    _assertCloneStatement('try {} on E {}');
-  }
-
-  void test_visitTryStatement_catches() {
-    _assertCloneStatement('try {} on E {} on F {}');
-  }
-
-  void test_visitTryStatement_catchFinally() {
-    _assertCloneStatement('try {} on E {} finally {}');
-  }
-
-  void test_visitTryStatement_finally() {
-    _assertCloneStatement('try {} finally {}');
-  }
-
-  void test_visitTypeName_multipleArgs() {
-    _assertCloneExpression('new C<D, E>()');
-  }
-
-  void test_visitTypeName_nestedArg() {
-    _assertCloneExpression('new C<D<E>>()');
-  }
-
-  void test_visitTypeName_noArgs() {
-    _assertCloneExpression('new C()');
-  }
-
-  void test_visitTypeName_singleArg() {
-    _assertCloneExpression('new C<D>()');
-  }
-
-  void test_visitTypeParameter_withExtends() {
-    _assertCloneUnitMember('class A<E extends C> {}');
-  }
-
-  void test_visitTypeParameter_withMetadata() {
-    _assertCloneUnitMember('class A<@deprecated E> {}');
-  }
-
-  void test_visitTypeParameter_withoutExtends() {
-    _assertCloneUnitMember('class A<E> {}');
-  }
-
-  void test_visitTypeParameterList_multiple() {
-    _assertCloneUnitMember('class A<E, F> {}');
-  }
-
-  void test_visitTypeParameterList_single() {
-    _assertCloneUnitMember('class A<E> {}');
-  }
-
-  void test_visitVariableDeclaration_initialized() {
-    _assertCloneStatement('var a = b;');
-  }
-
-  void test_visitVariableDeclaration_uninitialized() {
-    _assertCloneStatement('var a;');
-  }
-
-  void test_visitVariableDeclarationList_const_type() {
-    _assertCloneStatement('const C a, b;');
-  }
-
-  void test_visitVariableDeclarationList_final_noType() {
-    _assertCloneStatement('final a, b;');
-  }
-
-  void test_visitVariableDeclarationList_final_withMetadata() {
-    _assertCloneStatement('@deprecated final a, b;');
-  }
-
-  void test_visitVariableDeclarationList_type() {
-    _assertCloneStatement('C a, b;');
-  }
-
-  void test_visitVariableDeclarationList_var() {
-    _assertCloneStatement('var a, b;');
-  }
-
-  void test_visitVariableDeclarationStatement() {
-    _assertCloneStatement('C c;');
-  }
-
-  void test_visitWhileStatement() {
-    _assertCloneStatement('while (c) {}');
-  }
-
-  void test_visitWithClause_multiple() {
-    _assertCloneUnitMember('class X extends Y with A, B, C {}');
-  }
-
-  void test_visitWithClause_single() {
-    _assertCloneUnitMember('class X extends Y with A {}');
-  }
-
-  void test_visitYieldStatement() {
-    _assertCloneUnitMember('main() async* { yield 42; }');
-  }
-
-  /// Assert that an `AstCloner` will produce the expected AST structure when
-  /// visiting the given [node].
-  ///
-  /// @param node the AST node being visited to produce the cloned structure
-  /// @throws AFE if the visitor does not produce the expected source for the
-  ///           given node
-  void _assertClone(AstNode node) {
-    {
-      AstNode clone = node.accept(AstCloner())!;
-      AstCloneComparator comparator = AstCloneComparator(false);
-      if (!comparator.isEqualNodes(node, clone)) {
-        fail("Failed to clone ${node.runtimeType.toString()}");
-      }
-      _assertEqualTokens(clone, node);
-    }
-    {
-      AstNode clone = node.accept(AstCloner(true))!;
-      AstCloneComparator comparator = AstCloneComparator(true);
-      if (!comparator.isEqualNodes(node, clone)) {
-        fail("Failed to clone ${node.runtimeType.toString()}");
-      }
-      _assertEqualTokens(clone, node);
-    }
-  }
-
-  void _assertCloneExpression(String code) {
-    AstNode node = _parseExpression(code);
-    _assertClone(node);
-  }
-
-  void _assertCloneStatement(String code) {
-    AstNode node = _parseStatement(code);
-    _assertClone(node);
-  }
-
-  void _assertCloneUnit(String code) {
-    AstNode node = _parseUnit(code);
-    _assertClone(node);
-  }
-
-  void _assertCloneUnitMember(String code, {FeatureSet? featureSet}) {
-    AstNode node = _parseUnitMember(code, featureSet: featureSet);
-    _assertClone(node);
-  }
-
-  Expression _parseExpression(String code) {
-    CompilationUnit unit = _parseUnit('var v = $code;');
-    var decl = unit.declarations.single as TopLevelVariableDeclaration;
-    return decl.variables.variables.single.initializer!;
-  }
-
-  Statement _parseStatement(String code) {
-    CompilationUnit unit = _parseUnit('main() async { $code }');
-    var main = unit.declarations.single as FunctionDeclaration;
-    var body = main.functionExpression.body as BlockFunctionBody;
-    return body.block.statements.single;
-  }
-
-  CompilationUnit _parseUnit(String code, {FeatureSet? featureSet}) {
-    GatheringErrorListener listener = GatheringErrorListener();
-    CharSequenceReader reader = CharSequenceReader(code);
-    featureSet ??= FeatureSet.forTesting(sdkVersion: '2.2.2');
-    Scanner scanner = Scanner(TestSource(), reader, listener)
-      ..configureFeatures(
-        featureSetForOverriding: featureSet,
-        featureSet: featureSet,
-      );
-    Token token = scanner.tokenize();
-    Parser parser = Parser(
-      NonExistingSource.unknown,
-      listener,
-      featureSet: featureSet,
-    );
-    CompilationUnit unit = parser.parseCompilationUnit(token);
-    expect(unit, isNotNull);
-    listener.assertNoErrors();
-    return unit;
-  }
-
-  CompilationUnitMember _parseUnitMember(String code,
-      {FeatureSet? featureSet}) {
-    CompilationUnit unit = _parseUnit(code, featureSet: featureSet);
-    return unit.declarations.single;
-  }
-
-  static void _assertEqualToken(Token clone, Token original) {
-    expect(clone.type, original.type);
-    expect(clone.offset, original.offset);
-    expect(clone.length, original.length);
-    expect(clone.lexeme, original.lexeme);
-  }
-
-  static void _assertEqualTokens(AstNode cloneNode, AstNode originalNode) {
-    Token clone = cloneNode.beginToken;
-    Token original = originalNode.beginToken;
-    if (original is! CommentToken) {
-      _assertHasPrevious(original);
-      _assertHasPrevious(clone);
-    }
-    Token stopOriginalToken = originalNode.endToken.next!;
-    Token? skipCloneComment;
-    Token? skipOriginalComment;
-    while (original != stopOriginalToken) {
-      expect(clone, isNotNull);
-      _assertEqualToken(clone, original);
-      // comments
-      {
-        var cloneComment = clone.precedingComments;
-        var originalComment = original.precedingComments;
-        if (cloneComment != skipCloneComment &&
-            originalComment != skipOriginalComment) {
-          while (true) {
-            if (originalComment == null) {
-              expect(cloneComment, isNull);
-              break;
-            }
-            expect(cloneComment, isNotNull);
-            _assertEqualToken(cloneComment!, originalComment);
-            cloneComment = cloneComment.next as CommentToken?;
-            originalComment = originalComment.next as CommentToken?;
-          }
-        }
-      }
-      // next tokens
-      if (original is CommentToken) {
-        expect(clone, TypeMatcher<CommentToken>());
-        skipOriginalComment = original;
-        skipCloneComment = clone;
-        original = original.parent!;
-        clone = (clone as CommentToken).parent!;
-      } else {
-        clone = clone.next!;
-        original = original.next!;
-      }
-    }
-  }
-
-  /// Assert that the [token] has `previous` set, and if it `EOF`, then it
-  /// points itself.
-  static void _assertHasPrevious(Token? token) {
-    if (token == null) {
-      fail('Expected not null');
-    }
-    if (token.type == TokenType.EOF) {
-      return;
-    }
-    while (token != null) {
-      var previous = token.previous;
-      expect(previous, isNotNull);
-      if (token.type == TokenType.EOF) {
-        expect(previous, same(token));
-        break;
-      }
-      token = previous;
-    }
-  }
-}
-
-@reflectiveTest
 class BooleanArrayTest {
   void test_get_negative() {
     try {
@@ -3513,10 +2284,9 @@
   void _assertReplace(AstNode parent, NodeReplacerTest_Getter getter) {
     var child = getter.get(parent);
     if (child != null) {
-      AstNode clone = child.accept(AstCloner())!;
-      NodeReplacer.replace(child, clone);
-      expect(getter.get(parent), clone);
-      expect(clone.parent, child.parent);
+      NodeReplacer.replace(child, child);
+      expect(getter.get(parent), child);
+      expect(child.parent, child.parent);
     }
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b617776..62bdd51 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -7612,9 +7612,6 @@
     _assertArgumentToParameter(arguments[2], fElement.parameters[2]);
   }
 
-  @FailingTest(
-    reason: 'No nameOffset for formal parameters',
-  )
   test_top_functionTypeAlias() async {
     String content = r'''
 typedef int F<T>(bool a, T b);
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index 0ab7d85..031eb7e 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -146,6 +146,7 @@
 }
 ''', [
       error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 26, 8),
     ]);
 
     assertFunctionExpressionInvocation(
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index 4b2098e..1fc2927 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -879,6 +879,45 @@
     ]);
   }
 
+  test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
+    await assertErrorsInCode(r'''
+class A {
+  Never get f => throw 0;
+}
+void g(A a) {
+  a.f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
+      error(HintCode.DEAD_CODE, 57, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  (f)(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
+      error(HintCode.DEAD_CODE, 23, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 21, 16),
+    ]);
+  }
+
   test_returnTypeNever_function() async {
     await assertErrorsInCode(r'''
 Never foo() => throw 0;
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 933f6f9..c64b592 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -114,6 +114,7 @@
 }
 ''', [
       error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 21, 3),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 1071a07..86ffd26 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -2627,7 +2627,7 @@
         aliasedType: dynamic Function(C<dynamic Function()>)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional value @-1
+            requiredPositional value @36
               type: C<dynamic Function()>
           returnType: dynamic
 ''');
@@ -2909,14 +2909,14 @@
         aliasedType: dynamic Function(dynamic Function())
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional value @-1
+            requiredPositional value @36
               type: dynamic Function()
           returnType: dynamic
       functionTypeAliasBased notSimplyBounded G @52
         aliasedType: dynamic Function(dynamic Function())
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional value @-1
+            requiredPositional value @56
               type: dynamic Function()
           returnType: dynamic
 ''');
@@ -6516,7 +6516,7 @@
                   staticInvokeType: int Function()
                   staticType: int
                 staticElement: dart:core::@class::num::@method::+
-                staticInvokeType: null
+                staticInvokeType: num Function(num)
                 staticType: int
         constructors
           synthetic @-1
@@ -6593,7 +6593,7 @@
               staticInvokeType: int Function()
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
     accessors
       synthetic static get v @-1
@@ -6632,7 +6632,7 @@
               literal: 5 @36
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
     accessors
       synthetic static get a @-1
@@ -8722,7 +8722,7 @@
                       literal: 2 @44
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
         accessors
           synthetic get x @-1
@@ -8760,7 +8760,7 @@
                       literal: 2 @45
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
         accessors
           synthetic get x @-1
@@ -8801,7 +8801,7 @@
                       literal: 2 @40
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
           const named @55
             periodOffset: 54
@@ -8819,7 +8819,7 @@
                       literal: 2 @69
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
         methods
           methodPositional @81
@@ -8836,7 +8836,7 @@
                       literal: 2 @107
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
             returnType: void
           methodPositionalWithoutDefault @121
@@ -8858,7 +8858,7 @@
                       literal: 2 @187
                       staticType: int
                     staticElement: dart:core::@class::num::@method::+
-                    staticInvokeType: null
+                    staticInvokeType: num Function(num)
                     staticType: int
             returnType: void
           methodNamedWithoutDefault @201
@@ -9489,7 +9489,7 @@
               literal: 2 @27
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
     accessors
       synthetic static get A @-1
@@ -9526,7 +9526,7 @@
               literal: 2 @31
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
     accessors
       synthetic static get B @-1
@@ -9569,7 +9569,7 @@
               literal: 2 @38
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
     accessors
       synthetic static get B @-1
@@ -9636,9 +9636,9 @@
         aliasedType: dynamic Function(int, String)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @56
               type: int
-            requiredPositional b @-1
+            requiredPositional b @66
               type: String
           returnType: dynamic
     topLevelVariables
@@ -10210,7 +10210,7 @@
               literal: 2 @20
               staticType: int
             staticElement: dart:core::@class::num::@method::==
-            staticInvokeType: null
+            staticInvokeType: bool Function(Object)
             staticType: bool
       static const vAnd @29
         type: bool
@@ -10252,7 +10252,7 @@
               literal: 2 @98
               staticType: int
             staticElement: dart:core::@class::int::@method::^
-            staticInvokeType: null
+            staticInvokeType: int Function(int)
             staticType: int
       static const vBitAnd @107
         type: int
@@ -10266,7 +10266,7 @@
               literal: 2 @121
               staticType: int
             staticElement: dart:core::@class::int::@method::&
-            staticInvokeType: null
+            staticInvokeType: int Function(int)
             staticType: int
       static const vBitOr @130
         type: int
@@ -10280,7 +10280,7 @@
               literal: 2 @143
               staticType: int
             staticElement: dart:core::@class::int::@method::|
-            staticInvokeType: null
+            staticInvokeType: int Function(int)
             staticType: int
       static const vBitShiftLeft @152
         type: int
@@ -10294,7 +10294,7 @@
               literal: 2 @173
               staticType: int
             staticElement: dart:core::@class::int::@method::<<
-            staticInvokeType: null
+            staticInvokeType: int Function(int)
             staticType: int
       static const vBitShiftRight @182
         type: int
@@ -10308,7 +10308,7 @@
               literal: 2 @204
               staticType: int
             staticElement: dart:core::@class::int::@method::>>
-            staticInvokeType: null
+            staticInvokeType: int Function(int)
             staticType: int
       static const vAdd @213
         type: int
@@ -10322,7 +10322,7 @@
               literal: 2 @224
               staticType: int
             staticElement: dart:core::@class::num::@method::+
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
       static const vSubtract @233
         type: int
@@ -10336,7 +10336,7 @@
               literal: 2 @249
               staticType: int
             staticElement: dart:core::@class::num::@method::-
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
       static const vMiltiply @258
         type: int
@@ -10350,7 +10350,7 @@
               literal: 2 @274
               staticType: int
             staticElement: dart:core::@class::num::@method::*
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
       static const vDivide @283
         type: double
@@ -10364,7 +10364,7 @@
               literal: 2 @297
               staticType: int
             staticElement: dart:core::@class::num::@method::/
-            staticInvokeType: null
+            staticInvokeType: double Function(num)
             staticType: double
       static const vFloorDivide @306
         type: int
@@ -10378,7 +10378,7 @@
               literal: 2 @326
               staticType: int
             staticElement: dart:core::@class::num::@method::~/
-            staticInvokeType: null
+            staticInvokeType: int Function(num)
             staticType: int
       static const vModulo @335
         type: int
@@ -10392,7 +10392,7 @@
               literal: 2 @349
               staticType: int
             staticElement: dart:core::@class::num::@method::%
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
       static const vGreater @358
         type: bool
@@ -10406,7 +10406,7 @@
               literal: 2 @373
               staticType: int
             staticElement: dart:core::@class::num::@method::>
-            staticInvokeType: null
+            staticInvokeType: bool Function(num)
             staticType: bool
       static const vGreaterEqual @382
         type: bool
@@ -10420,7 +10420,7 @@
               literal: 2 @403
               staticType: int
             staticElement: dart:core::@class::num::@method::>=
-            staticInvokeType: null
+            staticInvokeType: bool Function(num)
             staticType: bool
       static const vLess @412
         type: bool
@@ -10434,7 +10434,7 @@
               literal: 2 @424
               staticType: int
             staticElement: dart:core::@class::num::@method::<
-            staticInvokeType: null
+            staticInvokeType: bool Function(num)
             staticType: bool
       static const vLessEqual @433
         type: bool
@@ -10448,7 +10448,7 @@
               literal: 2 @451
               staticType: int
             staticElement: dart:core::@class::num::@method::<=
-            staticInvokeType: null
+            staticInvokeType: bool Function(num)
             staticType: bool
     accessors
       synthetic static get vEqual @-1
@@ -10513,7 +10513,7 @@
                   literal: 2 @27
                   staticType: int
                 staticElement: dart:core::@class::num::@method::==
-                staticInvokeType: null
+                staticInvokeType: bool Function(Object)
                 staticType: bool
               leftParenthesis: ( @21
               rightParenthesis: ) @28
@@ -10555,7 +10555,7 @@
                   literal: 2 @25
                   staticType: int
                 staticElement: dart:core::@class::num::@method::==
-                staticInvokeType: null
+                staticInvokeType: bool Function(Object)
                 staticType: bool
               leftParenthesis: ( @19
               rightParenthesis: ) @26
@@ -10627,7 +10627,7 @@
         constantInitializer
           NullLiteral
             literal: null @14
-            staticType: null
+            staticType: Null
       static const vBoolFalse @26
         type: bool
         constantInitializer
@@ -10831,7 +10831,7 @@
                   literal: 2 @20
                   staticType: int
                 staticElement: dart:core::@class::num::@method::+
-                staticInvokeType: null
+                staticInvokeType: num Function(num)
                 staticType: int
               leftParenthesis: ( @15
               rightParenthesis: ) @21
@@ -10841,7 +10841,7 @@
               literal: 3 @25
               staticType: int
             staticElement: dart:core::@class::num::@method::*
-            staticInvokeType: null
+            staticInvokeType: num Function(num)
             staticType: int
       static const v2 @38
         type: int
@@ -10857,7 +10857,7 @@
                   literal: 2 @49
                   staticType: int
                 staticElement: dart:core::@class::num::@method::+
-                staticInvokeType: null
+                staticInvokeType: num Function(num)
                 staticType: int
               leftParenthesis: ( @44
               rightParenthesis: ) @50
@@ -10883,7 +10883,7 @@
                 rightOperand: SimpleStringLiteral
                   literal: 'bbb' @77
                 staticElement: dart:core::@class::String::@method::+
-                staticInvokeType: null
+                staticInvokeType: String Function(String)
                 staticType: String
               leftParenthesis: ( @68
               rightParenthesis: ) @82
@@ -10921,7 +10921,7 @@
               literal: 2 @23
               staticType: int
             staticElement: dart:core::@class::num::@method::==
-            staticInvokeType: null
+            staticInvokeType: bool Function(Object)
             staticType: bool
       static const vNot @32
         type: bool
@@ -11336,7 +11336,7 @@
         aliasedType: int Function(String)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional id @-1
+            requiredPositional id @21
               type: String
           returnType: int
     topLevelVariables
@@ -11806,7 +11806,7 @@
             constantInitializer
               NullLiteral
                 literal: null @51
-                staticType: null
+                staticType: Null
         constructors
           synthetic @-1
         accessors
@@ -11896,7 +11896,7 @@
                     literal: 42 @41
                     staticType: int
                   staticElement: dart:core::@class::num::@method::>=
-                  staticInvokeType: null
+                  staticInvokeType: bool Function(num)
                   staticType: bool
                 leftParenthesis: ( @35
                 rightParenthesis: ) @43
@@ -11932,7 +11932,7 @@
                     literal: 42 @41
                     staticType: int
                   staticElement: dart:core::@class::num::@method::>=
-                  staticInvokeType: null
+                  staticInvokeType: bool Function(num)
                   staticType: bool
                 leftParenthesis: ( @35
                 message: SimpleStringLiteral
@@ -12093,7 +12093,7 @@
                     staticType: int
                     token: p @48
                   staticElement: dart:core::@class::num::@method::+
-                  staticInvokeType: null
+                  staticInvokeType: num Function(num)
                   staticType: int
                 fieldName: SimpleIdentifier
                   staticElement: self::@class::C::@field::x
@@ -12160,7 +12160,7 @@
                                   parameters
                                   returnType: dynamic
                                   type: dynamic Function()
-                                functionKeyword: Function @0
+                                functionKeyword: Function @86
                                 parameters: FormalParameterList
                                 type: dynamic Function()
                             leftBracket: < @85
@@ -12668,6 +12668,10 @@
           covariant U @96
             defaultType: dynamic
         supertype: C<U, T>
+          aliasElement: self::@typeAlias::A
+          aliasArguments
+            U
+            T
         constructors
           named @121
             periodOffset: 120
@@ -13621,7 +13625,7 @@
         aliasedType: void Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional v @-1
+            requiredPositional v @20
               type: T
           returnType: void
     functions
@@ -13684,7 +13688,7 @@
                                 parameters
                                 returnType: dynamic
                                 type: dynamic Function()
-                              functionKeyword: Function @0
+                              functionKeyword: Function @61
                               parameters: FormalParameterList
                               type: dynamic Function()
                           leftBracket: < @60
@@ -14521,16 +14525,16 @@
         aliasedType: void Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @37
               type: int
           returnType: void
       functionTypeAliasBased F @54
         aliasedType: void Function([int, double])
         aliasedElement: GenericFunctionTypeElement
           parameters
-            optionalPositional b @-1
+            optionalPositional b @61
               type: int
-            optionalPositional c @-1
+            optionalPositional c @71
               type: double
           returnType: void
 ''');
@@ -14969,7 +14973,7 @@
         aliasedType: dynamic Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional p @-1
+            requiredPositional p @14
               type: int
           returnType: dynamic
     functions
@@ -15663,14 +15667,14 @@
                                 type: double
                             returnType: int
                             type: int Function(double)
-                          functionKeyword: Function @0
+                          functionKeyword: Function @62
                           parameters: FormalParameterList
                             parameters
                               SimpleFormalParameter
-                                declaredElement: a@-1
+                                declaredElement: a@78
                                 declaredElementType: double
                                 identifier: SimpleIdentifier
-                                  staticElement: <null>
+                                  staticElement: a@78
                                   staticType: null
                                   token: a @78
                                 type: TypeName
@@ -16668,7 +16672,7 @@
         aliasedType: void Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @20
               type: T
           returnType: void
 ''');
@@ -16690,7 +16694,7 @@
         aliasedType: void Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @21
               type: T
           returnType: void
       functionTypeAliasBased F2 @39
@@ -16732,7 +16736,7 @@
         aliasedType: void Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @44
               type: T
           returnType: void
 ''');
@@ -16819,7 +16823,7 @@
         aliasedType: void Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @21
               type: T
           returnType: void
       functionTypeAliasBased F2 @38
@@ -16829,7 +16833,7 @@
         aliasedType: void Function(void Function(T))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @50
               type: void Function(T)
                 aliasElement: self::@typeAlias::F1
                 aliasArguments
@@ -16853,7 +16857,7 @@
         aliasedType: T Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @17
               type: T
           returnType: T
 ''');
@@ -16882,7 +16886,7 @@
         aliasedType: T Function() Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @41
               type: T
           returnType: T Function()
             aliasElement: self::@typeAlias::F1
@@ -16906,7 +16910,7 @@
         aliasedType: void Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @22
               type: int
           returnType: void
 ''');
@@ -17152,7 +17156,7 @@
         aliasedType: void Function(String) Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional b @-1
+            requiredPositional b @49
               type: int
           returnType: void Function(String)
 ''');
@@ -17257,14 +17261,14 @@
                         type: String
                     returnType: int
                     type: int Function(String)
-                  functionKeyword: Function @0
+                  functionKeyword: Function @36
                   parameters: FormalParameterList
                     parameters
                       SimpleFormalParameter
-                        declaredElement: a@-1
+                        declaredElement: a@52
                         declaredElementType: String
                         identifier: SimpleIdentifier
-                          staticElement: <null>
+                          staticElement: a@52
                           staticType: null
                           token: a @52
                         type: TypeName
@@ -17331,14 +17335,14 @@
                         type: String
                     returnType: int
                     type: int Function(String)
-                  functionKeyword: Function @0
+                  functionKeyword: Function @36
                   parameters: FormalParameterList
                     parameters
                       SimpleFormalParameter
-                        declaredElement: a@-1
+                        declaredElement: a@52
                         declaredElementType: String
                         identifier: SimpleIdentifier
-                          staticElement: <null>
+                          staticElement: a@52
                           staticType: null
                           token: a @52
                         type: TypeName
@@ -17414,21 +17418,21 @@
                             type: int?
                         returnType: String
                         type: String Function({int? a})
-                      functionKeyword: Function @0
+                      functionKeyword: Function @48
                       parameters: FormalParameterList
                         parameters
                           DefaultFormalParameter
-                            declaredElement: a@-1
+                            declaredElement: a@63
                             declaredElementType: int?
                             identifier: SimpleIdentifier
-                              staticElement: <null>
+                              staticElement: a@63
                               staticType: null
                               token: a @63
                             parameter: SimpleFormalParameter
-                              declaredElement: a@-1
+                              declaredElement: a@63
                               declaredElementType: int?
                               identifier: SimpleIdentifier
-                                staticElement: <null>
+                                staticElement: a@63
                                 staticType: null
                                 token: a @63
                               type: TypeName
@@ -17499,21 +17503,21 @@
                             type: int?
                         returnType: String
                         type: String Function([int?])
-                      functionKeyword: Function @0
+                      functionKeyword: Function @48
                       parameters: FormalParameterList
                         parameters
                           DefaultFormalParameter
-                            declaredElement: a@-1
+                            declaredElement: a@63
                             declaredElementType: int?
                             identifier: SimpleIdentifier
-                              staticElement: <null>
+                              staticElement: a@63
                               staticType: null
                               token: a @63
                             parameter: SimpleFormalParameter
-                              declaredElement: a@-1
+                              declaredElement: a@63
                               declaredElementType: int?
                               identifier: SimpleIdentifier
-                                staticElement: <null>
+                                staticElement: a@63
                                 staticType: null
                                 token: a @63
                               type: TypeName
@@ -17584,21 +17588,21 @@
                             type: int
                         returnType: String
                         type: String Function({required int a})
-                      functionKeyword: Function @0
+                      functionKeyword: Function @48
                       parameters: FormalParameterList
                         parameters
                           DefaultFormalParameter
-                            declaredElement: a@-1
+                            declaredElement: a@71
                             declaredElementType: int
                             identifier: SimpleIdentifier
-                              staticElement: <null>
+                              staticElement: a@71
                               staticType: null
                               token: a @71
                             parameter: SimpleFormalParameter
-                              declaredElement: a@-1
+                              declaredElement: a@71
                               declaredElementType: int
                               identifier: SimpleIdentifier
-                                staticElement: <null>
+                                staticElement: a@71
                                 staticType: null
                                 token: a @71
                               requiredKeyword: required @0
@@ -17670,14 +17674,14 @@
                             type: int
                         returnType: String
                         type: String Function(int)
-                      functionKeyword: Function @0
+                      functionKeyword: Function @48
                       parameters: FormalParameterList
                         parameters
                           SimpleFormalParameter
-                            declaredElement: a@-1
+                            declaredElement: a@61
                             declaredElementType: int
                             identifier: SimpleIdentifier
-                              staticElement: <null>
+                              staticElement: a@61
                               staticType: null
                               token: a @61
                             type: TypeName
@@ -17773,7 +17777,7 @@
         aliasedType: dynamic Function<V1>(V1 Function())
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant V1 @-1
+            covariant V1 @22
           parameters
             requiredPositional @-1
               type: V1 Function()
@@ -18571,7 +18575,7 @@
         aliasedType: D<T, U> Function<U>()
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant U @-1
+            covariant U @31
           returnType: D<T, U>
     topLevelVariables
       static const x @118
@@ -18641,7 +18645,7 @@
         aliasedType: D<T> Function<T>()
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant T @-1
+            covariant T @26
           returnType: D<T>
     topLevelVariables
       static const x @101
@@ -19200,7 +19204,7 @@
         aliasedType: int Function(String)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional s @-1
+            requiredPositional s @21
               type: String
           returnType: int
 ''');
@@ -19368,10 +19372,10 @@
         aliasedType: void Function(int Function(String))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional g @-1
+            requiredPositional g @19
               type: int Function(String)
               parameters
-                requiredPositional s @-1
+                requiredPositional s @28
                   type: String
           returnType: void
     topLevelVariables
@@ -20440,7 +20444,7 @@
         aliasedType: dynamic Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional p @-1
+            requiredPositional p @27
               type: T
           returnType: dynamic
     topLevelVariables
@@ -20523,9 +20527,9 @@
         aliasedType: S Function<S>(T)
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant S @-1
+            covariant S @38
           parameters
-            requiredPositional p @-1
+            requiredPositional p @43
               type: T
           returnType: S
     topLevelVariables
@@ -21486,13 +21490,13 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static const b @22
         type: dynamic
         constantInitializer
           NullLiteral
             literal: null @26
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -21541,7 +21545,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22382,7 +22386,7 @@
               arguments
                 NullLiteral
                   literal: null @27
-                  staticType: null
+                  staticType: Null
               leftParenthesis: ( @26
               rightParenthesis: ) @31
             atSign.offset: 24
@@ -22422,7 +22426,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22452,7 +22456,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22668,7 +22672,7 @@
         constantInitializer
           NullLiteral
             literal: null @32
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22785,7 +22789,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22826,7 +22830,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22876,7 +22880,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22910,7 +22914,7 @@
                 constantInitializer
                   NullLiteral
                     literal: null @48
-                    staticType: null
+                    staticType: Null
         accessors
           synthetic get x @-1
             returnType: dynamic
@@ -22925,7 +22929,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22947,7 +22951,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -22976,7 +22980,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       synthetic static f @-1
         type: dynamic
     accessors
@@ -23006,7 +23010,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       synthetic static f @-1
         type: dynamic
     accessors
@@ -23052,7 +23056,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23070,7 +23074,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23102,7 +23106,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23163,13 +23167,13 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static const b @22
         type: dynamic
         constantInitializer
           NullLiteral
             literal: null @26
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23274,7 +23278,7 @@
         aliasedType: void Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional first @-1
+            requiredPositional first @47
               type: int
               metadata
                 Annotation
@@ -23311,10 +23315,10 @@
         aliasedType: void Function(int Function(int))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional foo @-1
+            requiredPositional foo @44
               type: int Function(int)
               parameters
-                requiredPositional bar @-1
+                requiredPositional bar @55
                   type: int
                   metadata
                     Annotation
@@ -23351,7 +23355,7 @@
         aliasedType: void Function<T>(int)
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant T @-1
+            covariant T @43
               metadata
                 Annotation
                   atSign.offset: 40
@@ -23361,7 +23365,7 @@
                     staticType: null
                     token: a @41
           parameters
-            requiredPositional first @-1
+            requiredPositional first @50
               type: int
           returnType: void
     topLevelVariables
@@ -23431,7 +23435,7 @@
         constantInitializer
           NullLiteral
             literal: null @24
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23468,7 +23472,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23516,13 +23520,13 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static const b @22
         type: dynamic
         constantInitializer
           NullLiteral
             literal: null @26
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23574,13 +23578,13 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static const b @22
         type: dynamic
         constantInitializer
           NullLiteral
             literal: null @26
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23627,7 +23631,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -23744,13 +23748,13 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static const b @22
         type: dynamic
         constantInitializer
           NullLiteral
             literal: null @26
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -24408,7 +24412,7 @@
         aliasedType: void Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @53
               type: int
               metadata
                 Annotation
@@ -24466,7 +24470,7 @@
         aliasedType: void Function<U>(int)
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant U @-1
+            covariant U @60
               metadata
                 Annotation
                   atSign.offset: 55
@@ -24476,7 +24480,7 @@
                     staticType: null
                     token: foo @56
           parameters
-            requiredPositional a @-1
+            requiredPositional a @72
               type: int
               metadata
                 Annotation
@@ -24776,7 +24780,7 @@
         constantInitializer
           NullLiteral
             literal: null @41
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -24852,7 +24856,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -24908,7 +24912,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -24930,7 +24934,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       synthetic static foo @-1
         type: int
     accessors
@@ -24963,7 +24967,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -24983,7 +24987,7 @@
             constantInitializer
               NullLiteral
                 literal: null @26
-                staticType: null
+                staticType: Null
         returnType: dynamic
 ''');
   }
@@ -24999,7 +25003,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
       static v @23
         metadata
           Annotation
@@ -25049,7 +25053,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -25102,7 +25106,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -25120,7 +25124,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -25167,7 +25171,7 @@
         constantInitializer
           NullLiteral
             literal: null @10
-            staticType: null
+            staticType: Null
     accessors
       synthetic static get a @-1
         returnType: dynamic
@@ -28832,7 +28836,7 @@
         aliasedType: dynamic Function(dynamic)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional p @-1
+            requiredPositional p @38
               type: dynamic
           returnType: dynamic
     topLevelVariables
@@ -29988,7 +29992,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @20
               type: T
           returnType: U
     topLevelVariables
@@ -30032,7 +30036,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @20
               type: T
           returnType: U
     topLevelVariables
@@ -30114,13 +30118,13 @@
         aliasedType: void Function(T Function<T, U>(U))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional a @-1
+            requiredPositional a @17
               type: T Function<T, U>(U)
               typeParameters
-                covariant T @-1
-                covariant U @-1
+                covariant T @19
+                covariant U @22
               parameters
-                requiredPositional u @-1
+                requiredPositional u @27
                   type: U
           returnType: void
 ''');
@@ -30524,9 +30528,9 @@
         aliasedType: int Function<S>(List<S>, num Function<A>(A), T)
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant S @-1
+            covariant S @28
           parameters
-            requiredPositional list @-1
+            requiredPositional list @39
               type: List<S>
             requiredPositional @-1
               type: num Function<A>(A)
@@ -30578,9 +30582,9 @@
         aliasedType: S Function<T>(T)
         aliasedElement: GenericFunctionTypeElement
           typeParameters
-            covariant T @-1
+            covariant T @28
           parameters
-            requiredPositional x @-1
+            requiredPositional x @33
               type: T
           returnType: S
 ''');
@@ -30804,6 +30808,9 @@
       class B @49
         interfaces
           A<int, String>
+            aliasElement: self::@typeAlias::X
+            aliasArguments
+              String
         constructors
           synthetic @-1
     typeAliases
@@ -30884,6 +30891,9 @@
         interfaces
           B
           A<int?>
+            aliasElement: self::@typeAlias::X
+            aliasArguments
+              int
           C
         constructors
           synthetic @-1
@@ -31021,6 +31031,7 @@
         supertype: Object
         mixins
           A<int>
+            aliasElement: self::@typeAlias::X
         constructors
           synthetic @-1
     typeAliases
@@ -31096,6 +31107,7 @@
         mixins
           M1
           A<int?>
+            aliasElement: self::@typeAlias::X
           M2
         constructors
           synthetic @-1
@@ -31154,6 +31166,7 @@
           synthetic @-1
       class B @40
         supertype: A<int>
+          aliasElement: self::@typeAlias::X
         constructors
           synthetic @-1
     typeAliases
@@ -31181,6 +31194,9 @@
           synthetic @-1
       class B @38
         supertype: A<int>
+          aliasElement: self::@typeAlias::X
+          aliasArguments
+            A<int>
         constructors
           synthetic @-1
     typeAliases
@@ -31256,6 +31272,7 @@
           synthetic @-1
       class D @41
         supertype: A<int?>
+          aliasElement: self::@typeAlias::X
         constructors
           synthetic @-1
     typeAliases
@@ -31596,7 +31613,7 @@
         aliasedType: void Function(C<C<dynamic>>)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional c @-1
+            requiredPositional c @28
               type: C<C<dynamic>>
           returnType: void
 ''');
@@ -31654,7 +31671,7 @@
         aliasedType: void Function(C<C<dynamic>>)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional c @-1
+            requiredPositional c @17
               type: C<C<dynamic>>
           returnType: void
 ''');
@@ -31735,12 +31752,12 @@
         aliasedType: dynamic Function(dynamic Function(dynamic, dynamic))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional g @-1
+            requiredPositional g @10
               type: dynamic Function(dynamic, dynamic)
               parameters
-                requiredPositional x @-1
+                requiredPositional x @12
                   type: dynamic
-                requiredPositional y @-1
+                requiredPositional y @15
                   type: dynamic
           returnType: dynamic
 ''');
@@ -31761,10 +31778,10 @@
         aliasedType: dynamic Function(A Function(B))
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional g @-1
+            requiredPositional g @18
               type: A Function(B)
               parameters
-                requiredPositional x @-1
+                requiredPositional x @22
                   type: B
           returnType: dynamic
 ''');
@@ -31780,7 +31797,7 @@
         aliasedType: dynamic Function(int Function())
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional g @-1
+            requiredPositional g @14
               type: int Function()
           returnType: dynamic
 ''');
@@ -31796,7 +31813,7 @@
         aliasedType: dynamic Function(int)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional i @-1
+            requiredPositional i @14
               type: int
           returnType: dynamic
 ''');
@@ -31815,7 +31832,7 @@
         aliasedType: dynamic Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @15
               type: T
           returnType: dynamic
 ''');
@@ -31831,9 +31848,9 @@
         aliasedType: dynamic Function(dynamic, dynamic)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional x @-1
+            requiredPositional x @10
               type: dynamic
-            requiredPositional y @-1
+            requiredPositional y @13
               type: dynamic
           returnType: dynamic
 ''');
@@ -31849,11 +31866,11 @@
         aliasedType: dynamic Function({dynamic x, dynamic y, dynamic z})
         aliasedElement: GenericFunctionTypeElement
           parameters
-            optionalNamed y @-1
+            optionalNamed y @11
               type: dynamic
-            optionalNamed z @-1
+            optionalNamed z @14
               type: dynamic
-            optionalNamed x @-1
+            optionalNamed x @17
               type: dynamic
           returnType: dynamic
 ''');
@@ -31929,7 +31946,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @20
               type: T
           returnType: U
 ''');
@@ -31957,7 +31974,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @45
               type: T
           returnType: U
 ''');
@@ -32015,7 +32032,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @36
               type: T
           returnType: U
 ''');
@@ -32038,7 +32055,7 @@
         aliasedType: U* Function(T*)*
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @36
               type: T*
           returnType: U*
 ''');
@@ -32060,7 +32077,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @30
               type: T
           returnType: U
 ''');
@@ -32083,7 +32100,7 @@
         aliasedType: U* Function(T*)*
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @30
               type: T*
           returnType: U*
 ''');
@@ -32106,7 +32123,7 @@
         aliasedType: U Function(T)
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @41
               type: T
           returnType: U
 ''');
@@ -32130,7 +32147,7 @@
         aliasedType: U* Function(T*)*
         aliasedElement: GenericFunctionTypeElement
           parameters
-            requiredPositional t @-1
+            requiredPositional t @41
               type: T*
           returnType: U*
 ''');
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index 2ba9ae1..5954673 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -50,6 +50,7 @@
   ffi::DoublePointer,
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
+  ffi::FfiNative,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
@@ -119,6 +120,7 @@
   ffi::DoublePointer,
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
+  ffi::FfiNative,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index b09ca73..c390f66 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -50,6 +50,7 @@
   ffi::DoublePointer,
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
+  ffi::FfiNative,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
@@ -119,6 +120,7 @@
   ffi::DoublePointer,
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
+  ffi::FfiNative,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 5d93861..547e14a 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -24,6 +24,8 @@
 import '../transformations/ffi.dart' as ffiHelper show importsFfi;
 import '../transformations/ffi_definitions.dart' as transformFfiDefinitions
     show transformLibraries;
+import '../transformations/ffi_native.dart' as transformFfiNative
+    show transformLibraries;
 import '../transformations/ffi_use_sites.dart' as transformFfiUseSites
     show transformLibraries;
 
@@ -157,6 +159,10 @@
     if (!ffiHelper.importsFfi(component, libraries)) {
       logger?.call("Skipped ffi transformation");
     } else {
+      // Transform @FfiNative(..) functions into ffi native call functions.
+      transformFfiNative.transformLibraries(
+          component, libraries, referenceFromIndex);
+      logger?.call("Transformed ffi natives");
       // TODO(jensj/dacoharkes): We can probably limit the transformations to
       // libraries that transitivley depend on dart:ffi.
       transformFfiDefinitions.transformLibraries(
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
new file mode 100644
index 0000000..3d67aae
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.12
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/library_index.dart' show LibraryIndex;
+import 'package:kernel/reference_from_index.dart'
+    show IndexedLibrary, ReferenceFromIndex;
+
+/// Transform @FfiNative annotated functions into FFI native function pointer
+/// functions.
+void transformLibraries(Component component, List<Library> libraries,
+    ReferenceFromIndex referenceFromIndex) {
+  final index = LibraryIndex(component, ['dart:ffi']);
+  // Skip if dart:ffi isn't loaded (e.g. during incremental compile).
+  if (index.tryGetClass('dart:ffi', 'FfiNative') == null) {
+    return;
+  }
+  final transformer = FfiNativeTransformer(index, referenceFromIndex);
+  libraries.forEach(transformer.visitLibrary);
+}
+
+class FfiNativeTransformer extends Transformer {
+  Library? currentLibrary;
+  IndexedLibrary? currentLibraryIndex;
+
+  final ReferenceFromIndex? referenceFromIndex;
+  final Class ffiNativeClass;
+  final Class nativeFunctionClass;
+  final Field ffiNativeNameField;
+  final Field resolverField;
+  final Procedure asFunctionProcedure;
+  final Procedure fromAddressInternal;
+
+  FfiNativeTransformer(LibraryIndex index, this.referenceFromIndex)
+      : ffiNativeClass = index.getClass('dart:ffi', 'FfiNative'),
+        nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
+        ffiNativeNameField =
+            index.getField('dart:ffi', 'FfiNative', 'nativeName'),
+        resolverField = index.getTopLevelField('dart:ffi', '_ffi_resolver'),
+        asFunctionProcedure = index.getProcedure(
+            'dart:ffi', 'NativeFunctionPointer', 'asFunction'),
+        fromAddressInternal =
+            index.getTopLevelProcedure('dart:ffi', '_fromAddress') {}
+
+  @override
+  TreeNode visitLibrary(Library node) {
+    assert(currentLibrary == null);
+    currentLibrary = node;
+    currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
+    // We only transform top-level, external procedures:
+    transformList(node.procedures, node);
+    currentLibrary = null;
+    return node;
+  }
+
+  InstanceConstant? _tryGetFfiNativeAnnotation(Member node) {
+    for (final Expression annotation in node.annotations) {
+      if (annotation is ConstantExpression) {
+        if (annotation.constant is InstanceConstant) {
+          final instConst = annotation.constant as InstanceConstant;
+          if (instConst.classNode == ffiNativeClass) {
+            return instConst;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  // Transform:
+  //   @FfiNative<Double Function(Double)>('Math_sqrt')
+  //   external double _sqrt(double x);
+  //
+  // Into:
+  //   final _@FfiNative_Math_sqrt =
+  //       Pointer<NativeFunction<Double Function(Double)>>
+  //           .fromAddress(_ffi_resolver('dart:math', 'Math_sqrt'))
+  //           .asFunction<double Function(double)>();
+  //   double _sqrt(double x) => _@FfiNative_Math_sqrt(x);
+  Statement transformFfiNative(
+      Procedure node, InstanceConstant annotationConst) {
+    assert(currentLibrary != null);
+    final params = node.function.positionalParameters;
+    final functionName = annotationConst
+        .fieldValues[ffiNativeNameField.getterReference] as StringConstant;
+
+    // double Function(double)
+    final DartType dartType =
+        node.function.computeThisFunctionType(Nullability.nonNullable);
+    // Double Function(Double)
+    final nativeType = annotationConst.typeArguments[0];
+    // InterfaceType(NativeFunction<Double Function(Double)>*)
+    final DartType nativeInterfaceType =
+        InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeType]);
+
+    // TODO(dartbug.com/31579): Add `..fileOffset`s once we can handle these in
+    // patch files.
+
+    // _ffi_resolver('dart:math', 'Math_sqrt')
+    final resolverInvocation = MethodInvocation(
+        StaticGet(resolverField),
+        Name('call'),
+        Arguments([
+          ConstantExpression(
+              StringConstant(currentLibrary!.importUri.toString())),
+          ConstantExpression(functionName)
+        ]));
+
+    // _fromAddress<NativeFunction<Double Function(Double)>>(...)
+    final fromAddressInvocation = StaticInvocation(fromAddressInternal,
+        Arguments([resolverInvocation], types: [nativeInterfaceType]));
+
+    // NativeFunctionPointer.asFunction
+    //     <Double Function(Double), double Function(double)>(...)
+    final asFunctionInvocation = StaticInvocation(asFunctionProcedure,
+        Arguments([fromAddressInvocation], types: [nativeType, dartType]));
+
+    // final _@FfiNative_Math_sqrt = ...
+    final fieldName = Name('_@FfiNative_${functionName.value}', currentLibrary);
+    final funcPtrField = Field.immutable(fieldName,
+        type: dartType,
+        initializer: asFunctionInvocation,
+        isStatic: true,
+        isFinal: true,
+        fileUri: currentLibrary!.fileUri,
+        getterReference: currentLibraryIndex?.lookupGetterReference(fieldName));
+    currentLibrary!.addField(funcPtrField);
+
+    // _@FfiNative_Math_sqrt(x)
+    final callFuncPtrInvocation = MethodInvocation(StaticGet(funcPtrField),
+        Name('call'), Arguments(params.map((p) => VariableGet(p)).toList()));
+
+    return ReturnStatement(callFuncPtrInvocation);
+  }
+
+  @override
+  visitProcedure(Procedure node) {
+    // Only transform functions that are external and have FfiNative annotation:
+    //   @FfiNative<Double Function(Double)>('Math_sqrt')
+    //   external double _sqrt(double x);
+    if (!node.isExternal) {
+      return node;
+    }
+    InstanceConstant? ffiNativeAnnotation = _tryGetFfiNativeAnnotation(node);
+    if (ffiNativeAnnotation == null) {
+      return node;
+    }
+
+    node.isExternal = false;
+    node.function.body = transformFfiNative(node, ffiNativeAnnotation)
+      ..parent = node.function;
+
+    return node;
+  }
+}
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 3da8be8..8b3db04 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -89,7 +89,7 @@
 static SnapshotKind snapshot_kind = kCore;
 
 // The ordering of this list must match the SnapshotKind enum above.
-static const char* kSnapshotKindNames[] = {
+static const char* const kSnapshotKindNames[] = {
     // clang-format off
     "core",
     "core-jit",
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index ed0c781..83503b5 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -192,7 +192,7 @@
 
 IO_NATIVE_LIST(DECLARE_FUNCTION);
 
-static struct NativeEntries {
+static const struct NativeEntries {
   const char* name_;
   Dart_NativeFunction function_;
   int argument_count_;
@@ -209,7 +209,7 @@
   *auto_setup_scope = true;
   int num_entries = sizeof(IOEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
-    struct NativeEntries* entry = &(IOEntries[i]);
+    const struct NativeEntries* entry = &(IOEntries[i]);
     if ((strcmp(function_name, entry->name_) == 0) &&
         (entry->argument_count_ == argument_count)) {
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
@@ -221,7 +221,7 @@
 const uint8_t* IONativeSymbol(Dart_NativeFunction nf) {
   int num_entries = sizeof(IOEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
-    struct NativeEntries* entry = &(IOEntries[i]);
+    const struct NativeEntries* entry = &(IOEntries[i]);
     if (reinterpret_cast<Dart_NativeFunction>(entry->function_) == nf) {
       return reinterpret_cast<const uint8_t*>(entry->name_);
     }
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index dd82f2d..faf1d5c 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -28,7 +28,7 @@
 namespace bin {
 
 // These strings must match the enum SnapshotKind in main_options.h.
-static const char* kSnapshotKindNames[] = {
+static const char* const kSnapshotKindNames[] = {
     "none",
     "kernel",
     "app-jit",
@@ -36,7 +36,7 @@
 };
 
 // These strings must match the enum VerbosityLevel in main_options.h.
-static const char* kVerbosityLevelNames[] = {
+static const char* const kVerbosityLevelNames[] = {
     "error", "warning", "info", "all", nullptr,
 };
 
diff --git a/runtime/bin/options.h b/runtime/bin/options.h
index bb5f5ee..32e185e 100644
--- a/runtime/bin/options.h
+++ b/runtime/bin/options.h
@@ -84,7 +84,7 @@
 
 #define DEFINE_ENUM_OPTION(name, enum_name, variable)                          \
   DEFINE_STRING_OPTION_CB(name, {                                              \
-    const char** kNames = k##enum_name##Names;                                 \
+    const char* const* kNames = k##enum_name##Names;                           \
     for (intptr_t i = 0; kNames[i] != NULL; i++) {                             \
       if (strcmp(value, kNames[i]) == 0) {                                     \
         variable = static_cast<enum_name>(i);                                  \
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 3fce5e6..d8db597 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3041,6 +3041,13 @@
  */
 typedef const uint8_t* (*Dart_NativeEntrySymbol)(Dart_NativeFunction nf);
 
+/**
+ * FFI Native C function pointer resolver callback.
+ *
+ * See Dart_SetFfiNativeResolver.
+ */
+typedef void* (*Dart_FfiNativeResolver)(const char* name);
+
 /*
  * ===========
  * Environment
@@ -3103,6 +3110,22 @@
 DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library,
                                              Dart_NativeEntrySymbol* resolver);
 
+/**
+ * Sets the callback used to resolve FFI native functions for a library.
+ * The resolved functions are expected to be a C function pointer of the
+ * correct signature (as specified in the `@FfiNative<NFT>()` function
+ * annotation in Dart code).
+ *
+ * NOTE: This is an experimental feature and might change in the future.
+ *
+ * \param library A library.
+ * \param resolver A native function resolver.
+ *
+ * \return A valid handle if the native resolver was set successfully.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetFfiNativeResolver(Dart_Handle library, Dart_FfiNativeResolver resolver);
+
 /*
  * =====================
  * Scripts and Libraries
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index f9217ed..cc4a6ff 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -11,6 +11,8 @@
 #include "vm/bootstrap_natives.h"
 #include "vm/class_finalizer.h"
 #include "vm/class_id.h"
+#include "vm/compiler/ffi/native_type.h"
+#include "vm/dart_api_impl.h"
 #include "vm/exceptions.h"
 #include "vm/flags.h"
 #include "vm/log.h"
@@ -273,4 +275,41 @@
   return Integer::New(reinterpret_cast<intptr_t>(&dart_api_data));
 }
 
+// FFI native C function pointer resolver.
+static intptr_t FfiResolve(Dart_Handle lib_url, Dart_Handle name) {
+  DARTSCOPE(Thread::Current());
+
+  const String& lib_url_str = Api::UnwrapStringHandle(T->zone(), lib_url);
+  const String& function_name = Api::UnwrapStringHandle(T->zone(), name);
+
+  // Find the corresponding library's native function resolver (if set).
+  const Library& lib = Library::Handle(Library::LookupLibrary(T, lib_url_str));
+  if (lib.IsNull()) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Unknown library: '%s'.", lib_url_str.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+  auto resolver = lib.ffi_native_resolver();
+  if (resolver == nullptr) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Library has no handler: '%s'.", lib_url_str.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+
+  auto* f = resolver(function_name.ToCString());
+  if (f == nullptr) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Couldn't resolve function: '%s'.", function_name.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+
+  return reinterpret_cast<intptr_t>(f);
+}
+
+// Bootstrap to get the FFI Native resolver through a `native` call.
+DEFINE_NATIVE_ENTRY(Ffi_GetFfiNativeResolver, 1, 0) {
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  return Pointer::New(type_arg, reinterpret_cast<intptr_t>(FfiResolve));
+}
+
 }  // namespace dart
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 5d9d84b..91b4f6f 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -21,7 +21,7 @@
 // List all native functions implemented in the vm or core bootstrap dart
 // libraries so that we can resolve the native function to it's entry
 // point.
-static struct NativeEntries {
+static const struct NativeEntries {
   const char* name_;
   BootstrapNativeFunction function_;
   int argument_count_;
@@ -46,7 +46,7 @@
   ASSERT(function_name != NULL);
   int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
-    struct NativeEntries* entry = &(BootStrapEntries[i]);
+    const struct NativeEntries* entry = &(BootStrapEntries[i]);
     if ((strcmp(function_name, entry->name_) == 0) &&
         (entry->argument_count_ == argument_count)) {
       return reinterpret_cast<Dart_NativeFunction>(entry->function_);
@@ -58,7 +58,7 @@
 const uint8_t* BootstrapNatives::Symbol(Dart_NativeFunction nf) {
   int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
   for (int i = 0; i < num_entries; i++) {
-    struct NativeEntries* entry = &(BootStrapEntries[i]);
+    const struct NativeEntries* entry = &(BootStrapEntries[i]);
     if (reinterpret_cast<Dart_NativeFunction>(entry->function_) == nf) {
       return reinterpret_cast<const uint8_t*>(entry->name_);
     }
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 373dffb..7eb3452 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -404,6 +404,7 @@
   V(Ffi_asExternalTypedData, 2)                                                \
   V(Ffi_dl_processLibrary, 0)                                                  \
   V(Ffi_dl_executableLibrary, 0)                                               \
+  V(Ffi_GetFfiNativeResolver, 0)                                               \
   V(DartApiDLInitializeData, 0)                                                \
   V(DartApiDLMajorVersion, 0)                                                  \
   V(DartApiDLMinorVersion, 0)                                                  \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index fd75159..0cec1c2 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -133,15 +133,6 @@
 
 #endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
-static ObjectPtr AllocateUninitialized(PageSpace* old_space, intptr_t size) {
-  ASSERT(Utils::IsAligned(size, kObjectAlignment));
-  uword address = old_space->TryAllocateDataBumpLocked(size);
-  if (address == 0) {
-    OUT_OF_MEMORY();
-  }
-  return UntaggedObject::FromAddr(address);
-}
-
 void Deserializer::InitializeHeader(ObjectPtr raw,
                                     intptr_t class_id,
                                     intptr_t size,
@@ -194,7 +185,21 @@
   }
   size_ += (stop - start);
 }
+#endif  // !DART_PRECOMPILED_RUNTIME
 
+DART_NOINLINE
+void DeserializationCluster::ReadAllocFixedSize(Deserializer* d,
+                                                intptr_t instance_size) {
+  start_index_ = d->next_index();
+  PageSpace* old_space = d->heap()->old_space();
+  intptr_t count = d->ReadUnsigned();
+  for (intptr_t i = 0; i < count; i++) {
+    d->AssignRef(old_space->AllocateSnapshot(instance_size));
+  }
+  stop_index_ = d->next_index();
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 static UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(
     Serializer* s,
     intptr_t class_id) {
@@ -362,7 +367,7 @@
     start_index_ = d->next_index();
     count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Class::InstanceSize()));
+      d->AssignRef(old_space->AllocateSnapshot(Class::InstanceSize()));
     }
     stop_index_ = d->next_index();
   }
@@ -674,7 +679,7 @@
                                                     intptr_t count) {
     const intptr_t instance_size = Array::InstanceSize(length);
     ArrayPtr table = static_cast<ArrayPtr>(
-        AllocateUninitialized(d->heap()->old_space(), instance_size));
+        d->heap()->old_space()->AllocateSnapshot(instance_size));
     Deserializer::InitializeHeader(table, kArrayCid, instance_size);
     table->untag()->type_arguments_ = TypeArguments::null();
     table->untag()->length_ = Smi::New(length);
@@ -732,14 +737,7 @@
   ~TypeParametersDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, TypeParameters::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, TypeParameters::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -832,8 +830,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         TypeArguments::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(TypeArguments::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
     BuildCanonicalSetFromLayout(d);
@@ -921,14 +919,7 @@
   ~PatchClassDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, PatchClass::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, PatchClass::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1033,13 +1024,7 @@
   ~FunctionDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Function::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Function::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1193,14 +1178,7 @@
   ~ClosureDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, ClosureData::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, ClosureData::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1275,14 +1253,7 @@
   ~FfiTrampolineDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, FfiTrampolineData::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, FfiTrampolineData::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1396,13 +1367,7 @@
   ~FieldDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Field::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Field::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1539,13 +1504,7 @@
   ~ScriptDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Script::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Script::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1615,13 +1574,7 @@
   ~LibraryDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Library::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Library::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1690,13 +1643,7 @@
   ~NamespaceDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Namespace::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Namespace::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -1759,14 +1706,7 @@
   ~KernelProgramInfoDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, KernelProgramInfo::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, KernelProgramInfo::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -2172,7 +2112,7 @@
       d->AssignRef(StubCode::UnknownDartCode().ptr());
     } else {
       auto code = static_cast<CodePtr>(
-          AllocateUninitialized(old_space, Code::InstanceSize(0)));
+          old_space->AllocateSnapshot(Code::InstanceSize(0)));
       d->AssignRef(code);
       code->untag()->state_bits_ = state_bits;
     }
@@ -2381,7 +2321,7 @@
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
-          AllocateUninitialized(old_space, ObjectPool::InstanceSize(length)));
+          old_space->AllocateSnapshot(ObjectPool::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -2563,8 +2503,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         PcDescriptors::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(PcDescriptors::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -2638,8 +2578,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         CodeSourceMap::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(CodeSourceMap::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -2715,8 +2655,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(
-          old_space, CompressedStackMaps::InstanceSize(length)));
+      d->AssignRef(old_space->AllocateSnapshot(
+          CompressedStackMaps::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -2924,8 +2864,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(
-          old_space, ExceptionHandlers::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(ExceptionHandlers::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -3014,8 +2954,7 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(
-          AllocateUninitialized(old_space, Context::InstanceSize(length)));
+      d->AssignRef(old_space->AllocateSnapshot(Context::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -3095,7 +3034,7 @@
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
-          AllocateUninitialized(old_space, ContextScope::InstanceSize(length)));
+          old_space->AllocateSnapshot(ContextScope::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -3160,14 +3099,7 @@
   ~UnlinkedCallDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, UnlinkedCall::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, UnlinkedCall::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3231,13 +3163,7 @@
   ~ICDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, ICData::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, ICData::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3299,14 +3225,7 @@
   ~MegamorphicCacheDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, MegamorphicCache::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, MegamorphicCache::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3386,14 +3305,7 @@
   ~SubtypeTestCacheDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, SubtypeTestCache::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, SubtypeTestCache::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3452,14 +3364,7 @@
   ~LoadingUnitDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, LoadingUnit::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, LoadingUnit::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3525,14 +3430,7 @@
   ~LanguageErrorDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, LanguageError::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, LanguageError::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3595,14 +3493,7 @@
   ~UnhandledExceptionDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, UnhandledException::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, UnhandledException::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3720,6 +3611,7 @@
       : DeserializationCluster(name, is_canonical) {}
 
  public:
+#if defined(DART_PRECOMPILED_RUNTIME)
   void PostLoad(Deserializer* d, const Array& refs, bool primary) {
     if (!primary && is_canonical()) {
       SafepointMutexLocker ml(
@@ -3732,6 +3624,7 @@
       }
     }
   }
+#endif
 };
 
 class InstanceDeserializationCluster
@@ -3751,7 +3644,7 @@
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
     for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, instance_size));
+      d->AssignRef(old_space->AllocateSnapshot(instance_size));
     }
     stop_index_ = d->next_index();
   }
@@ -3843,14 +3736,7 @@
   ~LibraryPrefixDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, LibraryPrefix::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, LibraryPrefix::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -3973,14 +3859,7 @@
   ~TypeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      ObjectPtr object = AllocateUninitialized(old_space, Type::InstanceSize());
-      d->AssignRef(object);
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Type::InstanceSize());
     BuildCanonicalSetFromLayout(d);
   }
 
@@ -4103,15 +3982,7 @@
   ~FunctionTypeDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      ObjectPtr object =
-          AllocateUninitialized(old_space, FunctionType::InstanceSize());
-      d->AssignRef(object);
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, FunctionType::InstanceSize());
     BuildCanonicalSetFromLayout(d);
   }
 
@@ -4206,13 +4077,7 @@
   ~TypeRefDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, TypeRef::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, TypeRef::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -4325,14 +4190,7 @@
   ~TypeParameterDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, TypeParameter::InstanceSize());
     BuildCanonicalSetFromLayout(d);
   }
 
@@ -4432,13 +4290,7 @@
   ~ClosureDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Closure::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Closure::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -4454,8 +4306,8 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool primary) {
 #if defined(DART_PRECOMPILED_RUNTIME)
+  void PostLoad(Deserializer* d, const Array& refs, bool primary) {
     // We only cache the entry point in bare instructions mode (as we need
     // to load the function anyway otherwise).
     if (d->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions) {
@@ -4469,8 +4321,8 @@
         closure.ptr()->untag()->entry_point_ = entry_point;
       }
     }
-#endif
   }
+#endif
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4539,7 +4391,7 @@
         d->AssignRef(Smi::New(value));
       } else {
         MintPtr mint = static_cast<MintPtr>(
-            AllocateUninitialized(old_space, Mint::InstanceSize()));
+            old_space->AllocateSnapshot(Mint::InstanceSize()));
         Deserializer::InitializeHeader(mint, kMintCid, Mint::InstanceSize(),
                                        is_canonical());
         mint->untag()->value_ = value;
@@ -4551,6 +4403,7 @@
 
   void ReadFill(Deserializer* d, bool primary) {}
 
+#if defined(DART_PRECOMPILED_RUNTIME)
   void PostLoad(Deserializer* d, const Array& refs, bool primary) {
     if (!primary && is_canonical()) {
       const Class& mint_cls = Class::Handle(
@@ -4573,6 +4426,7 @@
       }
     }
   }
+#endif
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4620,13 +4474,7 @@
   ~DoubleDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Double::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, Double::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -4638,6 +4486,7 @@
     }
   }
 
+#if defined(DART_PRECOMPILED_RUNTIME)
   void PostLoad(Deserializer* d, const Array& refs, bool primary) {
     if (!primary && is_canonical()) {
       auto Z = d->zone();
@@ -4659,6 +4508,7 @@
       }
     }
   }
+#endif
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4708,14 +4558,7 @@
   ~GrowableObjectArrayDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         GrowableObjectArray::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, GrowableObjectArray::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -4787,8 +4630,8 @@
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(
-          old_space, TypedData::InstanceSize(length * element_size)));
+      d->AssignRef(old_space->AllocateSnapshot(
+          TypedData::InstanceSize(length * element_size)));
     }
     stop_index_ = d->next_index();
   }
@@ -4860,14 +4703,7 @@
   ~TypedDataViewDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, TypedDataView::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, TypedDataView::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -4942,14 +4778,7 @@
   ~ExternalTypedDataDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, ExternalTypedData::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, ExternalTypedData::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -5017,14 +4846,7 @@
   ~StackTraceDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, StackTrace::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, StackTrace::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -5085,13 +4907,7 @@
   ~RegExpDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, RegExp::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, RegExp::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -5168,14 +4984,7 @@
   ~WeakPropertyDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, WeakProperty::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, WeakProperty::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -5268,14 +5077,7 @@
   ~LinkedHashMapDeserializationCluster() {}
 
   void ReadAlloc(Deserializer* d) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, LinkedHashMap::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
+    ReadAllocFixedSize(d, LinkedHashMap::InstanceSize());
   }
 
   void ReadFill(Deserializer* d, bool primary) {
@@ -5298,7 +5100,7 @@
           static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
 
       ArrayPtr data = static_cast<ArrayPtr>(
-          AllocateUninitialized(old_space, Array::InstanceSize(data_size)));
+          old_space->AllocateSnapshot(Array::InstanceSize(data_size)));
       data->untag()->type_arguments_ = TypeArguments::null();
       data->untag()->length_ = Smi::New(data_size);
       intptr_t i;
@@ -5382,8 +5184,7 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(
-          AllocateUninitialized(old_space, Array::InstanceSize(length)));
+      d->AssignRef(old_space->AllocateSnapshot(Array::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -5459,6 +5260,7 @@
       : DeserializationCluster(name, is_canonical) {}
 
  public:
+#if defined(DART_PRECOMPILED_RUNTIME)
   void PostLoad(Deserializer* d, const Array& refs, bool primary) {
     if (!primary && is_canonical()) {
       auto Z = d->zone();
@@ -5480,6 +5282,7 @@
       isolate_group->object_store()->set_symbol_table(table.Release());
     }
   }
+#endif
 };
 
 class OneByteStringDeserializationCluster
@@ -5495,8 +5298,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         OneByteString::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(OneByteString::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -5580,8 +5383,8 @@
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       const intptr_t length = d->ReadUnsigned();
-      d->AssignRef(AllocateUninitialized(old_space,
-                                         TwoByteString::InstanceSize(length)));
+      d->AssignRef(
+          old_space->AllocateSnapshot(TwoByteString::InstanceSize(length)));
     }
     stop_index_ = d->next_index();
   }
@@ -5838,7 +5641,7 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-static const char* kObjectStoreFieldNames[] = {
+static const char* const kObjectStoreFieldNames[] = {
 #define DECLARE_OBJECT_STORE_FIELD(Type, Name) #Name,
     OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
                             DECLARE_OBJECT_STORE_FIELD,
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index be649ed..26411ce 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -161,6 +161,8 @@
   bool is_canonical() const { return is_canonical_; }
 
  protected:
+  void ReadAllocFixedSize(Deserializer* deserializer, intptr_t instance_size);
+
   const char* const name_;
   const bool is_canonical_;
   // The range of the ref array that belongs to this cluster.
@@ -382,6 +384,11 @@
   void WriteFromTo(T obj, P&&... args) {
     auto* from = obj->untag()->from();
     auto* to = obj->untag()->to_snapshot(kind(), args...);
+    WriteRange(obj, from, to);
+  }
+
+  template <typename T>
+  DART_NOINLINE void WriteRange(ObjectPtr obj, T from, T to) {
     for (auto* p = from; p <= to; p++) {
       WriteOffsetRef(
           p->Decompress(obj->heap_base()),
@@ -393,6 +400,11 @@
   void PushFromTo(T obj, P&&... args) {
     auto* from = obj->untag()->from();
     auto* to = obj->untag()->to_snapshot(kind(), args...);
+    PushRange(obj, from, to);
+  }
+
+  template <typename T>
+  DART_NOINLINE void PushRange(ObjectPtr obj, T from, T to) {
     for (auto* p = from; p <= to; p++) {
       Push(p->Decompress(obj->heap_base()));
     }
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 16ce521..77021e4 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -209,7 +209,7 @@
 
 static InstructionTable instruction_table;
 
-static InstructionDesc cmov_instructions[16] = {
+static const InstructionDesc cmov_instructions[16] = {
     {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
     {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
     {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false},
@@ -641,8 +641,8 @@
   uint8_t modrm = *(data + 1);
   int mod, regop, rm;
   get_modrm(modrm, &mod, &regop, &rm);
-  static const char* mnemonics[] = {"test", NULL,   "not", "neg",
-                                    "mul",  "imul", "div", "idiv"};
+  static const char* const mnemonics[] = {"test", NULL,   "not", "neg",
+                                          "mul",  "imul", "div", "idiv"};
   const char* mnem = mnemonics[regop];
   if (mod == 3 && regop != 0) {
     if (regop > 3) {
@@ -1529,8 +1529,8 @@
     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
   } else if (0x10 <= opcode && opcode <= 0x16) {
     // ...ps xmm, xmm/m128
-    static const char* mnemonics[] = {"movups",   NULL,       "movhlps", NULL,
-                                      "unpcklps", "unpckhps", "movlhps"};
+    static const char* const mnemonics[] = {
+        "movups", NULL, "movhlps", NULL, "unpcklps", "unpckhps", "movlhps"};
     const char* mnemonic = mnemonics[opcode - 0x10];
     if (mnemonic == NULL) {
       UnimplementedInstruction();
@@ -1613,7 +1613,7 @@
     return xmm_instructions[opcode & 0xF].ps_name;
   }
   if (0xA2 <= opcode && opcode <= 0xBF) {
-    static const char* mnemonics[] = {
+    static const char* const mnemonics[] = {
         "cpuid", "bt",   "shld",    "shld",    NULL,     NULL,
         NULL,    NULL,   NULL,      "bts",     "shrd",   "shrd",
         NULL,    "imul", "cmpxchg", "cmpxchg", NULL,     NULL,
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index b954bee..1bfffd0 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -787,7 +787,7 @@
   value()->PrintTo(f);
 }
 
-static const char* simd_op_kind_string[] = {
+static const char* const simd_op_kind_string[] = {
 #define CASE(Arity, Mask, Name, ...) #Name,
     SIMD_OP_LIST(CASE, CASE)
 #undef CASE
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index a1a0973..bce561c 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -157,37 +157,37 @@
 
 struct LibraryInstrinsicsDesc {
   Library& library;
-  IntrinsicDesc* intrinsics;
+  const IntrinsicDesc* intrinsics;
 };
 
 #define DEFINE_INTRINSIC(class_name, function_name, destination, fp)           \
   {#class_name, #function_name},
 
 // clang-format off
-static IntrinsicDesc core_intrinsics[] = {
+static const IntrinsicDesc core_intrinsics[] = {
   CORE_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   CORE_INTEGER_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   GRAPH_CORE_INTRINSICS_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
 
-static IntrinsicDesc math_intrinsics[] = {
+static const IntrinsicDesc math_intrinsics[] = {
   MATH_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   GRAPH_MATH_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
 
-static IntrinsicDesc typed_data_intrinsics[] = {
+static const IntrinsicDesc typed_data_intrinsics[] = {
   GRAPH_TYPED_DATA_INTRINSICS_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
 
-static IntrinsicDesc developer_intrinsics[] = {
+static const IntrinsicDesc developer_intrinsics[] = {
   DEVELOPER_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
 
-static IntrinsicDesc internal_intrinsics[] = {
+static const IntrinsicDesc internal_intrinsics[] = {
   INTERNAL_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
@@ -204,7 +204,7 @@
   Error& error = Error::Handle(zone);
 
   static const intptr_t kNumLibs = 5;
-  LibraryInstrinsicsDesc intrinsics[kNumLibs] = {
+  const LibraryInstrinsicsDesc intrinsics[kNumLibs] = {
       {Library::Handle(zone, Library::CoreLibrary()), core_intrinsics},
       {Library::Handle(zone, Library::MathLibrary()), math_intrinsics},
       {Library::Handle(zone, Library::TypedDataLibrary()),
@@ -216,7 +216,7 @@
 
   for (intptr_t i = 0; i < kNumLibs; i++) {
     lib = intrinsics[i].library.ptr();
-    for (IntrinsicDesc* intrinsic = intrinsics[i].intrinsics;
+    for (const IntrinsicDesc* intrinsic = intrinsics[i].intrinsics;
          intrinsic->class_name != nullptr; intrinsic++) {
       func = Function::null();
       if (strcmp(intrinsic->class_name, "::") == 0) {
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 873f9e0..0c5a85a 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -356,7 +356,7 @@
 #define RECOGNIZE_FACTORY(symbol, class_name, constructor_name, cid, fp)       \
   {Symbols::k##symbol##Id, cid, fp, #symbol ", " #cid},  // NOLINT
 
-static struct {
+static const struct {
   const intptr_t symbol_id;
   const intptr_t cid;
   const uint32_t finger_print;
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index e3d2c5d..8465181 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -509,7 +509,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     60;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
-static constexpr dart::compiler::target::word Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -1055,7 +1055,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     120;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
-static constexpr dart::compiler::target::word Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -1591,7 +1591,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     60;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
-static constexpr dart::compiler::target::word Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -2138,7 +2138,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     120;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
-static constexpr dart::compiler::target::word Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -2683,7 +2683,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     64;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 32;
-static constexpr dart::compiler::target::word Library_InstanceSize = 104;
+static constexpr dart::compiler::target::word Library_InstanceSize = 112;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 24;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -3229,7 +3229,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     64;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 32;
-static constexpr dart::compiler::target::word Library_InstanceSize = 104;
+static constexpr dart::compiler::target::word Library_InstanceSize = 112;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 24;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -3764,7 +3764,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     60;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
-static constexpr dart::compiler::target::word Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -4304,7 +4304,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     120;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
-static constexpr dart::compiler::target::word Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -4834,7 +4834,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     60;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 28;
-static constexpr dart::compiler::target::word Library_InstanceSize = 84;
+static constexpr dart::compiler::target::word Library_InstanceSize = 88;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 20;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -5375,7 +5375,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     120;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 48;
-static constexpr dart::compiler::target::word Library_InstanceSize = 160;
+static constexpr dart::compiler::target::word Library_InstanceSize = 168;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 40;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -5914,7 +5914,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     64;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 32;
-static constexpr dart::compiler::target::word Library_InstanceSize = 104;
+static constexpr dart::compiler::target::word Library_InstanceSize = 112;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 24;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -6454,7 +6454,7 @@
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
     64;
 static constexpr dart::compiler::target::word LanguageError_InstanceSize = 32;
-static constexpr dart::compiler::target::word Library_InstanceSize = 104;
+static constexpr dart::compiler::target::word Library_InstanceSize = 112;
 static constexpr dart::compiler::target::word LibraryPrefix_InstanceSize = 24;
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 static constexpr dart::compiler::target::word MegamorphicCache_InstanceSize =
@@ -7052,7 +7052,7 @@
     AOT_KernelProgramInfo_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     28;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 84;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     20;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -7660,7 +7660,7 @@
     AOT_KernelProgramInfo_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     48;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 152;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -8272,7 +8272,7 @@
     AOT_KernelProgramInfo_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     48;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 152;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -8880,7 +8880,7 @@
     AOT_KernelProgramInfo_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     32;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 96;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 104;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -9489,7 +9489,7 @@
     AOT_KernelProgramInfo_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     32;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 96;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 104;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -10088,7 +10088,7 @@
     AOT_KernelProgramInfo_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     28;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 84;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     20;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -10689,7 +10689,7 @@
     AOT_KernelProgramInfo_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     48;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 152;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -11294,7 +11294,7 @@
     AOT_KernelProgramInfo_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     48;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 152;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 160;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -11895,7 +11895,7 @@
     AOT_KernelProgramInfo_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     32;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 96;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 104;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
@@ -12497,7 +12497,7 @@
     AOT_KernelProgramInfo_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_LanguageError_InstanceSize =
     32;
-static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 96;
+static constexpr dart::compiler::target::word AOT_Library_InstanceSize = 104;
 static constexpr dart::compiler::target::word AOT_LibraryPrefix_InstanceSize =
     24;
 static constexpr dart::compiler::target::word AOT_LinkedHashMap_InstanceSize =
diff --git a/runtime/vm/constants_arm.cc b/runtime/vm/constants_arm.cc
index 21ae852..1903427 100644
--- a/runtime/vm/constants_arm.cc
+++ b/runtime/vm/constants_arm.cc
@@ -12,7 +12,7 @@
 
 using dart::bit_cast;
 
-const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
     "r0", "r1", "r2",  "r3",  "r4", "pp", "r6", "fp",
     "r8", "r9", "thr", "r11", "ip", "sp", "lr", "pc",
@@ -22,13 +22,13 @@
 #endif
 };
 
-const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+const char* const fpu_reg_names[kNumberOfFpuRegisters] = {
     "q0", "q1", "q2",  "q3",  "q4",  "q5",  "q6",  "q7",
 #if defined(VFPv3_D32)
     "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
 #endif
 };
-const char* fpu_d_reg_names[kNumberOfDRegisters] = {
+const char* const fpu_d_reg_names[kNumberOfDRegisters] = {
     "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
     "d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
 #if defined(VFPv3_D32)
@@ -36,7 +36,7 @@
     "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
 #endif
 };
-const char* fpu_s_reg_names[kNumberOfSRegisters] = {
+const char* const fpu_s_reg_names[kNumberOfSRegisters] = {
     "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",  "s8",  "s9",  "s10",
     "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21",
     "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index b72a093..8130b72 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -291,10 +291,10 @@
 const int kNumberOfFpuRegisters = kNumberOfQRegisters;
 const FpuRegister kNoFpuRegister = kNoQRegister;
 
-extern const char* cpu_reg_names[kNumberOfCpuRegisters];
-extern const char* fpu_reg_names[kNumberOfFpuRegisters];
-extern const char* fpu_s_reg_names[kNumberOfSRegisters];
-extern const char* fpu_d_reg_names[kNumberOfDRegisters];
+extern const char* const cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* const fpu_reg_names[kNumberOfFpuRegisters];
+extern const char* const fpu_s_reg_names[kNumberOfSRegisters];
+extern const char* const fpu_d_reg_names[kNumberOfDRegisters];
 
 // Register aliases.
 const Register TMP = IP;            // Used as scratch register by assembler.
diff --git a/runtime/vm/constants_arm64.cc b/runtime/vm/constants_arm64.cc
index 7945838..b30808b 100644
--- a/runtime/vm/constants_arm64.cc
+++ b/runtime/vm/constants_arm64.cc
@@ -10,13 +10,13 @@
 
 namespace dart {
 
-const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
     "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
     "nr",  "r23", "r24", "ip0", "ip1", "pp",  "r28", "fp",  "lr",  "r31",
 };
 
-const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+const char* const fpu_reg_names[kNumberOfFpuRegisters] = {
     "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",  "v8",  "v9",  "v10",
     "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
     "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 91ff40e..61f2c4a 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -126,8 +126,8 @@
 const int kNumberOfFpuRegisters = kNumberOfVRegisters;
 const FpuRegister kNoFpuRegister = kNoVRegister;
 
-extern const char* cpu_reg_names[kNumberOfCpuRegisters];
-extern const char* fpu_reg_names[kNumberOfFpuRegisters];
+extern const char* const cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* const fpu_reg_names[kNumberOfFpuRegisters];
 
 // Register aliases.
 const Register TMP = R16;  // Used as scratch register by assembler.
diff --git a/runtime/vm/constants_ia32.cc b/runtime/vm/constants_ia32.cc
index 2d83fdd..bbe4feb 100644
--- a/runtime/vm/constants_ia32.cc
+++ b/runtime/vm/constants_ia32.cc
@@ -10,10 +10,10 @@
 
 namespace dart {
 
-const char* cpu_reg_names[kNumberOfCpuRegisters] = {"eax", "ecx", "edx", "ebx",
-                                                    "esp", "ebp", "esi", "edi"};
+const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
+    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
 
-const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+const char* const fpu_reg_names[kNumberOfXmmRegisters] = {
     "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
 
 // Although 'kArgumentRegisters' and 'kFpuArgumentRegisters' are both 0, we have
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index df188c2..b83e196 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -64,8 +64,8 @@
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
-extern const char* cpu_reg_names[kNumberOfCpuRegisters];
-extern const char* fpu_reg_names[kNumberOfXmmRegisters];
+extern const char* const cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* const fpu_reg_names[kNumberOfXmmRegisters];
 
 // Register aliases.
 const Register TMP = kNoRegister;   // No scratch register used by assembler.
diff --git a/runtime/vm/constants_x64.cc b/runtime/vm/constants_x64.cc
index 24e9abc..6312a54 100644
--- a/runtime/vm/constants_x64.cc
+++ b/runtime/vm/constants_x64.cc
@@ -10,11 +10,11 @@
 
 namespace dart {
 
-const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+const char* const cpu_reg_names[kNumberOfCpuRegisters] = {
     "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
     "r8",  "r9",  "r10", "r11", "r12", "r13", "thr", "pp"};
 
-const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+const char* const fpu_reg_names[kNumberOfXmmRegisters] = {
     "xmm0", "xmm1", "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
     "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
 
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index e20d755..546a0f2 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -96,8 +96,8 @@
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
-extern const char* cpu_reg_names[kNumberOfCpuRegisters];
-extern const char* fpu_reg_names[kNumberOfXmmRegisters];
+extern const char* const cpu_reg_names[kNumberOfCpuRegisters];
+extern const char* const fpu_reg_names[kNumberOfXmmRegisters];
 
 enum RexBits {
   REX_NONE = 0,
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 54be0aa..8b0cd3d 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5999,6 +5999,18 @@
   return Api::Success();
 }
 
+DART_EXPORT Dart_Handle
+Dart_SetFfiNativeResolver(Dart_Handle library,
+                          Dart_FfiNativeResolver resolver) {
+  DARTSCOPE(Thread::Current());
+  const Library& lib = Api::UnwrapLibraryHandle(Z, library);
+  if (lib.IsNull()) {
+    RETURN_TYPE_ERROR(Z, library, Library);
+  }
+  lib.set_ffi_native_resolver(resolver);
+  return Api::Success();
+}
+
 // --- Peer support ---
 
 DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer) {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a008f7b..1f2f190 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -9293,6 +9293,76 @@
   EXPECT(result == Dart_True());
 }
 
+static intptr_t EchoInt(double x) {
+  return x;
+}
+
+static void* FfiNativeResolver(const char* name) {
+  ASSERT(strcmp(name, "EchoInt") == 0);
+  return reinterpret_cast<void*>(EchoInt);
+}
+
+TEST_CASE(Dart_SetFfiNativeResolver) {
+  const char* kScriptChars = R"(
+    import 'dart:ffi';
+    @FfiNative<IntPtr Function(Double)>('EchoInt')
+    external int echoInt(double x);
+    main() => echoInt(7.0);
+    )";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
+  EXPECT_VALID(lib);
+
+  Dart_Handle result = Dart_SetFfiNativeResolver(lib, &FfiNativeResolver);
+  EXPECT_VALID(result);
+
+  result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+  EXPECT_VALID(result);
+
+  int64_t value = 0;
+  result = Dart_IntegerToInt64(result, &value);
+  EXPECT_VALID(result);
+  EXPECT_EQ(7, value);
+}
+
+TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) {
+  const char* kScriptChars = R"(
+    import 'dart:ffi';
+    @FfiNative<IntPtr Function(Double)>('EchoInt')
+    external int echoInt(double x);
+    main() => echoInt(7.0);
+    )";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
+  EXPECT_VALID(lib);
+
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+  EXPECT_ERROR(
+      result,
+      "Invalid argument(s): Library has no handler: 'file:///test-lib'.");
+}
+
+static void* NopResolver(const char* name) {
+  return nullptr;
+}
+
+TEST_CASE(Dart_SetFfiNativeResolver_DoesNotResolve) {
+  const char* kScriptChars = R"(
+    import 'dart:ffi';
+    @FfiNative<Void Function()>('DoesNotResolve')
+    external void doesNotResolve();
+    main() => doesNotResolve();
+    )";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
+  EXPECT_VALID(lib);
+
+  Dart_Handle result = Dart_SetFfiNativeResolver(lib, &NopResolver);
+  EXPECT_VALID(result);
+
+  result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+  EXPECT_ERROR(
+      result,
+      "Invalid argument(s): Couldn't resolve function: 'DoesNotResolve'");
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 61023ef..0aa6d1b 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1413,6 +1413,15 @@
   return TryAllocateDataBumpLocked(freelist, size);
 }
 
+ObjectPtr PageSpace::AllocateSnapshot(intptr_t size) {
+  ASSERT(Utils::IsAligned(size, kObjectAlignment));
+  uword address = TryAllocateDataBumpLocked(size);
+  if (address == 0) {
+    OUT_OF_MEMORY();
+  }
+  return UntaggedObject::FromAddr(address);
+}
+
 void PageSpace::SetupImagePage(void* pointer, uword size, bool is_executable) {
   // Setup a OldPage so precompiled Instructions can be traversed.
   // Instructions are contiguous at [pointer, pointer + size). OldPage
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 7eef9f8..4795240 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -509,6 +509,7 @@
     return TryAllocatePromoLockedSlow(freelist, size);
   }
   uword TryAllocatePromoLockedSlow(FreeList* freelist, intptr_t size);
+  ObjectPtr AllocateSnapshot(intptr_t size);
 
   void SetupImagePage(void* pointer, uword size, bool is_executable);
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index fae5e39b..29a2fba 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13095,6 +13095,7 @@
   result.untag()->set_loaded_scripts(Array::null());
   result.set_native_entry_resolver(NULL);
   result.set_native_entry_symbol_resolver(NULL);
+  result.set_ffi_native_resolver(nullptr);
   result.set_flags(0);
   result.set_is_in_fullsnapshot(false);
   result.set_is_nnbd(false);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 898c813..03824ad 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4766,6 +4766,17 @@
         &untag()->native_entry_symbol_resolver_, native_symbol_resolver);
   }
 
+  // Resolver for FFI native function pointers.
+  Dart_FfiNativeResolver ffi_native_resolver() const {
+    return LoadNonPointer<Dart_FfiNativeResolver, std::memory_order_relaxed>(
+        &untag()->ffi_native_resolver_);
+  }
+  void set_ffi_native_resolver(Dart_FfiNativeResolver value) const {
+    StoreNonPointer<Dart_FfiNativeResolver, Dart_FfiNativeResolver,
+                    std::memory_order_relaxed>(&untag()->ffi_native_resolver_,
+                                               value);
+  }
+
   bool is_in_fullsnapshot() const {
     return UntaggedLibrary::InFullSnapshotBit::decode(untag()->flags_);
   }
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 1f75699..2ffb6ce 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -24,12 +24,8 @@
 }
 
 void IsolateObjectStore::Init() {
-#define INIT_FIELD(Type, name) name##_ = Type::null();
-  ISOLATE_OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD)
-#undef INIT_FIELD
-
   for (ObjectPtr* current = from(); current <= to(); current++) {
-    ASSERT(*current == Object::null());
+    *current = Object::null();
   }
 }
 
@@ -40,12 +36,21 @@
   {
     JSONObject fields(jsobj, "fields");
     Object& value = Object::Handle();
-#define PRINT_OBJECT_STORE_FIELD(type, name)                                   \
-  value = name##_;                                                             \
-  fields.AddProperty(#name "_", value);
-    ISOLATE_OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD,
-                                    PRINT_OBJECT_STORE_FIELD);
-#undef PRINT_OBJECT_STORE_FIELD
+
+    static const char* const names[] = {
+#define EMIT_FIELD_NAME(type, name) #name "_",
+        ISOLATE_OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME)
+#undef EMIT_FIELD_NAME
+    };
+    ObjectPtr* current = from();
+    intptr_t i = 0;
+    while (current <= to()) {
+      value = *current;
+      fields.AddProperty(names[i], value);
+      current++;
+      i++;
+    }
+    ASSERT(i == ARRAY_SIZE(names));
   }
 }
 #endif  // !PRODUCT
@@ -87,12 +92,8 @@
 }
 
 ObjectStore::ObjectStore() {
-#define INIT_FIELD(Type, name) name##_ = Type::null();
-  OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD, INIT_FIELD, INIT_FIELD)
-#undef INIT_FIELD
-
   for (ObjectPtr* current = from(); current <= to(); current++) {
-    ASSERT(*current == Object::null());
+    *current = Object::null();
   }
 }
 
@@ -118,12 +119,21 @@
   {
     JSONObject fields(jsobj, "fields");
     Object& value = Object::Handle();
-#define PRINT_OBJECT_STORE_FIELD(type, name)                                   \
-  value = name##_;                                                             \
-  fields.AddProperty(#name "_", value);
-    OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD,
-                            PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD);
-#undef PRINT_OBJECT_STORE_FIELD
+    static const char* const names[] = {
+#define EMIT_FIELD_NAME(type, name) #name "_",
+        OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME,
+                                EMIT_FIELD_NAME, EMIT_FIELD_NAME)
+#undef EMIT_FIELD_NAME
+    };
+    ObjectPtr* current = from();
+    intptr_t i = 0;
+    while (current <= to()) {
+      value = *current;
+      fields.AddProperty(names[i], value);
+      current++;
+      i++;
+    }
+    ASSERT(i == ARRAY_SIZE(names));
   }
 }
 #endif  // !PRODUCT
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b9f09a5..b25b2bb 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1697,6 +1697,8 @@
 
   Dart_NativeEntryResolver native_entry_resolver_;  // Resolves natives.
   Dart_NativeEntrySymbol native_entry_symbol_resolver_;
+  Dart_FfiNativeResolver ffi_native_resolver_;
+
   classid_t index_;       // Library id number.
   uint16_t num_imports_;  // Number of entries in imports_.
   int8_t load_state_;     // Of type LibraryState.
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 1b09c40..454551b 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -234,7 +234,7 @@
    OFFSET_OF(Untagged##class_name, field_name)},
 
 // clang-format off
-OffsetsTable::OffsetsTableEntry OffsetsTable::offsets_table[] = {
+const OffsetsTable::OffsetsTableEntry OffsetsTable::offsets_table[] = {
     COMMON_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
 #if !defined(PRODUCT)
     NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
diff --git a/runtime/vm/raw_object_fields.h b/runtime/vm/raw_object_fields.h
index 2b456be8..6a4f572 100644
--- a/runtime/vm/raw_object_fields.h
+++ b/runtime/vm/raw_object_fields.h
@@ -31,11 +31,11 @@
 
   struct OffsetsTableEntry {
     const intptr_t class_id;
-    const char* field_name;
-    intptr_t offset;
+    const char* const field_name;
+    const intptr_t offset;
   };
 
-  static OffsetsTableEntry offsets_table[];
+  static const OffsetsTableEntry offsets_table[];
 
  private:
   struct IntAndIntToStringMapTraits {
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 9a90be3..e926685 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -132,7 +132,7 @@
 const uint8_t* Service::dart_library_kernel_ = NULL;
 intptr_t Service::dart_library_kernel_len_ = 0;
 
-static StreamInfo* streams_[] = {
+static StreamInfo* const streams_[] = {
     &Service::vm_stream,      &Service::isolate_stream,
     &Service::debug_stream,   &Service::gc_stream,
     &Service::echo_stream,    &Service::heapsnapshot_stream,
@@ -1395,7 +1395,7 @@
                                       parameter_values, reply_port, id);
 }
 
-static const MethodParameter* get_isolate_params[] = {
+static const MethodParameter* const get_isolate_params[] = {
     ISOLATE_PARAMETER,
     NULL,
 };
@@ -1404,7 +1404,7 @@
   thread->isolate()->PrintJSON(js, false);
 }
 
-static const MethodParameter* get_isolate_group_params[] = {
+static const MethodParameter* const get_isolate_group_params[] = {
     ISOLATE_GROUP_PARAMETER,
     NULL,
 };
@@ -1462,7 +1462,7 @@
   });
 }
 
-static const MethodParameter* get_memory_usage_params[] = {
+static const MethodParameter* const get_memory_usage_params[] = {
     ISOLATE_PARAMETER,
     NULL,
 };
@@ -1471,7 +1471,7 @@
   thread->isolate()->PrintMemoryUsageJSON(js);
 }
 
-static const MethodParameter* get_isolate_group_memory_usage_params[] = {
+static const MethodParameter* const get_isolate_group_memory_usage_params[] = {
     ISOLATE_GROUP_PARAMETER,
     NULL,
 };
@@ -1482,7 +1482,7 @@
   });
 }
 
-static const MethodParameter* get_scripts_params[] = {
+static const MethodParameter* const get_scripts_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -1516,7 +1516,7 @@
   }
 }
 
-static const MethodParameter* get_stack_params[] = {
+static const MethodParameter* const get_stack_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new UIntParameter("limit", false),
     NULL,
@@ -2177,7 +2177,7 @@
   }
 }
 
-static const MethodParameter* get_inbound_references_params[] = {
+static const MethodParameter* const get_inbound_references_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -2310,7 +2310,7 @@
   }
 }
 
-static const MethodParameter* get_retaining_path_params[] = {
+static const MethodParameter* const get_retaining_path_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -2351,7 +2351,7 @@
   PrintRetainingPath(thread, &obj, limit, js);
 }
 
-static const MethodParameter* get_retained_size_params[] = {
+static const MethodParameter* const get_retained_size_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("targetId", true),
     NULL,
@@ -2390,7 +2390,7 @@
   result.PrintJSON(js, true);
 }
 
-static const MethodParameter* get_reachable_size_params[] = {
+static const MethodParameter* const get_reachable_size_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("targetId", true),
     NULL,
@@ -2429,7 +2429,7 @@
   result.PrintJSON(js, true);
 }
 
-static const MethodParameter* invoke_params[] = {
+static const MethodParameter* const invoke_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -2562,7 +2562,7 @@
                  js->method());
 }
 
-static const MethodParameter* evaluate_params[] = {
+static const MethodParameter* const evaluate_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -2686,11 +2686,12 @@
       js->method());
 }
 
-static const MethodParameter* build_expression_evaluation_scope_params[] = {
-    RUNNABLE_ISOLATE_PARAMETER,
-    new IdParameter("frameIndex", false),
-    new IdParameter("targetId", false),
-    NULL,
+static const MethodParameter* const build_expression_evaluation_scope_params[] =
+    {
+        RUNNABLE_ISOLATE_PARAMETER,
+        new IdParameter("frameIndex", false),
+        new IdParameter("targetId", false),
+        NULL,
 };
 
 static void BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
@@ -2862,7 +2863,7 @@
 }
 #endif
 
-static const MethodParameter* compile_expression_params[] = {
+static const MethodParameter* const compile_expression_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new StringParameter("expression", true),
     new StringParameter("definitions", false),
@@ -2932,7 +2933,7 @@
 #endif
 }
 
-static const MethodParameter* evaluate_compiled_expression_params[] = {
+static const MethodParameter* const evaluate_compiled_expression_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new UIntParameter("frameIndex", false),
     new IdParameter("targetId", false),
@@ -3066,7 +3067,7 @@
   }
 }
 
-static const MethodParameter* evaluate_in_frame_params[] = {
+static const MethodParameter* const evaluate_in_frame_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new UIntParameter("frameIndex", true),
     new MethodParameter("expression", true),
@@ -3165,7 +3166,7 @@
   intptr_t count_;
 };
 
-static const MethodParameter* get_instances_params[] = {
+static const MethodParameter* const get_instances_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3219,7 +3220,7 @@
   }
 }
 
-static const MethodParameter* get_instances_as_array_params[] = {
+static const MethodParameter* const get_instances_as_array_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3267,7 +3268,7 @@
   instances.PrintJSON(js, /* as_ref */ true);
 }
 
-static const MethodParameter* get_ports_params[] = {
+static const MethodParameter* const get_ports_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3303,7 +3304,7 @@
 };
 #endif
 
-static const MethodParameter* get_source_report_params[] = {
+static const MethodParameter* const get_source_report_params[] = {
 #if !defined(DART_PRECOMPILED_RUNTIME)
     RUNNABLE_ISOLATE_PARAMETER,
     new EnumListParameter("reports", true, report_enum_names),
@@ -3382,7 +3383,7 @@
 #endif  // !DART_PRECOMPILED_RUNTIME
 }
 
-static const MethodParameter* reload_sources_params[] = {
+static const MethodParameter* const reload_sources_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new BoolParameter("force", false),
     new BoolParameter("pause", false),
@@ -3489,7 +3490,7 @@
   bpt->PrintJSON(js);
 }
 
-static const MethodParameter* add_breakpoint_params[] = {
+static const MethodParameter* const add_breakpoint_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("scriptId", true),
     new UIntParameter("line", true),
@@ -3514,7 +3515,7 @@
   AddBreakpointCommon(thread, js, script_uri);
 }
 
-static const MethodParameter* add_breakpoint_with_script_uri_params[] = {
+static const MethodParameter* const add_breakpoint_with_script_uri_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("scriptUri", true),
     new UIntParameter("line", true),
@@ -3532,7 +3533,7 @@
   AddBreakpointCommon(thread, js, script_uri);
 }
 
-static const MethodParameter* add_breakpoint_at_entry_params[] = {
+static const MethodParameter* const add_breakpoint_at_entry_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("functionId", true),
     NULL,
@@ -3561,7 +3562,7 @@
   bpt->PrintJSON(js);
 }
 
-static const MethodParameter* add_breakpoint_at_activation_params[] = {
+static const MethodParameter* const add_breakpoint_at_activation_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("objectId", true),
     NULL,
@@ -3589,7 +3590,7 @@
   bpt->PrintJSON(js);
 }
 
-static const MethodParameter* remove_breakpoint_params[] = {
+static const MethodParameter* const remove_breakpoint_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3715,7 +3716,7 @@
   PrintInvalidParamError(js, "metricId");
 }
 
-static const MethodParameter* get_isolate_metric_list_params[] = {
+static const MethodParameter* const get_isolate_metric_list_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3742,7 +3743,7 @@
   }
 }
 
-static const MethodParameter* get_isolate_metric_params[] = {
+static const MethodParameter* const get_isolate_metric_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3781,7 +3782,7 @@
 #undef DEFINE_NAME
         NULL};
 
-static const MethodParameter* set_vm_timeline_flags_params[] = {
+static const MethodParameter* const set_vm_timeline_flags_params[] = {
     NO_ISOLATE_PARAMETER,
     new EnumListParameter("recordedStreams",
                           false,
@@ -3832,7 +3833,7 @@
 #endif
 }
 
-static const MethodParameter* get_vm_timeline_flags_params[] = {
+static const MethodParameter* const get_vm_timeline_flags_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3849,7 +3850,7 @@
 #endif
 }
 
-static const MethodParameter* get_vm_timeline_micros_params[] = {
+static const MethodParameter* const get_vm_timeline_micros_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3860,7 +3861,7 @@
   obj.AddPropertyTimeMicros("timestamp", OS::GetCurrentMonotonicMicros());
 }
 
-static const MethodParameter* clear_vm_timeline_params[] = {
+static const MethodParameter* const clear_vm_timeline_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -3875,7 +3876,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* get_vm_timeline_params[] = {
+static const MethodParameter* const get_vm_timeline_params[] = {
     NO_ISOLATE_PARAMETER,
     new Int64Parameter("timeOriginMicros", false),
     new Int64Parameter("timeExtentMicros", false),
@@ -3921,7 +3922,7 @@
     Debugger::kContinue,  // Default value
 };
 
-static const MethodParameter* resume_params[] = {
+static const MethodParameter* const resume_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new EnumParameter("step", false, step_enum_names),
     new UIntParameter("frameIndex", false),
@@ -3994,7 +3995,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* kill_params[] = {
+static const MethodParameter* const kill_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4008,7 +4009,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* pause_params[] = {
+static const MethodParameter* const pause_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4024,7 +4025,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* enable_profiler_params[] = {
+static const MethodParameter* const enable_profiler_params[] = {
     NULL,
 };
 
@@ -4036,7 +4037,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* get_tag_profile_params[] = {
+static const MethodParameter* const get_tag_profile_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4047,7 +4048,7 @@
   thread->isolate()->vm_tag_counters()->PrintToJSONObject(&miniProfile);
 }
 
-static const MethodParameter* get_cpu_samples_params[] = {
+static const MethodParameter* const get_cpu_samples_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new Int64Parameter("timeOriginMicros", false),
     new Int64Parameter("timeExtentMicros", false),
@@ -4068,7 +4069,7 @@
                              include_code_samples);
 }
 
-static const MethodParameter* get_allocation_traces_params[] = {
+static const MethodParameter* const get_allocation_traces_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("classId", false),
     new Int64Parameter("timeOriginMicros", false),
@@ -4108,7 +4109,7 @@
   }
 }
 
-static const MethodParameter* get_native_allocation_samples_params[] = {
+static const MethodParameter* const get_native_allocation_samples_params[] = {
     NO_ISOLATE_PARAMETER,
     new Int64Parameter("timeOriginMicros", false),
     new Int64Parameter("timeExtentMicros", false),
@@ -4132,7 +4133,7 @@
       js, time_origin_micros, time_extent_micros, include_code_samples);
 }
 
-static const MethodParameter* clear_cpu_samples_params[] = {
+static const MethodParameter* const clear_cpu_samples_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4174,7 +4175,7 @@
   isolate_group->class_table()->AllocationProfilePrintJSON(js, internal);
 }
 
-static const MethodParameter* get_allocation_profile_params[] = {
+static const MethodParameter* const get_allocation_profile_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4187,7 +4188,7 @@
   GetAllocationProfileImpl(thread, js, true);
 }
 
-static const MethodParameter* collect_all_garbage_params[] = {
+static const MethodParameter* const collect_all_garbage_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4198,7 +4199,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* get_heap_map_params[] = {
+static const MethodParameter* const get_heap_map_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4221,7 +4222,7 @@
   isolate_group->heap()->PrintHeapMapToJSONStream(isolate_group, js);
 }
 
-static const MethodParameter* request_heap_snapshot_params[] = {
+static const MethodParameter* const request_heap_snapshot_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4437,7 +4438,7 @@
   return vm_size;
 }
 
-static const MethodParameter* get_process_memory_usage_params[] = {
+static const MethodParameter* const get_process_memory_usage_params[] = {
     NULL,
 };
 
@@ -4506,7 +4507,7 @@
   Service::HandleEvent(&event);
 }
 
-static const MethodParameter* get_persistent_handles_params[] = {
+static const MethodParameter* const get_persistent_handles_params[] = {
     ISOLATE_PARAMETER,
     NULL,
 };
@@ -4594,7 +4595,7 @@
   }
 }
 
-static const MethodParameter* get_ports_private_params[] = {
+static const MethodParameter* const get_ports_private_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4620,7 +4621,7 @@
   jsobj.AddProperty("bart", "simpson");
 }
 
-static const MethodParameter* get_object_params[] = {
+static const MethodParameter* const get_object_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new UIntParameter("offset", false),
     new UIntParameter("count", false),
@@ -4693,7 +4694,7 @@
   PrintInvalidParamError(js, "objectId");
 }
 
-static const MethodParameter* get_object_store_params[] = {
+static const MethodParameter* const get_object_store_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4703,7 +4704,7 @@
   thread->isolate_group()->object_store()->PrintToJSONObject(&jsobj);
 }
 
-static const MethodParameter* get_isolate_object_store_params[] = {
+static const MethodParameter* const get_isolate_object_store_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4713,7 +4714,7 @@
   thread->isolate()->isolate_object_store()->PrintToJSONObject(&jsobj);
 }
 
-static const MethodParameter* get_class_list_params[] = {
+static const MethodParameter* const get_class_list_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4724,7 +4725,7 @@
   table->PrintToJSONObject(&jsobj);
 }
 
-static const MethodParameter* get_type_arguments_list_params[] = {
+static const MethodParameter* const get_type_arguments_list_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4760,7 +4761,7 @@
   typeargs_table.Release();
 }
 
-static const MethodParameter* get_version_params[] = {
+static const MethodParameter* const get_version_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4807,7 +4808,7 @@
   JSONArray* jsarr_;
 };
 
-static const MethodParameter* get_vm_params[] = {
+static const MethodParameter* const get_vm_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4904,7 +4905,7 @@
   Service::PrintJSONForVM(js, false);
 }
 
-static const char* exception_pause_mode_names[] = {
+static const char* const exception_pause_mode_names[] = {
     "All",
     "None",
     "Unhandled",
@@ -4918,7 +4919,7 @@
     kInvalidExceptionPauseInfo,
 };
 
-static const MethodParameter* set_exception_pause_mode_params[] = {
+static const MethodParameter* const set_exception_pause_mode_params[] = {
     ISOLATE_PARAMETER,
     new EnumParameter("mode", true, exception_pause_mode_names),
     NULL,
@@ -4945,7 +4946,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* set_breakpoint_state_params[] = {
+static const MethodParameter* const set_breakpoint_state_params[] = {
     ISOLATE_PARAMETER,
     new IdParameter("breakpointId", true),
     new BoolParameter("enable", true),
@@ -4974,7 +4975,7 @@
   bpt->PrintJSON(js);
 }
 
-static const MethodParameter* get_flag_list_params[] = {
+static const MethodParameter* const get_flag_list_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -4983,7 +4984,7 @@
   Flags::PrintJSON(js);
 }
 
-static const MethodParameter* set_flags_params[] = {
+static const MethodParameter* const set_flags_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
@@ -5062,7 +5063,7 @@
   }
 }
 
-static const MethodParameter* set_library_debuggable_params[] = {
+static const MethodParameter* const set_library_debuggable_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("libraryId", true),
     new BoolParameter("isDebuggable", true),
@@ -5085,7 +5086,7 @@
   PrintInvalidParamError(js, "libraryId");
 }
 
-static const MethodParameter* set_name_params[] = {
+static const MethodParameter* const set_name_params[] = {
     ISOLATE_PARAMETER,
     new MethodParameter("name", true),
     NULL,
@@ -5102,7 +5103,7 @@
   return;
 }
 
-static const MethodParameter* set_vm_name_params[] = {
+static const MethodParameter* const set_vm_name_params[] = {
     NO_ISOLATE_PARAMETER,
     new MethodParameter("name", true),
     NULL,
@@ -5120,7 +5121,7 @@
   return;
 }
 
-static const MethodParameter* set_trace_class_allocation_params[] = {
+static const MethodParameter* const set_trace_class_allocation_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     new IdParameter("classId", true),
     new BoolParameter("enable", true),
@@ -5147,7 +5148,7 @@
   PrintSuccess(js);
 }
 
-static const MethodParameter* get_default_classes_aliases_params[] = {
+static const MethodParameter* const get_default_classes_aliases_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
 };
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 8b6fec7..78612fb 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -134,7 +134,7 @@
 }
 
 static Register LookupCpuRegisterByName(const char* name) {
-  static const char* kNames[] = {
+  static const char* const kNames[] = {
       "r0",  "r1",  "r2",  "r3",  "r4",  "r5", "r6", "r7", "r8", "r9", "r10",
       "r11", "r12", "r13", "r14", "r15", "pc", "lr", "sp", "ip", "fp", "pp"};
   static const Register kRegisters[] = {R0, R1, R2,  R3,  R4,  R5,  R6,  R7,
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 3b5182d..83f65d7 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -139,7 +139,7 @@
 }
 
 static Register LookupCpuRegisterByName(const char* name) {
-  static const char* kNames[] = {
+  static const char* const kNames[] = {
       "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
       "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 23dd381..fdddf37 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -22,7 +22,7 @@
 StringPtr Symbols::predefined_[Symbols::kNumberOfOneCharCodeSymbols];
 String* Symbols::symbol_handles_[Symbols::kMaxPredefinedId];
 
-static const char* names[] = {
+static const char* const names[] = {
     // clang-format off
   NULL,
 #define DEFINE_SYMBOL_LITERAL(symbol, literal) literal,
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index 8c48f22..ba981ee 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -66,9 +66,10 @@
   return nullptr;
 }
 
-VMTag::TagEntry VMTag::entries_[] = {
+const VMTag::TagEntry VMTag::entries_[] = {
     {
-        "InvalidTag", kInvalidTagId,
+        "InvalidTag",
+        kInvalidTagId,
     },
 #define DEFINE_VM_TAG_ENTRY(tag) {"" #tag, k##tag##TagId},
     VM_TAG_LIST(DEFINE_VM_TAG_ENTRY)
diff --git a/runtime/vm/tags.h b/runtime/vm/tags.h
index e8d5919..8e270ab 100644
--- a/runtime/vm/tags.h
+++ b/runtime/vm/tags.h
@@ -71,7 +71,7 @@
     const char* name;
     uword id;
   };
-  static TagEntry entries_[];
+  static const TagEntry entries_[];
 };
 
 class VMTagScope : ThreadStackResource {
diff --git a/runtime/vm/token.cc b/runtime/vm/token.cc
index 5208384..ba33707 100644
--- a/runtime/vm/token.cc
+++ b/runtime/vm/token.cc
@@ -9,13 +9,13 @@
 namespace dart {
 
 #define TOKEN_NAME(t, s, p, a) #t,
-const char* Token::name_[] = {DART_TOKEN_LIST(TOKEN_NAME)
-                                  DART_KEYWORD_LIST(TOKEN_NAME)};
+const char* const Token::name_[] = {DART_TOKEN_LIST(TOKEN_NAME)
+                                        DART_KEYWORD_LIST(TOKEN_NAME)};
 #undef TOKEN_NAME
 
 #define TOKEN_STRING(t, s, p, a) s,
-const char* Token::tok_str_[] = {DART_TOKEN_LIST(TOKEN_STRING)
-                                     DART_KEYWORD_LIST(TOKEN_STRING)};
+const char* const Token::tok_str_[] = {DART_TOKEN_LIST(TOKEN_STRING)
+                                           DART_KEYWORD_LIST(TOKEN_STRING)};
 #undef TOKEN_STRING
 
 #define TOKEN_PRECEDENCE(t, s, p, a) p,
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index bae0743..e2fc074 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -364,8 +364,8 @@
   }
 
  private:
-  static const char* name_[];
-  static const char* tok_str_[];
+  static const char* const name_[];
+  static const char* const tok_str_[];
   static const uint8_t precedence_[];
   static const Attribute attributes_[];
 };
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index e82e567..0e8be36 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -801,3 +801,33 @@
   /// symbols in `dart_api_dl.h`.
   external static Pointer<Void> get initializeApiDLData;
 }
+
+/// Annotation to be used for marking an external function as FFI native.
+///
+/// Example:
+///```dart
+/// @FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum")
+/// external int sum(int a, int b);
+///```
+/// Calling such functions will throw an exception if no resolver
+/// was set on the library or the resolver failed to resolve the name.
+///
+/// See `Dart_SetFfiNativeResolver` in `dart_api.h`
+///
+/// NOTE: This is an experimental feature and may change in the future.
+class FfiNative<T> {
+  final String nativeName;
+  const FfiNative(this.nativeName);
+}
+
+// Bootstrapping native for getting the FFI native C function pointer to look
+// up the FFI resolver.
+Pointer<NativeFunction<IntPtr Function(Handle, Handle)>>
+    _get_ffi_native_resolver<
+        T extends NativeFunction>() native "Ffi_GetFfiNativeResolver";
+
+// Resolver for FFI Native C function pointers.
+@pragma('vm:entry-point')
+final _ffi_resolver =
+    _get_ffi_native_resolver<NativeFunction<IntPtr Function(Handle, Handle)>>()
+        .asFunction<int Function(Object, Object)>();
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index f0ed6d2..36cf262 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -1,14 +1,36 @@
 part of html_common;
 
-/// Converts a JavaScript object with properties into a Dart Map.
-/// Not suitable for nested objects.
+/// Converts native values to their Dart equivalent
+///
+/// This includes other maps, lists, or values that don't need a conversion e.g.
+/// bool, String.
+_convertNativeToDart_Value(value) {
+  if (value == null) return value;
+  if (value is String || value is num || value is bool) return value;
+  if (isJavaScriptSimpleObject(value)) {
+    return convertNativeToDart_Dictionary(value);
+  }
+  if (JS('bool', 'Array.isArray(#)', value)) {
+    List values = [];
+    for (var i = 0; i < JS<int>('int', '#.length', value); i++) {
+      values.add(_convertNativeToDart_Value(JS('var', '#[#]', value, i)));
+    }
+
+    return values;
+  }
+  return value;
+}
+
+/// Recursively converts a JavaScript object with properties into a Dart Map.
+/// This includes maps, lists, and other values that don't need a conversion.
 Map<String, dynamic>? convertNativeToDart_Dictionary(object) {
   if (object == null) return null;
   var dict = <String, dynamic>{};
   var keys = JS<JSExtendableArray>(
       'JSExtendableArray', 'Object.getOwnPropertyNames(#)', object);
   for (final key in keys) {
-    dict[key] = JS('var', '#[#]', object, key);
+    dict[JS('String', '#', key)] =
+        _convertNativeToDart_Value(JS('var', '#[#]', object, key));
   }
   return dict;
 }
diff --git a/tests/lib/html/convert_native_to_dart_dictionary_test.dart b/tests/lib/html/convert_native_to_dart_dictionary_test.dart
new file mode 100644
index 0000000..b61fea1
--- /dev/null
+++ b/tests/lib/html/convert_native_to_dart_dictionary_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html_common';
+import 'package:expect/expect.dart';
+import 'package:expect/minitest.dart';
+
+var obj = {
+  'val1': 'hello',
+  'val2': 'there',
+  'val3': {
+    'sub1': 'general kenobi',
+    'sub2': 'you are',
+    'sub3': 'a bold one',
+    'sub4': {
+      'nilval': null,
+      'boolval': false,
+    }
+  },
+  'val4': [
+    'execute',
+    'order',
+    '66',
+    {'number': 33}
+  ]
+};
+
+main() {
+  test('dart to native -> native to dart', () {
+    var toNative = convertDartToNative_Dictionary(obj);
+    var toDart = convertNativeToDart_Dictionary(toNative);
+
+    Expect.deepEquals(obj, toDart);
+  });
+}
diff --git a/tests/lib_2/html/convert_native_to_dart_dictionary_test.dart b/tests/lib_2/html/convert_native_to_dart_dictionary_test.dart
new file mode 100644
index 0000000..b61fea1
--- /dev/null
+++ b/tests/lib_2/html/convert_native_to_dart_dictionary_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html_common';
+import 'package:expect/expect.dart';
+import 'package:expect/minitest.dart';
+
+var obj = {
+  'val1': 'hello',
+  'val2': 'there',
+  'val3': {
+    'sub1': 'general kenobi',
+    'sub2': 'you are',
+    'sub3': 'a bold one',
+    'sub4': {
+      'nilval': null,
+      'boolval': false,
+    }
+  },
+  'val4': [
+    'execute',
+    'order',
+    '66',
+    {'number': 33}
+  ]
+};
+
+main() {
+  test('dart to native -> native to dart', () {
+    var toNative = convertDartToNative_Dictionary(obj);
+    var toDart = convertNativeToDart_Dictionary(toNative);
+
+    Expect.deepEquals(obj, toDart);
+  });
+}
diff --git a/tools/VERSION b/tools/VERSION
index d90890e..57c8cad 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 212
+PRERELEASE 213
 PRERELEASE_PATCH 0
\ No newline at end of file