Version 2.14.0-176.0.dev

Merge commit '4d607fd3b7a20220e72cfbee685ee129f1642128' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 069fea5e1..2d3c48f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -67,6 +67,9 @@
   'recommended' set of lints from `package:lints`. See https://dart.dev/go/core-lints
   for more information about these lints.
 
+* The `dart analyze` command has been extended to support specifying multiple
+  files or directories to analyze; see also https://github.com/dart-lang/sdk/issues/45352.
+
 #### Linter
 
 Updated the Linter to `1.5.0`, which includes:
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index d23309d7..3f29b84 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -1455,6 +1455,11 @@
   }
 
   @override
+  void handleNewAsIdentifier(Token token) {
+    listener?.handleNewAsIdentifier(token);
+  }
+
+  @override
   void handleNoArguments(Token token) {
     listener?.handleNoArguments(token);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
index 6b81262..c6de484 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
@@ -287,6 +287,15 @@
 
   String toString() => _name;
 
+  /// Indicates whether the token `new` in this context should be treated as a
+  /// valid identifier, under the rules of the "constructor tearoff" feature.
+  /// Note that if the feature is disabled, such uses of `new` are still parsed
+  /// as identifiers, however the parser will report an appropriate error; this
+  /// should allow the best possible error recovery in the event that a user
+  /// attempts to use the feature with a language version that doesn't permit
+  /// it.
+  bool get allowsNewAsIdentifier => false;
+
   /// Ensure that the next token is an identifier (or keyword which should be
   /// treated as an identifier) and return that identifier.
   /// Report errors as necessary via [parser].
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
index 5c3963f..4d51a7b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -147,6 +147,9 @@
             isContinuation: true);
 
   @override
+  bool get allowsNewAsIdentifier => isContinuation;
+
+  @override
   Token ensureIdentifier(Token token, Parser parser) {
     Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
@@ -296,6 +299,9 @@
       : super('expressionContinuation', isContinuation: true);
 
   @override
+  bool get allowsNewAsIdentifier => isContinuation;
+
+  @override
   Token ensureIdentifier(Token token, Parser parser) {
     Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
@@ -410,6 +416,9 @@
       : super('fieldInitializer', isContinuation: true);
 
   @override
+  bool get allowsNewAsIdentifier => true;
+
+  @override
   Token ensureIdentifier(Token token, Parser parser) {
     assert(optional('.', token));
     Token identifier = token.next!;
@@ -811,6 +820,9 @@
       : super('operatorName', inDeclaration: true);
 
   @override
+  bool get allowsNewAsIdentifier => isContinuation;
+
+  @override
   Token ensureIdentifier(Token token, Parser parser) {
     Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 9d7de10..4b1f39c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -1742,4 +1742,10 @@
   /// `var x = (f)<int>;`).  The client is responsible for reporting an error if
   /// this occurs.
   void handleTypeArgumentApplication(Token openAngleBracket) {}
+
+  /// A `new` token was found in a place where an identifier was expected, and
+  /// the "constructor tearoffs" feature permits `new` to be used as an
+  /// identifier name.  It is the client's responsibility to report an
+  /// appropriate error if the "constructor tearoffs" feature is not enabled.
+  void handleNewAsIdentifier(Token token) {}
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index b8eb480..64c5be3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -1859,6 +1859,7 @@
   Token parseQualifiedRest(Token token, IdentifierContext context) {
     token = token.next!;
     assert(optional('.', token));
+    _tryRewriteNewToIdentifier(token, context);
     Token period = token;
     token = ensureIdentifier(token, context);
     listener.handleQualified(period);
@@ -2399,6 +2400,7 @@
   Token ensureIdentifier(Token token, IdentifierContext context) {
     // ignore: unnecessary_null_comparison
     assert(context != null);
+    _tryRewriteNewToIdentifier(token, context);
     Token identifier = token.next!;
     if (identifier.kind != IDENTIFIER_TOKEN) {
       identifier = context.ensureIdentifier(token, this);
@@ -2410,6 +2412,43 @@
     return identifier;
   }
 
+  /// Returns `true` if [token] is either an identifier or a `new` token.  This
+  /// can be used to match identifiers in contexts where a constructor name can
+  /// appear, since `new` can be used to refer to the unnamed constructor.
+  bool _isNewOrIdentifier(Token token) {
+    if (token.isIdentifier) return true;
+    if (token.kind == KEYWORD_TOKEN) {
+      final String? value = token.stringValue;
+      if (value == 'new') {
+        // Treat `new` as an identifier so that it can represent an unnamed
+        // constructor.
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// If the token following [token] is a `new` keyword, and [context] is a
+  /// context that permits `new` to be treated as an identifier, rewrites the
+  /// `new` token to an identifier token, and reports the rewritten token to the
+  /// listener.  Otherwise does nothing.
+  void _tryRewriteNewToIdentifier(Token token, IdentifierContext context) {
+    if (!context.allowsNewAsIdentifier) return;
+    Token identifier = token.next!;
+    if (identifier.kind == KEYWORD_TOKEN) {
+      final String? value = token.next!.stringValue;
+      if (value == 'new') {
+        // `new` after `.` is treated as an identifier so that it can represent
+        // an unnamed constructor.
+        Token replacementToken = rewriter.replaceTokenFollowing(
+            token,
+            new StringToken(TokenType.IDENTIFIER, identifier.lexeme,
+                token.next!.charOffset));
+        listener.handleNewAsIdentifier(replacementToken);
+      }
+    }
+  }
+
   /// Checks whether the next token is (directly) an identifier. If this returns
   /// true a call to [ensureIdentifier] will return the next token.
   bool isNextIdentifier(Token token) => token.next?.kind == IDENTIFIER_TOKEN;
@@ -3073,6 +3112,10 @@
       next = token.next!;
       if (optional('.', next)) {
         token = next;
+        Token? afterIdentifier = token.next!.next;
+        if (afterIdentifier != null && optional('(', afterIdentifier)) {
+          _tryRewriteNewToIdentifier(token, IdentifierContext.fieldInitializer);
+        }
         next = token.next!;
         if (next.isIdentifier) {
           token = next;
@@ -3153,6 +3196,8 @@
     Token next = token.next!;
     if (optional('.', next)) {
       token = next;
+      _tryRewriteNewToIdentifier(
+          token, IdentifierContext.constructorReferenceContinuation);
       next = token.next!;
       if (next.kind != IDENTIFIER_TOKEN) {
         next = IdentifierContext.expressionContinuation
@@ -5183,7 +5228,7 @@
             Token afterTypeArguments = endTypeArguments.next!;
             if (optional(".", afterTypeArguments)) {
               Token afterPeriod = afterTypeArguments.next!;
-              if (afterPeriod.isIdentifier &&
+              if (_isNewOrIdentifier(afterPeriod) &&
                   optional('(', afterPeriod.next!)) {
                 return parseImplicitCreationExpression(token, typeArg);
               }
@@ -5283,6 +5328,7 @@
   }
 
   Token parsePrimary(Token token, IdentifierContext context) {
+    _tryRewriteNewToIdentifier(token, context);
     final int kind = token.next!.kind;
     if (kind == IDENTIFIER_TOKEN) {
       return parseSendOrFunctionLiteral(token, context);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index deb2cb7..4f7d07c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -28,6 +28,10 @@
       if (libraryElement != null) {
         _buildSuggestions(request, builder, importElement.namespace,
             prefix: importElement.prefix?.name);
+        if (libraryElement.isDartCore &&
+            request.opType.includeTypeNameSuggestions) {
+          builder.suggestName('Never');
+        }
       }
     }
   }
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 d44cb1a..8ff653b 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
@@ -350,7 +350,8 @@
     if (constructorDeclaration != null) {
       _addSuggestion(Keyword.THIS);
     }
-    if (entity is Token && (entity as Token).type == TokenType.CLOSE_PAREN) {
+    final entity = this.entity;
+    if (entity is Token && entity.type == TokenType.CLOSE_PAREN) {
       _addSuggestion(Keyword.COVARIANT);
       _addSuggestion(Keyword.DYNAMIC);
       _addSuggestion(Keyword.VOID);
@@ -358,8 +359,9 @@
         _addSuggestion(Keyword.REQUIRED);
       }
     } else if (entity is FormalParameter) {
-      var beginToken = (entity as FormalParameter).beginToken;
-      if (request.target.offset == beginToken.end) {
+      var beginToken = entity.beginToken;
+      var offset = request.target.offset;
+      if (beginToken.offset <= offset && offset <= beginToken.end) {
         _addSuggestion(Keyword.COVARIANT);
         _addSuggestion(Keyword.DYNAMIC);
         _addSuggestion(Keyword.VOID);
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 84b0ba8..6792f3e 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -1151,6 +1151,69 @@
     assertSuggestKeywords([Keyword.VAR]);
   }
 
+  Future<void> test_formalParameterList_beforeFunctionType() async {
+    addTestSource('void f(^void Function() g) {}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
+  Future<void> test_formalParameterList_named_init() async {
+    addTestSource('class A { foo({bool bar: ^}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
+  Future<void> test_formalParameterList_named_init2() async {
+    addTestSource('class A { foo({bool bar: f^}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
+  Future<void> test_formalParameterList_noPrefix() async {
+    addTestSource('class A { foo(^) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
+  Future<void> test_formalParameterList_noPrefix_func_parameter() async {
+    addTestSource('class A { foo(^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
+  Future<void> test_formalParameterList_positional_init() async {
+    addTestSource('class A { foo([bool bar = ^]) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
+  Future<void> test_formalParameterList_positional_init2() async {
+    addTestSource('class A { foo([bool bar = f^]) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
+  }
+
+  Future<void> test_formalParameterList_prefix() async {
+    addTestSource('class A { foo(t^) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
+  Future<void> test_formalParameterList_prefix_func_parameter() async {
+    addTestSource('class A { foo(v^ Function(){}) {}}');
+    await computeSuggestions();
+    expect(suggestions, isNotEmpty);
+    assertSuggestKeywords(methodParameter);
+  }
+
   Future<void> test_function_async() async {
     addTestSource('main()^');
     await computeSuggestions();
@@ -2035,62 +2098,6 @@
     assertNoSuggestions();
   }
 
-  Future<void> test_method_param_named_init() async {
-    addTestSource('class A { foo({bool bar: ^}) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
-  }
-
-  Future<void> test_method_param_named_init2() async {
-    addTestSource('class A { foo({bool bar: f^}) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
-  }
-
-  Future<void> test_method_param_noPrefix() async {
-    addTestSource('class A { foo(^) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(methodParameter);
-  }
-
-  Future<void> test_method_param_noPrefix_func_parameter() async {
-    addTestSource('class A { foo(^ Function(){}) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(methodParameter);
-  }
-
-  Future<void> test_method_param_positional_init() async {
-    addTestSource('class A { foo([bool bar = ^]) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
-  }
-
-  Future<void> test_method_param_positional_init2() async {
-    addTestSource('class A { foo([bool bar = f^]) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(EXPRESSION_START_NO_INSTANCE);
-  }
-
-  Future<void> test_method_param_prefix() async {
-    addTestSource('class A { foo(t^) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(methodParameter);
-  }
-
-  Future<void> test_method_param_prefix_func_parameter() async {
-    addTestSource('class A { foo(v^ Function(){}) {}}');
-    await computeSuggestions();
-    expect(suggestions, isNotEmpty);
-    assertSuggestKeywords(methodParameter);
-  }
-
   Future<void> test_method_type_params() async {
     addTestSource('''
 void f<T>() {}
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 62ab3cd..ca754b5 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -971,8 +971,9 @@
         .toList();
     elementKinds.sort((first, second) => first.name.compareTo(second.name));
     for (var kind in elementKinds) {
-      table.add(toRow(
-          targetMetrics.map((metrics) => metrics.groupMrrComputers[kind]!)));
+      table.add(toRow(targetMetrics.map((metrics) =>
+          metrics.groupMrrComputers[kind] ??
+          MeanReciprocalRankComputer(kind.name))));
     }
     if (options.printMrrByLocation) {
       table.add(blankRow);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 12b9301..b514bb3 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -2389,8 +2389,8 @@
   // ```
   static const HintCode SDK_VERSION_NEVER = HintCode(
       'SDK_VERSION_NEVER',
-      "The type 'Never' wasn't supported until version 2.X.0, but this code is "
-          "required to be able to run on earlier versions.",
+      "The type 'Never' wasn't supported until version 2.12.0, but this code "
+          "is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.",
       hasPublishedDocs: true);
 
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 29d755d..2ea4f04 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -3227,6 +3227,20 @@
   }
 
   @override
+  void handleNewAsIdentifier(Token token) {
+    if (!enableConstructorTearoffs) {
+      var feature = ExperimentalFeatures.constructor_tearoffs;
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments(
+            feature.enableString,
+            _versionAsString(ExperimentStatus.currentVersion),
+          ),
+          token,
+          token);
+    }
+  }
+
+  @override
   void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
     debugEvent("NoConstructorReferenceContinuationAfterTypeArguments");
 
diff --git a/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart b/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart
new file mode 100644
index 0000000..9ce08a4
--- /dev/null
+++ b/pkg/analyzer/test/generated/new_as_identifier_parser_test.dart
@@ -0,0 +1,442 @@
+// 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NewAsIdentifierParserTest);
+  });
+}
+
+/// Tests exercising the fasta parser's handling of generic instantiations.
+@reflectiveTest
+class NewAsIdentifierParserTest extends FastaParserTestCase {
+  void test_constructor_field_initializer() {
+    // Even though `C() : this.new();` is allowed, `C() : this.new = ...;`
+    // should not be.
+    parseCompilationUnit(
+        '''
+class C {
+  C() : this.new = null;
+}
+''',
+        featureSet: constructorTearoffs,
+        errors: [
+          expectedError(
+              ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 18, 4),
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 3),
+          expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 23, 3),
+          expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 23, 3),
+          expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 27, 1),
+          expectedError(ParserErrorCode.INVALID_OPERATOR, 27, 1),
+          expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 27, 1),
+          expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 4),
+          expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 29, 4),
+          expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 33, 1),
+        ]);
+  }
+
+  void test_constructor_invocation_const() {
+    var instanceCreationExpression =
+        parseExpression('const C.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    // Parsing treats `new` as an identifier, so `D.new` is classified as a
+    // type.  Resolution will change the type to `D` and the name to `new` if
+    // appropriate.
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'C');
+    expect(typeName.identifier.name, 'new');
+    expect(constructorName.type.typeArguments, isNull);
+    expect(constructorName.name, isNull);
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_const_generic() {
+    var instanceCreationExpression =
+        parseExpression('const C<int>.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as SimpleIdentifier;
+    expect(typeName.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_const_prefixed() {
+    var instanceCreationExpression =
+        parseExpression('const prefix.C.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'C');
+    expect(constructorName.type.typeArguments, isNull);
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_const_prefixed_generic() {
+    var instanceCreationExpression = parseExpression(
+        'const prefix.C<int>.new()',
+        featureSet: constructorTearoffs) as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_explicit() {
+    var instanceCreationExpression =
+        parseExpression('new C.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    // Parsing treats `new` as an identifier, so `D.new` is classified as a
+    // type.  Resolution will change the type to `D` and the name to `new` if
+    // appropriate.
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'C');
+    expect(typeName.identifier.name, 'new');
+    expect(constructorName.type.typeArguments, isNull);
+    expect(constructorName.name, isNull);
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_explicit_generic() {
+    var instanceCreationExpression =
+        parseExpression('new C<int>.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as SimpleIdentifier;
+    expect(typeName.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_explicit_prefixed() {
+    var instanceCreationExpression =
+        parseExpression('new prefix.C.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'C');
+    expect(constructorName.type.typeArguments, isNull);
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_explicit_prefixed_generic() {
+    var instanceCreationExpression = parseExpression('new prefix.C<int>.new()',
+        featureSet: constructorTearoffs) as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_implicit() {
+    var methodInvocation =
+        parseExpression('C.new()', featureSet: constructorTearoffs)
+            as MethodInvocation;
+    var target = methodInvocation.target as SimpleIdentifier;
+    expect(target.name, 'C');
+    expect(methodInvocation.methodName.name, 'new');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_implicit_generic() {
+    var instanceCreationExpression =
+        parseExpression('C<int>.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as SimpleIdentifier;
+    expect(typeName.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_implicit_prefixed() {
+    var methodInvocation =
+        parseExpression('prefix.C.new()', featureSet: constructorTearoffs)
+            as MethodInvocation;
+    var target = methodInvocation.target as PrefixedIdentifier;
+    expect(target.prefix.name, 'prefix');
+    expect(target.identifier.name, 'C');
+    expect(methodInvocation.methodName.name, 'new');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_constructor_invocation_implicit_prefixed_generic() {
+    var instanceCreationExpression =
+        parseExpression('prefix.C<int>.new()', featureSet: constructorTearoffs)
+            as InstanceCreationExpression;
+    var constructorName = instanceCreationExpression.constructorName;
+    var typeName = constructorName.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'C');
+    expect(constructorName.type.typeArguments!.arguments, hasLength(1));
+    expect(constructorName.name!.name, 'new');
+    expect(instanceCreationExpression.argumentList, isNotNull);
+  }
+
+  void test_constructor_name() {
+    var unit = parseCompilationUnit('''
+class C {
+  C.new();
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.name!.name, 'new');
+  }
+
+  void test_constructor_name_factory() {
+    var unit = parseCompilationUnit('''
+class C {
+  factory C.new() => C._();
+  C._();
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members[0] as ConstructorDeclaration;
+    expect(constructorDeclaration.name!.name, 'new');
+  }
+
+  void test_constructor_tearoff() {
+    var prefixedIdentifier =
+        parseExpression('C.new', featureSet: constructorTearoffs)
+            as PrefixedIdentifier;
+    expect(prefixedIdentifier.prefix.name, 'C');
+    expect(prefixedIdentifier.identifier.name, 'new');
+  }
+
+  void test_constructor_tearoff_generic() {
+    var propertyAccess =
+        parseExpression('C<int>.new', featureSet: constructorTearoffs)
+            as PropertyAccess;
+    var target = propertyAccess.target as FunctionReference;
+    var className = target.function as SimpleIdentifier;
+    expect(className.name, 'C');
+    expect(target.typeArguments, isNotNull);
+    expect(propertyAccess.propertyName.name, 'new');
+  }
+
+  void test_constructor_tearoff_generic_method_invocation() {
+    var methodInvocation = parseExpression('C<int>.new.toString()',
+        featureSet: constructorTearoffs) as MethodInvocation;
+    var target = methodInvocation.target as PropertyAccess;
+    var functionReference = target.target as FunctionReference;
+    var className = functionReference.function as SimpleIdentifier;
+    expect(className.name, 'C');
+    expect(functionReference.typeArguments, isNotNull);
+    expect(target.propertyName.name, 'new');
+    expect(methodInvocation.methodName.name, 'toString');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_constructor_tearoff_method_invocation() {
+    var methodInvocation =
+        parseExpression('C.new.toString()', featureSet: constructorTearoffs)
+            as MethodInvocation;
+    var target = methodInvocation.target as PrefixedIdentifier;
+    expect(target.prefix.name, 'C');
+    expect(target.identifier.name, 'new');
+    expect(methodInvocation.methodName.name, 'toString');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_constructor_tearoff_prefixed() {
+    var propertyAccess =
+        parseExpression('prefix.C.new', featureSet: constructorTearoffs)
+            as PropertyAccess;
+    var target = propertyAccess.target as PrefixedIdentifier;
+    expect(target.prefix.name, 'prefix');
+    expect(target.identifier.name, 'C');
+    expect(propertyAccess.propertyName.name, 'new');
+  }
+
+  void test_constructor_tearoff_prefixed_generic() {
+    var propertyAccess =
+        parseExpression('prefix.C<int>.new', featureSet: constructorTearoffs)
+            as PropertyAccess;
+    var target = propertyAccess.target as FunctionReference;
+    var className = target.function as PrefixedIdentifier;
+    expect(className.prefix.name, 'prefix');
+    expect(className.identifier.name, 'C');
+    expect(target.typeArguments, isNotNull);
+    expect(propertyAccess.propertyName.name, 'new');
+  }
+
+  void test_constructor_tearoff_prefixed_generic_method_invocation() {
+    var methodInvocation = parseExpression('prefix.C<int>.new.toString()',
+        featureSet: constructorTearoffs) as MethodInvocation;
+    var target = methodInvocation.target as PropertyAccess;
+    var functionReference = target.target as FunctionReference;
+    var className = functionReference.function as PrefixedIdentifier;
+    expect(className.prefix.name, 'prefix');
+    expect(className.identifier.name, 'C');
+    expect(functionReference.typeArguments, isNotNull);
+    expect(target.propertyName.name, 'new');
+    expect(methodInvocation.methodName.name, 'toString');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_constructor_tearoff_prefixed_method_invocation() {
+    var methodInvocation = parseExpression('prefix.C.new.toString()',
+        featureSet: constructorTearoffs) as MethodInvocation;
+    var target = methodInvocation.target as PropertyAccess;
+    var prefixedIdentifier = target.target as PrefixedIdentifier;
+    expect(prefixedIdentifier.prefix.name, 'prefix');
+    expect(prefixedIdentifier.identifier.name, 'C');
+    expect(target.propertyName.name, 'new');
+    expect(methodInvocation.methodName.name, 'toString');
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_disabled() {
+    var unit = parseCompilationUnit(
+        '''
+class C {
+  C.new();
+}
+''',
+        featureSet: preConstructorTearoffs,
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 3),
+        ]);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.name!.name, 'new');
+  }
+
+  void test_factory_redirection() {
+    var unit = parseCompilationUnit('''
+class C {
+  factory C() = D.new;
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.initializers, isEmpty);
+    // Parsing treats `new` as an identifier, so `D.new` is classified as a
+    // type.  Resolution will change the type to `D` and the name to `new` if
+    // appropriate.
+    var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
+    var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'D');
+    expect(typeName.identifier.name, 'new');
+    expect(redirectedConstructor.type.typeArguments, isNull);
+    expect(redirectedConstructor.name, isNull);
+  }
+
+  void test_factory_redirection_generic() {
+    var unit = parseCompilationUnit('''
+class C {
+  factory C() = D<int>.new;
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.initializers, isEmpty);
+    var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
+    var typeName = redirectedConstructor.type.name as SimpleIdentifier;
+    expect(typeName.name, 'D');
+    expect(redirectedConstructor.type.typeArguments!.arguments, hasLength(1));
+    expect(redirectedConstructor.name!.name, 'new');
+  }
+
+  void test_factory_redirection_prefixed() {
+    var unit = parseCompilationUnit('''
+class C {
+  factory C() = prefix.D.new;
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.initializers, isEmpty);
+    var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
+    var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'D');
+    expect(redirectedConstructor.type.typeArguments, isNull);
+    expect(redirectedConstructor.name!.name, 'new');
+  }
+
+  void test_factory_redirection_prefixed_generic() {
+    var unit = parseCompilationUnit('''
+class C {
+  factory C() = prefix.D<int>.new;
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.initializers, isEmpty);
+    var redirectedConstructor = constructorDeclaration.redirectedConstructor!;
+    var typeName = redirectedConstructor.type.name as PrefixedIdentifier;
+    expect(typeName.prefix.name, 'prefix');
+    expect(typeName.identifier.name, 'D');
+    expect(redirectedConstructor.type.typeArguments!.arguments, hasLength(1));
+    expect(redirectedConstructor.name!.name, 'new');
+  }
+
+  void test_super_invocation() {
+    var unit = parseCompilationUnit('''
+class C extends B {
+  C() : super.new();
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members.single as ConstructorDeclaration;
+    expect(constructorDeclaration.redirectedConstructor, isNull);
+    var superConstructorInvocation = constructorDeclaration.initializers.single
+        as SuperConstructorInvocation;
+    expect(superConstructorInvocation.constructorName!.name, 'new');
+  }
+
+  void test_this_redirection() {
+    var unit = parseCompilationUnit('''
+class C {
+  C.named() : this.new();
+  C();
+}
+''', featureSet: constructorTearoffs);
+    var classDeclaration = unit.declarations.single as ClassDeclaration;
+    var constructorDeclaration =
+        classDeclaration.members[0] as ConstructorDeclaration;
+    expect(constructorDeclaration.redirectedConstructor, isNull);
+    var redirectingConstructorInvocation = constructorDeclaration
+        .initializers.single as RedirectingConstructorInvocation;
+    expect(redirectingConstructorInvocation.constructorName!.name, 'new');
+  }
+}
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index efc1a0e..2d48f18 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -22,6 +22,7 @@
 import 'issues_test.dart' as issues;
 import 'java_core_test.dart' as java_core_test;
 import 'java_io_test.dart' as java_io_test;
+import 'new_as_identifier_parser_test.dart' as new_as_identifier_parser;
 import 'nnbd_parser_test.dart' as nnbd_parser;
 import 'non_error_parser_test.dart' as non_error_parser;
 import 'non_error_resolver_test.dart' as non_error_resolver;
@@ -63,6 +64,7 @@
     issues.main();
     java_core_test.main();
     java_io_test.main();
+    new_as_identifier_parser.main();
     nnbd_parser.main();
     non_error_parser.main();
     non_error_resolver.main();
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 44cee98..5ae038a 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -11169,7 +11169,7 @@
 
 ### sdk_version_never
 
-_The type 'Never' wasn't supported until version 2.X.0, but this code is
+_The type 'Never' wasn't supported until version 2.12.0, but this code is
 required to be able to run on earlier versions._
 
 #### Description
diff --git a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
index 5398071..572d468 100644
--- a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
+++ b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
@@ -9,6 +9,7 @@
 import '../js/js.dart' as js;
 import '../serialization/serialization.dart';
 import '../util/util.dart';
+import '../js_emitter/model.dart' show Fragment;
 
 import 'namer.dart';
 
@@ -17,7 +18,7 @@
 // for the entity referenced in the DeferredHolderExpression.
 enum DeferredHolderExpressionKind {
   globalObjectForStaticState,
-  globalObjectForConstants,
+  globalObjectForConstant,
   globalObjectForLibrary,
   globalObjectForClass,
   globalObjectForMember,
@@ -34,19 +35,15 @@
   static const String tag = 'deferred-holder-expression';
 
   final DeferredHolderExpressionKind kind;
-  final Entity entity;
+  final Object data;
   js.Expression _value;
 
   @override
   final js.JavaScriptNodeSourceInformation sourceInformation;
 
-  DeferredHolderExpression(this.kind, this.entity) : sourceInformation = null;
+  DeferredHolderExpression(this.kind, this.data) : sourceInformation = null;
   DeferredHolderExpression._(
-      this.kind, this.entity, this._value, this.sourceInformation);
-  factory DeferredHolderExpression.forConstants() {
-    return DeferredHolderExpression(
-        DeferredHolderExpressionKind.globalObjectForConstants, null);
-  }
+      this.kind, this.data, this._value, this.sourceInformation);
 
   factory DeferredHolderExpression.forStaticState() {
     return DeferredHolderExpression(
@@ -56,24 +53,26 @@
   factory DeferredHolderExpression.readFromDataSource(DataSource source) {
     source.begin(tag);
     var kind = source.readEnum(DeferredHolderExpressionKind.values);
-    Entity entity;
+    Object data;
     switch (kind) {
       case DeferredHolderExpressionKind.globalObjectForLibrary:
-        entity = source.readLibrary();
+        data = source.readLibrary();
         break;
       case DeferredHolderExpressionKind.globalObjectForClass:
-        entity = source.readClass();
+        data = source.readClass();
         break;
       case DeferredHolderExpressionKind.globalObjectForMember:
-        entity = source.readMember();
+        data = source.readMember();
+        break;
+      case DeferredHolderExpressionKind.globalObjectForConstant:
+        data = source.readConstant();
         break;
       case DeferredHolderExpressionKind.globalObjectForStaticState:
-      case DeferredHolderExpressionKind.globalObjectForConstants:
         // no entity.
         break;
     }
     source.end(tag);
-    return DeferredHolderExpression(kind, entity);
+    return DeferredHolderExpression(kind, data);
   }
 
   void writeToDataSink(DataSink sink) {
@@ -81,16 +80,18 @@
     sink.writeEnum(kind);
     switch (kind) {
       case DeferredHolderExpressionKind.globalObjectForLibrary:
-        sink.writeLibrary(entity);
+        sink.writeLibrary(data);
         break;
       case DeferredHolderExpressionKind.globalObjectForClass:
-        sink.writeClass(entity);
+        sink.writeClass(data);
         break;
       case DeferredHolderExpressionKind.globalObjectForMember:
-        sink.writeMember(entity);
+        sink.writeMember(data);
+        break;
+      case DeferredHolderExpressionKind.globalObjectForConstant:
+        sink.writeConstant(data);
         break;
       case DeferredHolderExpressionKind.globalObjectForStaticState:
-      case DeferredHolderExpressionKind.globalObjectForConstants:
         // no entity.
         break;
     }
@@ -116,8 +117,7 @@
       js.JavaScriptNodeSourceInformation newSourceInformation) {
     if (newSourceInformation == sourceInformation) return this;
     if (newSourceInformation == null) return this;
-    return DeferredHolderExpression._(
-        kind, entity, _value, newSourceInformation);
+    return DeferredHolderExpression._(kind, data, _value, newSourceInformation);
   }
 
   @override
@@ -125,7 +125,7 @@
 
   @override
   int get hashCode {
-    return Hashing.objectsHash(kind, entity);
+    return Hashing.objectsHash(kind, data);
   }
 
   @override
@@ -133,13 +133,13 @@
     if (identical(this, other)) return true;
     return other is DeferredHolderExpression &&
         kind == other.kind &&
-        entity == other.entity;
+        data == other.data;
   }
 
   @override
   String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write('DeferredHolderExpression(kind=$kind,entity=$entity,');
+    StringBuffer sb = StringBuffer();
+    sb.write('DeferredHolderExpression(kind=$kind,data=$data,');
     sb.write('value=$_value)');
     return sb.toString();
   }
@@ -205,40 +205,43 @@
 
   @override
   String toString() {
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = StringBuffer();
     sb.write('DeferredHolderParameter(name=$_name)');
     return sb.toString();
   }
 }
 
 enum DeferredHolderResourceKind {
-  declaration,
-  update,
+  mainFragment,
+  deferredFragment,
 }
 
 /// A [DeferredHolderResource] is a deferred JavaScript statement determined by
-/// the finalization of holders. It is the injection point for data or
-/// code to holders. The actual [Statement] contained with the
+/// the finalization of holders. Each fragment contains one
+/// [DeferredHolderResource]. The actual [Statement] contained with the
 /// [DeferredHolderResource] will be determined by the
 /// [DeferredHolderResourceKind]. These [Statement]s differ considerably
-/// depending on where they are used in the AST. This class does not support
-/// serialization.
+/// depending on where they are used in the AST. This class is created by the
+/// fragment emitter so does not need to support serialization.
 class DeferredHolderResource extends js.DeferredStatement
     implements js.AstContainer {
   DeferredHolderResourceKind kind;
+  // Each resource has a distinct name.
+  String name;
+  List<Fragment> fragments;
   Map<Entity, List<js.Property>> holderCode;
-  bool initializeEmptyHolders;
   js.Statement _statement;
 
   @override
   final js.JavaScriptNodeSourceInformation sourceInformation;
 
-  DeferredHolderResource(this.kind,
-      {this.holderCode: const {}, this.initializeEmptyHolders: false})
+  DeferredHolderResource(this.kind, this.name, this.fragments, this.holderCode)
       : sourceInformation = null;
 
-  DeferredHolderResource._(this.kind, this.holderCode,
-      this.initializeEmptyHolders, this._statement, this.sourceInformation);
+  DeferredHolderResource._(this.kind, this.name, this.fragments,
+      this.holderCode, this._statement, this.sourceInformation);
+
+  bool get isMainFragment => kind == DeferredHolderResourceKind.mainFragment;
 
   set statement(js.Statement statement) {
     assert(!isFinalized && statement != null);
@@ -259,7 +262,7 @@
       js.JavaScriptNodeSourceInformation newSourceInformation) {
     if (newSourceInformation == sourceInformation) return this;
     if (newSourceInformation == null) return this;
-    return DeferredHolderResource._(kind, holderCode, initializeEmptyHolders,
+    return DeferredHolderResource._(kind, this.name, this.fragments, holderCode,
         _statement, newSourceInformation);
   }
 
@@ -277,41 +280,87 @@
   }
 }
 
+const String mainResourceName = 'MAIN';
+
 abstract class DeferredHolderExpressionFinalizer {
   /// Collects DeferredHolderExpressions from the JavaScript
-  /// AST [code];
-  void addCode(js.Node code);
+  /// AST [code] and associates it with [resourceName].
+  void addCode(String resourceName, js.Node code);
 
   /// Performs analysis on all collected DeferredHolderExpression nodes
   /// finalizes the values to expressions to access the holders.
   void finalize();
 }
 
+/// An abstraction representing a [Holder] object, which will contain some
+/// portion of the programs code.
+class Holder {
+  final String name;
+  final Map<String, int> refCountPerResource = {};
+  final Map<String, List<js.Property>> propertiesPerResource = {};
+  int _index;
+  int _hashCode;
+
+  Holder(this.name);
+
+  int refCount(String resource) => refCountPerResource[resource];
+
+  void registerUse(String resource) {
+    refCountPerResource.update(resource, (count) => count + 1,
+        ifAbsent: () => 0);
+  }
+
+  void registerUpdate(String resource, List<js.Property> properties) {
+    (propertiesPerResource[resource] ??= []).addAll(properties);
+    registerUse(resource);
+  }
+
+  int get index {
+    assert(_index != null);
+    return _index;
+  }
+
+  set index(int newIndex) {
+    assert(_index == null);
+    _index = newIndex;
+  }
+
+  @override
+  bool operator ==(that) {
+    return that is Holder && name == that.name;
+  }
+
+  @override
+  int get hashCode {
+    return _hashCode ??= Hashing.objectsHash(name);
+  }
+}
+
 /// [DeferredHolderExpressionFinalizerImpl] finalizes
 /// [DeferredHolderExpression]s, [DeferredHolderParameter]s,
 /// [DeferredHolderResource]s, [DeferredHolderResourceExpression]s.
 class DeferredHolderExpressionFinalizerImpl
     implements DeferredHolderExpressionFinalizer {
   _DeferredHolderExpressionCollectorVisitor _visitor;
-  final List<DeferredHolderExpression> holderReferences = [];
+  final Map<String, List<DeferredHolderExpression>> holderReferences = {};
   final List<DeferredHolderParameter> holderParameters = [];
   final List<DeferredHolderResource> holderResources = [];
-  final Set<String> _uniqueHolders = {};
-  final List<String> _holders = [];
-  final Map<Entity, String> _entityMap = {};
+  final Map<String, Set<Holder>> holdersPerResource = {};
+  final Map<String, Holder> holderMap = {};
   final JCommonElements _commonElements;
+  DeferredHolderResource mainHolderResource;
 
   DeferredHolderExpressionFinalizerImpl(this._commonElements) {
     _visitor = _DeferredHolderExpressionCollectorVisitor(this);
   }
 
   @override
-  void addCode(js.Node code) {
-    code.accept(_visitor);
+  void addCode(String resourceName, js.Node code) {
+    _visitor.setResourceNameAndVisit(resourceName, code);
   }
 
   final List<String> userGlobalObjects =
-      new List.from(Namer.reservedGlobalObjectNames)
+      List.from(Namer.reservedGlobalObjectNames)
         ..remove('C')
         ..remove('H')
         ..remove('J')
@@ -319,7 +368,7 @@
         ..remove('W');
 
   /// Returns the [reservedGlobalObjectNames] for [library].
-  String globalObjectForLibrary(LibraryEntity library) {
+  String globalObjectNameForLibrary(LibraryEntity library) {
     if (library == _commonElements.interceptorsLibrary) return 'J';
     Uri uri = library.canonicalUri;
     if (uri.scheme == 'dart') {
@@ -341,236 +390,285 @@
     return element.isField;
   }
 
-  String globalObjectForMember(MemberEntity entity) {
+  String globalObjectNameForMember(MemberEntity entity) {
     if (_isPropertyOfStaticStateHolder(entity)) {
-      return globalObjectForStaticState();
+      return globalObjectNameForStaticState();
     } else {
-      return globalObjectForLibrary(entity.library);
+      return globalObjectNameForLibrary(entity.library);
     }
   }
 
-  String globalObjectForClass(ClassEntity entity) {
-    return globalObjectForLibrary(entity.library);
+  String globalObjectNameForClass(ClassEntity entity) {
+    return globalObjectNameForLibrary(entity.library);
   }
 
-  String globalObjectForStaticState() => r'$';
+  final Holder globalObjectForStaticState =
+      Holder(globalObjectNameForStaticState());
 
-  String globalObjectForConstants() => 'C';
+  static String globalObjectNameForStaticState() => r'$';
 
-  String globalObjectForEntity(Entity entity) {
+  String globalObjectNameForConstants() => 'C';
+
+  String globalObjectNameForEntity(Entity entity) {
     if (entity is MemberEntity) {
-      return globalObjectForMember(entity);
+      return globalObjectNameForMember(entity);
     } else if (entity is ClassEntity) {
-      return globalObjectForLibrary(entity.library);
+      return globalObjectNameForLibrary(entity.library);
     } else {
       assert(entity is LibraryEntity);
-      return globalObjectForLibrary(entity);
+      return globalObjectNameForLibrary(entity);
     }
   }
 
-  /// Registers an [Entity] with a specific [holder].
-  void registerHolderUse(String holder, Entity entity) {
-    if (_uniqueHolders.add(holder)) _holders.add(holder);
-    if (entity != null) {
-      assert(!_entityMap.containsKey(entity) || _entityMap[entity] == holder);
-      _entityMap[entity] = holder;
+  Holder holderNameToHolder(String holderKey) {
+    if (holderKey == globalObjectNameForStaticState()) {
+      return globalObjectForStaticState;
+    } else {
+      return holderMap[holderKey];
     }
   }
 
-  /// Returns a global object for a given [Entity] based on the
+  Holder globalObjectForEntity(Entity entity) {
+    return holderNameToHolder(globalObjectNameForEntity(entity));
+  }
+
+  /// Registers a [holder] use within a given [resource], if [properties] are
+  /// provided then it is assumed this is an update to a holder.
+  void registerHolderUseOrUpdate(String resourceName, String holderName,
+      {List<js.Property> properties}) {
+    // For simplicity, we don't currently track the static state holder per
+    // resource.
+    if (holderName == globalObjectNameForStaticState()) return;
+    Holder holder = holderMap[holderName] ??= Holder(holderName);
+    if (properties == null) {
+      holder.registerUse(resourceName);
+    } else {
+      holder.registerUpdate(resourceName, properties);
+    }
+    (holdersPerResource[resourceName] ??= {}).add(holder);
+  }
+
+  /// Returns a key to a global object for a given [Object] based on the
   /// [DeferredHolderExpressionKind].
-  String kindToHolder(DeferredHolderExpressionKind kind, Entity entity) {
+  String kindToHolderName(DeferredHolderExpressionKind kind, Object data) {
     switch (kind) {
       case DeferredHolderExpressionKind.globalObjectForLibrary:
-        return globalObjectForLibrary(entity);
+        return globalObjectNameForLibrary(data);
       case DeferredHolderExpressionKind.globalObjectForClass:
-        return globalObjectForClass(entity);
+        return globalObjectNameForClass(data);
       case DeferredHolderExpressionKind.globalObjectForMember:
-        return globalObjectForMember(entity);
-      case DeferredHolderExpressionKind.globalObjectForConstants:
-        return globalObjectForConstants();
+        return globalObjectNameForMember(data);
+      case DeferredHolderExpressionKind.globalObjectForConstant:
+        return globalObjectNameForConstants();
       case DeferredHolderExpressionKind.globalObjectForStaticState:
-        return globalObjectForStaticState();
+        return globalObjectNameForStaticState();
     }
     throw UnsupportedError("Unreachable");
   }
 
-  /// Finalizes [DeferredHolderExpression]s [DeferredHolderParameter]s.
-  void finalizeReferences() {
-    // Finalize [DeferredHolderExpression]s and registers holder usage.
-    for (var reference in holderReferences) {
+  /// Returns a global object for a given [Object] based on the
+  /// [DeferredHolderExpressionKind].
+  Holder kindToHolder(DeferredHolderExpressionKind kind, Object data) {
+    return holderNameToHolder(kindToHolderName(kind, data));
+  }
+
+  /// Finalizes [DeferredHolderParameter]s.
+  void finalizeParameters() {
+    for (var parameter in holderParameters) {
+      if (parameter.isFinalized) continue;
+      parameter.name = globalObjectNameForStaticState();
+    }
+  }
+
+  /// Finalizes all of the [DeferredHolderExpression]s associated with a
+  /// [DeferredHolderResource].
+  void finalizeReferences(DeferredHolderResource resource) {
+    if (!holderReferences.containsKey(resource.name)) return;
+    for (var reference in holderReferences[resource.name]) {
       if (reference.isFinalized) continue;
-      Entity entity = reference.entity;
-      String holder = kindToHolder(reference.kind, entity);
+      String holder = kindToHolder(reference.kind, reference.data).name;
       js.Expression value = js.VariableUse(holder);
-      registerHolderUse(holder, entity);
       reference.value =
           value.withSourceInformation(reference.sourceInformation);
     }
-
-    // Finalize [DeferredHolderParameter]s.
-    for (var parameter in holderParameters) {
-      if (parameter.isFinalized) continue;
-      parameter.name = globalObjectForStaticState();
-    }
   }
 
-  /// Registers all of the holders used by a given [DeferredHolderResource].
-  void registerHolders(DeferredHolderResource resource) {
-    for (var entity in resource.holderCode.keys) {
-      var holder = globalObjectForEntity(entity);
-      registerHolderUse(holder, entity);
-    }
-  }
-
-  /// Returns a [List<String>] containing all of the holders except the static
-  /// state holder.
-  List<String> get nonStaticStateHolders {
-    return _holders
-        .where((holder) => holder != globalObjectForStaticState())
-        .toList(growable: false);
-  }
-
-  /// Generates code to declare holders.
-  HolderCode declareHolders(DeferredHolderResource resource) {
-    // Collect all holders except the static state holder. Then, create a map of
-    // holder to list of properties which are associated with that holder, but
-    // only with respect to a given [DeferredHolderResource]. Each fragment will
-    // have its own [DeferredHolderResource] and associated code.
-    Map<String, List<js.Property>> codePerHolder = {};
-    final holders = nonStaticStateHolders;
-    for (var holder in holders) {
-      codePerHolder[holder] = [];
+  /// Registers all of the holders used in the entire program.
+  void registerHolders() {
+    // Register all holders used in all [DeferredHolderResource]s.
+    for (var resource in holderResources) {
+      resource.holderCode.forEach((entity, properties) {
+        String holderName = globalObjectNameForEntity(entity);
+        registerHolderUseOrUpdate(resource.name, holderName,
+            properties: properties);
+      });
     }
 
-    final holderCode = resource.holderCode;
-    holderCode.forEach((entity, properties) {
-      assert(_entityMap.containsKey(entity));
-      var holder = _entityMap[entity];
-      assert(codePerHolder.containsKey(holder));
-      codePerHolder[holder].addAll(properties);
+    // Register all holders used in [DeferredHolderReference]s.
+    holderReferences.forEach((resource, references) {
+      for (var reference in references) {
+        String holderName = kindToHolderName(reference.kind, reference.data);
+        registerHolderUseOrUpdate(resource, holderName);
+      }
     });
+  }
 
-    // Create holder initialization code based on the [codePerHolder]. If there
-    // are no properties associated with a given holder in this specific
-    // [DeferredHolderResource] then it will be omitted. However, in some cases,
-    // i.e. the main output unit, we still want to declare the holder with an
-    // empty object literal which will be filled in later by another
-    // [DeferredHolderResource], i.e. in a specific deferred fragment.
-    // The generated code looks like this:
+  /// Returns an [Iterable<Holder>] containing all of the holders used within a
+  /// given [DeferredHolderResource]except the static state holder (if any).
+  Iterable<Holder> nonStaticStateHolders(DeferredHolderResource resource) {
+    return holdersPerResource[resource.name] ?? [];
+  }
+
+  /// Returns an [Iterable<Holder>] containing all of the holders used within a
+  /// given [DeferredHolderResource] except the static state holder.
+  Iterable<Holder> get allNonStaticStateHolders {
+    return holderMap.values;
+  }
+
+  /// Generates code to declare holders for a given [resourceName].
+  HolderInitCode declareHolders(String resourceName, Iterable<Holder> holders,
+      {bool initializeEmptyHolders = false}) {
+    // Create holder initialization code. If there are no properties
+    // associated with a given holder in this specific [DeferredHolderResource]
+    // then it will be omitted. However, in some cases, i.e. the main output
+    // unit, we still want to declare the holder with an empty object literal
+    // which will be filled in later by another [DeferredHolderResource], i.e.
+    // in a specific deferred fragment. The generated code looks like this:
     //
     //    {
     //      var H = {...}, ..., G = {...};
-    //      var holders = [ H, ..., G ]; // Main unit only.
     //    }
 
-    List<String> activeHolders = [];
+    List<Holder> activeHolders = [];
     List<js.VariableInitialization> holderInitializations = [];
     for (var holder in holders) {
-      List<js.Property> properties = codePerHolder[holder];
+      var holderName = holder.name;
+      List<js.Property> properties =
+          holder.propertiesPerResource[resourceName] ?? [];
       if (properties.isEmpty) {
         holderInitializations.add(js.VariableInitialization(
-            js.VariableDeclaration(holder, allowRename: false),
-            resource.initializeEmptyHolders
-                ? js.ObjectInitializer(properties)
-                : null));
+            js.VariableDeclaration(holderName, allowRename: false),
+            initializeEmptyHolders ? js.ObjectInitializer(properties) : null));
       } else {
         activeHolders.add(holder);
         holderInitializations.add(js.VariableInitialization(
-            js.VariableDeclaration(holder, allowRename: false),
+            js.VariableDeclaration(holderName, allowRename: false),
             js.ObjectInitializer(properties)));
       }
     }
 
-    List<js.Statement> statements = [];
-    statements.add(js.ExpressionStatement(js.VariableDeclarationList(
-        holderInitializations,
-        indentSplits: false)));
-    if (resource.initializeEmptyHolders) {
-      statements.add(js.js.statement(
-          'var holders = #',
-          js.ArrayInitializer(holders
-              .map((holder) => js.VariableUse(holder))
-              .toList(growable: false))));
-    }
-    return HolderCode(activeHolders, statements);
+    // Create statement to initialize holders.
+    var initStatement = js.ExpressionStatement(
+        js.VariableDeclarationList(holderInitializations, indentSplits: false));
+    return HolderInitCode(holders, activeHolders, initStatement);
   }
 
   /// Finalizes [resource] to code that updates holders. [resource] must be in
   /// the AST of a deferred fragment.
   void updateHolders(DeferredHolderResource resource) {
-    // Declare holders.
-    final holderCode = declareHolders(resource);
+    final holderCode =
+        declareHolders(resource.name, nonStaticStateHolders(resource));
 
     // Set names if necessary on deferred holders list.
     js.Expression deferredHoldersList = js.ArrayInitializer(holderCode
         .activeHolders
-        .map((holder) => js.js("#", holder))
+        .map((holder) => js.js("#", holder.name))
         .toList(growable: false));
     js.Statement setNames = js.js.statement(
         'hunkHelpers.setFunctionNamesIfNecessary(#deferredHoldersList)',
         {'deferredHoldersList': deferredHoldersList});
 
     // Update holder assignments.
-    final holders = nonStaticStateHolders;
-    List<js.Statement> updateHolderAssignments = [setNames];
-    for (int i = 0; i < holders.length; i++) {
-      var holder = holders[i];
+    List<js.Statement> updateHolderAssignments = [
+      holderCode.statement,
+      setNames
+    ];
+    for (var holder in holderCode.allHolders) {
+      var holderName = holder.name;
+      var holderIndex = js.number(holder.index);
       if (holderCode.activeHolders.contains(holder)) {
         updateHolderAssignments.add(js.js.statement(
             '#holder = hunkHelpers.updateHolder(holdersList[#index], #holder)',
-            {'index': js.number(i), 'holder': js.VariableUse(holder)}));
+            {'index': holderIndex, 'holder': js.VariableUse(holderName)}));
       } else {
         // TODO(sra): Change declaration followed by assignments to declarations
         // with initialization.
         updateHolderAssignments.add(js.js.statement(
             '#holder = holdersList[#index]',
-            {'index': js.number(i), 'holder': js.VariableUse(holder)}));
+            {'index': holderIndex, 'holder': js.VariableUse(holderName)}));
       }
     }
 
     // Create a single block of all statements.
-    List<js.Statement> statements = holderCode.statements
-        .followedBy(updateHolderAssignments)
-        .toList(growable: false);
-    resource.statement = js.Block(statements);
+    resource.statement = js.Block(updateHolderAssignments);
   }
 
-  /// Allocates all [DeferredHolderResource]s and
-  /// [DeferredHolderResourceExpression]s.
-  void allocateResources() {
-    // First ensure all holders used in all [DeferredHolderResource]s have been
-    // allocated.
-    for (var resource in holderResources) {
-      registerHolders(resource);
+  /// Declares all holders in the [DeferredHolderResource] representing the main
+  /// fragment.
+  void declareHoldersInMainResource() {
+    // Declare holders in main output unit.
+    var holders = allNonStaticStateHolders;
+    var holderCode = declareHolders(mainHolderResource.name, holders,
+        initializeEmptyHolders: true);
+
+    // Create holder uses and init holder indices.
+    List<js.VariableUse> holderUses = [];
+    int i = 0;
+    for (var holder in holders) {
+      holder.index = i++;
+      holderUses.add(js.VariableUse(holder.name));
     }
-    _holders.sort();
+
+    // Create holders array statement.
+    //    {
+    //      var holders = [ H, ..., G ];
+    //    }
+    var holderArray =
+        js.js.statement('var holders = #', js.ArrayInitializer(holderUses));
+
+    mainHolderResource.statement =
+        js.Block([holderCode.statement, holderArray]);
+  }
+
+  /// Allocates all [DeferredHolderResource]s and finalizes the associated
+  /// [DeferredHolderExpression]s.
+  void allocateResourcesAndFinalizeReferences() {
+    // First finalize all holders in the main output unit.
+    declareHoldersInMainResource();
 
     // Next finalize all [DeferredHolderResource]s.
     for (var resource in holderResources) {
       switch (resource.kind) {
-        case DeferredHolderResourceKind.declaration:
-          var holderCode = declareHolders(resource);
-          resource.statement = js.Block(holderCode.statements);
+        case DeferredHolderResourceKind.mainFragment:
+          // There should only be one main resource and at this point it
+          // should have already been finalized.
+          assert(mainHolderResource == resource && resource.isFinalized);
           break;
-        case DeferredHolderResourceKind.update:
+        case DeferredHolderResourceKind.deferredFragment:
           updateHolders(resource);
           break;
       }
+      finalizeReferences(resource);
     }
   }
 
   @override
   void finalize() {
-    finalizeReferences();
-    allocateResources();
+    registerHolders();
+    finalizeParameters();
+    allocateResourcesAndFinalizeReferences();
   }
 
-  void _registerDeferredHolderExpression(DeferredHolderExpression node) {
-    holderReferences.add(node);
+  void _registerDeferredHolderExpression(
+      String resourceName, DeferredHolderExpression node) {
+    (holderReferences[resourceName] ??= []).add(node);
   }
 
   void _registerDeferredHolderResource(DeferredHolderResource node) {
+    if (node.isMainFragment) {
+      assert(mainHolderResource == null);
+      mainHolderResource = node;
+    }
     holderResources.add(node);
   }
 
@@ -586,10 +684,17 @@
 /// The state is kept in the finalizer so that this scan could be extended to
 /// look for other deferred expressions in one pass.
 class _DeferredHolderExpressionCollectorVisitor extends js.BaseVisitor<void> {
+  String resourceName;
   final DeferredHolderExpressionFinalizerImpl _finalizer;
 
   _DeferredHolderExpressionCollectorVisitor(this._finalizer);
 
+  void setResourceNameAndVisit(String resourceName, js.Node code) {
+    this.resourceName = resourceName;
+    code.accept(this);
+    this.resourceName = null;
+  }
+
   @override
   void visitNode(js.Node node) {
     assert(node is! DeferredHolderExpression);
@@ -605,7 +710,8 @@
   @override
   void visitDeferredExpression(js.DeferredExpression node) {
     if (node is DeferredHolderExpression) {
-      _finalizer._registerDeferredHolderExpression(node);
+      assert(resourceName != null);
+      _finalizer._registerDeferredHolderExpression(resourceName, node);
     } else {
       visitNode(node);
     }
@@ -630,8 +736,9 @@
   }
 }
 
-class HolderCode {
-  final List<String> activeHolders;
-  final List<js.Statement> statements;
-  HolderCode(this.activeHolders, this.statements);
+class HolderInitCode {
+  final Iterable<Holder> allHolders;
+  final List<Holder> activeHolders;
+  final js.Statement statement;
+  HolderInitCode(this.allHolders, this.activeHolders, this.statement);
 }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 8503a49..5e4afbd 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2071,8 +2071,9 @@
   FixedNames get fixedNames;
 
   /// Returns a variable use for accessing constants.
-  jsAst.Expression globalObjectForConstants() {
-    return DeferredHolderExpression.forConstants();
+  jsAst.Expression globalObjectForConstant(ConstantValue constant) {
+    return DeferredHolderExpression(
+        DeferredHolderExpressionKind.globalObjectForConstant, constant);
   }
 
   /// Returns a variable use for accessing static state.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index bea472a..a4249ee 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -679,6 +679,7 @@
       size = estimator.charCount;
     }
     var emittedOutputUnit = EmittedOutputUnit(
+        fragment,
         fragment.outputUnit,
         fragment.libraries,
         classPrototypes,
@@ -704,9 +705,10 @@
     // Emit holder code.
     var holderCode = emitHolderCode(fragment.libraries);
     var holderDeclaration = DeferredHolderResource(
-        DeferredHolderResourceKind.declaration,
-        holderCode: holderCode,
-        initializeEmptyHolders: true);
+        DeferredHolderResourceKind.mainFragment,
+        mainResourceName,
+        [fragment],
+        holderCode);
     js.Statement mainCode = js.js.statement(_mainBoilerplate, {
       // TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
       'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
@@ -758,7 +760,7 @@
       'call2selector': js.quoteName(call2Name)
     });
     // We assume emitMainFragment will be the last piece of code we emit.
-    finalizeCode(mainCode, holderCode, finalizeHolders: true);
+    finalizeCode(mainResourceName, mainCode, holderCode, finalizeHolders: true);
     return mainCode;
   }
 
@@ -778,9 +780,12 @@
       return null;
     }
 
+    var resourceName = fragment.canonicalOutputUnit.name;
     var updateHolders = DeferredHolderResource(
-        DeferredHolderResourceKind.update,
-        holderCode: holderCode);
+        DeferredHolderResourceKind.deferredFragment,
+        resourceName,
+        fragment.fragments,
+        holderCode);
     js.Expression code = js.js(_deferredBoilerplate, {
       // TODO(floitsch): don't just reference 'init'.
       'embeddedGlobalsObject': new js.Parameter('init'),
@@ -806,7 +811,7 @@
     if (_options.experimentStartupFunctions) {
       code = js.Parentheses(code);
     }
-    finalizeCode(code, holderCode);
+    finalizeCode(resourceName, code, holderCode);
     return code;
   }
 
@@ -823,7 +828,8 @@
 
   /// Finalizes the code for a fragment, and optionally finalizes holders.
   /// Finalizing holders must be the last step of the emitter.
-  void finalizeCode(js.Node code, Map<Entity, List<js.Property>> holderCode,
+  void finalizeCode(String resourceName, js.Node code,
+      Map<Entity, List<js.Property>> holderCode,
       {bool finalizeHolders: false}) {
     StringReferenceFinalizer stringFinalizer =
         StringReferenceFinalizerImpl(_options.enableMinification);
@@ -841,7 +847,11 @@
     // per output unit, the holderFinalizer is a whole-program finalizer,
     // which collects deferred [Node]s from each call to `finalizeCode`
     // before begin finalized once for the last (main) unit.
-    addCodeToFinalizer(_holderFinalizer.addCode, code, holderCode);
+    void _addCode(js.Node code) {
+      _holderFinalizer.addCode(resourceName, code);
+    }
+
+    addCodeToFinalizer(_addCode, code, holderCode);
     if (finalizeHolders) {
       _holderFinalizer.finalize();
     }
@@ -1569,7 +1579,7 @@
       // TODO(25230): We only need to name constants that are used from function
       // bodies or from other constants in a different part.
       var assignment = js.js.statement('#.# = #', [
-        _namer.globalObjectForConstants(),
+        _namer.globalObjectForConstant(constant.value),
         constant.name,
         _constantEmitter.generate(constant.value)
       ]);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index 89cc19c..9fae89c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -109,6 +109,7 @@
 /// sent to the client.
 
 class EmittedOutputUnit {
+  final Fragment fragment;
   final OutputUnit outputUnit;
   final List<Library> libraries;
   final js.Statement classPrototypes;
@@ -124,6 +125,7 @@
   final js.Statement nativeSupport;
 
   EmittedOutputUnit(
+      this.fragment,
       this.outputUnit,
       this.libraries,
       this.classPrototypes,
@@ -140,6 +142,7 @@
 
   CodeFragment toCodeFragment(Program program) {
     return CodeFragment(
+        [fragment],
         [outputUnit],
         libraries,
         classPrototypes,
@@ -201,6 +204,7 @@
       return seedEmittedOutputUnit.toCodeFragment(program);
     } else {
       var seedOutputUnit = seedEmittedOutputUnit.outputUnit;
+      List<Fragment> fragments = [];
       List<Library> libraries = [];
       List<OutputUnit> outputUnits = [seedOutputUnit];
       List<js.Statement> classPrototypes = [];
@@ -219,6 +223,7 @@
         if (seedOutputUnit != thatOutputUnit) {
           program.mergeOutputUnitMetadata(seedOutputUnit, thatOutputUnit);
           outputUnits.add(thatOutputUnit);
+          fragments.add(emittedOutputUnit.fragment);
         }
         libraries.addAll(emittedOutputUnit.libraries);
         classPrototypes.add(emittedOutputUnit.classPrototypes);
@@ -234,6 +239,7 @@
         nativeSupport.add(emittedOutputUnit.nativeSupport);
       }
       return CodeFragment(
+          fragments,
           outputUnits,
           libraries,
           js.Block(classPrototypes),
@@ -316,6 +322,7 @@
 }
 
 class CodeFragment {
+  final List<Fragment> fragments;
   final List<OutputUnit> outputUnits;
   final List<Library> libraries;
   final js.Statement classPrototypes;
@@ -332,6 +339,7 @@
   final js.Expression deferredTypes;
 
   CodeFragment(
+      this.fragments,
       this.outputUnits,
       this.libraries,
       this.classPrototypes,
@@ -388,6 +396,8 @@
     }
     return outputUnitStrings.join('+');
   }
+
+  OutputUnit get canonicalOutputUnit => outputUnits.first;
 }
 
 class FinalizedFragment {
@@ -400,7 +410,7 @@
   // TODO(joshualitt): Refactor this to more clearly disambiguate between
   // [OutputUnits](units of deferred merging), fragments(units of emitted code),
   // and files.
-  OutputUnit get canonicalOutputUnit => codeFragments.first.outputUnits.first;
+  OutputUnit get canonicalOutputUnit => codeFragments.first.canonicalOutputUnit;
 
   @override
   String toString() {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 21fe02f..8a272c6 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -65,7 +65,8 @@
         DeferredHolderExpressionFinalizerImpl,
         DeferredHolderParameter,
         DeferredHolderResource,
-        DeferredHolderResourceKind;
+        DeferredHolderResourceKind,
+        mainResourceName;
 import '../../js_backend/type_reference.dart'
     show
         TypeReferenceFinalizer,
@@ -218,8 +219,8 @@
     if (isConstantInlinedOrAlreadyEmitted(value)) {
       return constantEmitter.generate(value);
     }
-    return js.js(
-        '#.#', [_namer.globalObjectForConstants(), _namer.constantName(value)]);
+    return js.js('#.#',
+        [_namer.globalObjectForConstant(value), _namer.constantName(value)]);
   }
 
   bool get shouldMergeFragments => _options.mergeFragmentsThreshold != null;
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index 6c46fed..bfe74b5 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -2,6 +2,8 @@
 // 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
+
 library dart2js.util.maplet;
 
 import 'dart:collection' show MapBase, IterableBase;
@@ -57,7 +59,7 @@
   }
 
   @override
-  bool containsKey(Object key) {
+  bool containsKey(Object? key) {
     if (_extra == null) {
       return _key == key;
     } else if (_MARKER == _extra) {
@@ -74,7 +76,7 @@
   }
 
   @override
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     if (_extra == null) {
       return (_key == key) ? _value : null;
     } else if (_MARKER == _extra) {
@@ -113,7 +115,8 @@
     } else {
       int remaining = _extra;
       int index = 0;
-      int copyTo, copyFrom;
+      int copyTo = 0;
+      int copyFrom = 0;
       while (remaining > 0 && index < CAPACITY) {
         var candidate = _key[index];
         if (_MARKER == candidate) {
@@ -172,7 +175,7 @@
   }
 
   @override
-  V remove(Object key) {
+  V? remove(Object? key) {
     if (_extra == null) {
       if (_key != key) return null;
       _key = _MARKER;
@@ -248,12 +251,12 @@
 
 class _MapletSingleIterator<K> implements Iterator<K> {
   var _element;
-  K _current;
+  K? _current;
 
   _MapletSingleIterator(this._element);
 
   @override
-  K get current => _current;
+  K get current => _current as K;
 
   @override
   bool moveNext() {
@@ -271,12 +274,12 @@
   final List _list;
   int _remaining;
   int _index = 0;
-  K _current;
+  K? _current;
 
   _MapletListIterator(this._list, this._remaining);
 
   @override
-  K get current => _current;
+  K get current => _current as K;
 
   @override
   bool moveNext() {
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index 2908f51..0e0f59c 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -6,8 +6,10 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:analysis_server/src/server/driver.dart' show Driver;
 import 'package:analysis_server_client/protocol.dart'
     show EditBulkFixesResult, ResponseDecoder;
+import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
 import 'core.dart';
@@ -16,10 +18,15 @@
 
 /// A class to provide an API wrapper around an analysis server process.
 class AnalysisServer {
-  AnalysisServer(this.sdkPath, this.analysisRoot);
+  AnalysisServer(
+    this.sdkPath,
+    this.analysisRoots, {
+    @required this.commandName,
+  });
 
   final Directory sdkPath;
-  final FileSystemEntity analysisRoot;
+  final List<FileSystemEntity> analysisRoots;
+  final String commandName;
 
   Process _process;
 
@@ -64,6 +71,8 @@
   Future<void> start() async {
     final List<String> command = <String>[
       sdk.analysisServerSnapshot,
+      '--${Driver.SUPPRESS_ANALYTICS_FLAG}',
+      '--${Driver.CLIENT_ID}=dart-$commandName',
       '--disable-server-feature-completion',
       '--disable-server-feature-search',
       '--sdk',
@@ -98,10 +107,10 @@
     //
     // The call to absolute.resolveSymbolicLinksSync() canonicalizes the path to
     // be passed to the analysis server.
-    var analysisRootPath = trimEnd(
-      analysisRoot.absolute.resolveSymbolicLinksSync(),
-      path.context.separator,
-    );
+    List<String> analysisRootPaths = analysisRoots.map((root) {
+      return trimEnd(
+          root.absolute.resolveSymbolicLinksSync(), path.context.separator);
+    }).toList();
 
     onAnalyzing.listen((bool isAnalyzing) {
       if (isAnalyzing && _analysisFinished.isCompleted) {
@@ -115,7 +124,7 @@
 
     // ignore: unawaited_futures
     _sendCommand('analysis.setAnalysisRoots', params: <String, dynamic>{
-      'included': [analysisRootPath],
+      'included': analysisRootPaths,
       'excluded': <String>[]
     });
   }
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index ea90429..254a780 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -69,26 +69,19 @@
 
   @override
   FutureOr<int> run() async {
-    if (argResults.rest.length > 1) {
-      usageException('Only one directory or file is expected.');
-    }
-
-    // find target from argResults.rest
-    io.FileSystemEntity target;
-    io.Directory relativeToDir;
+    // Find targets from the 'rest' params.
+    final List<io.FileSystemEntity> targets = [];
     if (argResults.rest.isEmpty) {
-      target = io.Directory.current;
-      relativeToDir = target;
+      targets.add(io.Directory.current);
     } else {
-      var targetPath = argResults.rest.single;
-      if (io.Directory(targetPath).existsSync()) {
-        target = io.Directory(targetPath);
-        relativeToDir = target;
-      } else if (io.File(targetPath).existsSync()) {
-        target = io.File(targetPath);
-        relativeToDir = target.parent;
-      } else {
-        usageException("Directory or file doesn't exist: $targetPath");
+      for (String targetPath in argResults.rest) {
+        if (io.Directory(targetPath).existsSync()) {
+          targets.add(io.Directory(targetPath));
+        } else if (io.File(targetPath).existsSync()) {
+          targets.add(io.File(targetPath));
+        } else {
+          usageException("Directory or file doesn't exist: $targetPath");
+        }
       }
     }
 
@@ -97,13 +90,16 @@
     final machineFormat = argResults['format'] == 'machine';
     final jsonFormat = argResults['format'] == 'json';
 
-    var progress = machineFormat
-        ? null
-        : log.progress('Analyzing ${path.basename(target.path)}');
+    final targetsNames =
+        targets.map((entity) => path.basename(entity.path)).join(', ');
+
+    var progress =
+        machineFormat ? null : log.progress('Analyzing $targetsNames');
 
     final AnalysisServer server = AnalysisServer(
       io.Directory(sdk.sdkPath),
-      target,
+      targets,
+      commandName: 'analyze',
     );
 
     server.onErrors.listen((FileAnalysisErrors fileErrors) {
@@ -144,8 +140,14 @@
     } else if (jsonFormat) {
       emitJsonFormat(log, errors);
     } else {
-      emitDefaultFormat(log, errors,
-          relativeToDir: relativeToDir, verbose: verbose);
+      var relativeTo = targets.length == 1 ? targets.single : null;
+
+      emitDefaultFormat(
+        log,
+        errors,
+        relativeToDir: relativeTo is io.File ? relativeTo.parent : relativeTo,
+        verbose: verbose,
+      );
     }
 
     bool hasErrors = false;
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index 546d5fa..c053a29 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -91,7 +91,8 @@
 
     var server = AnalysisServer(
       io.Directory(sdk.sdkPath),
-      dir,
+      [dir],
+      commandName: 'fix',
     );
 
     await server.start();
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
index 27f5b3f..dba2ccc 100644
--- a/pkg/dartdev/test/analysis_server_test.dart
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -24,13 +24,15 @@
     tearDown(() => p?.dispose());
 
     test('can start', () async {
-      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir);
+      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
+          commandName: 'testing');
       await server.start();
       await server.shutdown();
     });
 
     test('can send message', () async {
-      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir);
+      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
+          commandName: 'testing');
       await server.start();
 
       final response = await server.getVersion();
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index d098f53..293c139 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -85,14 +85,36 @@
     expect(result.stdout, contains(_analyzeVerboseUsageText));
   });
 
-  test('multiple directories', () {
-    p = project();
-    var result = p.runSync(['analyze', '/no/such/dir1/', '/no/such/dir2/']);
+  group('multiple items', () {
+    TestProject secondProject;
 
-    expect(result.exitCode, 64);
-    expect(result.stdout, isEmpty);
-    expect(result.stderr, contains('Only one directory or file is expected.'));
-    expect(result.stderr, contains(_analyzeUsageText));
+    tearDown(() => secondProject?.dispose());
+
+    test('folder and file', () {
+      p = project(mainSrc: "int get foo => 'str';\n");
+      secondProject = project(mainSrc: "int get foo => 'str';\n");
+      var result = p.runSync(['analyze', p.dirPath, secondProject.mainPath]);
+
+      expect(result.exitCode, 3);
+      expect(result.stderr, isEmpty);
+      expect(result.stdout, contains('A value of type '));
+      expect(result.stdout, contains('lib/main.dart:1:16 '));
+      expect(result.stdout, contains('return_of_invalid_type'));
+      expect(result.stdout, contains('2 issues found.'));
+    });
+
+    test('two folders', () {
+      p = project(mainSrc: "int get foo => 'str';\n");
+      secondProject = project(mainSrc: "int get foo => 'str';\n");
+      var result = p.runSync(['analyze', p.dirPath, secondProject.dirPath]);
+
+      expect(result.exitCode, 3);
+      expect(result.stderr, isEmpty);
+      expect(result.stdout, contains('A value of type '));
+      expect(result.stdout, contains('main.dart:1:16 '));
+      expect(result.stdout, contains('return_of_invalid_type'));
+      expect(result.stdout, contains('2 issues found.'));
+    });
   });
 
   test('no such directory', () {
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index 0397e2c..85ca410 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -3,8 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io';
+
+import 'package:collection/collection.dart';
+import 'package:vm_service/vm_service.dart' as vm;
 
 import '../base_debug_adapter.dart';
+import '../isolate_manager.dart';
 import '../logging.dart';
 import '../protocol_generated.dart';
 import '../protocol_stream.dart';
@@ -47,12 +52,35 @@
 /// to then send a `stackTraceRequest` or `scopesRequest` to get variables).
 abstract class DartDebugAdapter<T extends DartLaunchRequestArguments>
     extends BaseDebugAdapter<T> {
-  late T args;
+  late final T args;
   final _debuggerInitializedCompleter = Completer<void>();
   final _configurationDoneCompleter = Completer<void>();
 
+  /// Managers VM Isolates and their events, including fanning out any requests
+  /// to set breakpoints etc. from the client to all Isolates.
+  late IsolateManager _isolateManager;
+
+  /// All active VM Service subscriptions.
+  ///
+  /// TODO(dantup): This may be changed to use StreamManager as part of using
+  /// DDS in this process.
+  final _subscriptions = <StreamSubscription<vm.Event>>[];
+
+  /// The VM service of the app being debugged.
+  ///
+  /// `null` if the session is running in noDebug mode of the connection has not
+  /// yet been made.
+  vm.VmServiceInterface? vmService;
+
+  /// Whether the current debug session is an attach request (as opposed to a
+  /// launch request). Not available until after launchRequest or attachRequest
+  /// have been called.
+  late final bool isAttach;
+
   DartDebugAdapter(ByteStreamServerChannel channel, Logger? logger)
-      : super(channel, logger);
+      : super(channel, logger) {
+    _isolateManager = IsolateManager(this);
+  }
 
   /// Completes when the debugger initialization has completed. Used to delay
   /// processing isolate events while initialization is still running to avoid
@@ -60,6 +88,33 @@
   /// processed its initial paused state).
   Future<void> get debuggerInitialized => _debuggerInitializedCompleter.future;
 
+  /// attachRequest is called by the client when it wants us to to attach to
+  /// an existing app. This will only be called once (and only one of this or
+  /// launchRequest will be called).
+  @override
+  FutureOr<void> attachRequest(
+    Request request,
+    T args,
+    void Function(void) sendResponse,
+  ) async {
+    this.args = args;
+    isAttach = true;
+
+    // Don't start launching until configurationDone.
+    if (!_configurationDoneCompleter.isCompleted) {
+      logger?.call('Waiting for configurationDone request...');
+      await _configurationDoneCompleter.future;
+    }
+
+    // TODO(dantup): Implement attach support.
+    throw UnimplementedError();
+
+    // Delegate to the sub-class to attach to the process.
+    // await attachImpl();
+    //
+    // sendResponse(null);
+  }
+
   /// configurationDone is called by the client when it has finished sending
   /// any initial configuration (such as breakpoints and exception pause
   /// settings).
@@ -77,6 +132,97 @@
     sendResponse(null);
   }
 
+  /// Connects to the VM Service at [uri] and initializes debugging.
+  ///
+  /// This method will be called by sub-classes when they are ready to start
+  /// a debug session and may provide a URI given by the user (in the case
+  /// of attach) or from something like a vm-service-info file or Flutter
+  /// app.debugPort message.
+  ///
+  /// The URI protocol will be changed to ws/wss but otherwise not normalised.
+  /// The caller should handle any other normalisation (such as adding /ws to
+  /// the end if required).
+  Future<void> connectDebugger(Uri uri) async {
+    // The VM Service library always expects the WebSockets URI so fix the
+    // scheme (http -> ws, https -> wss).
+    final isSecure = uri.isScheme('https') || uri.isScheme('wss');
+    uri = uri.replace(scheme: isSecure ? 'wss' : 'ws');
+
+    logger?.call('Connecting to debugger at $uri');
+    sendOutput('console', 'Connecting to VM Service at $uri\n');
+    final vmService =
+        await _vmServiceConnectUri(uri.toString(), logger: logger);
+    logger?.call('Connected to debugger at $uri!');
+
+    // TODO(dantup): VS Code currently depends on a custom dart.debuggerUris
+    // event to notify it of VM Services that become available (for example to
+    // register with the DevTools server). If this is still required, it will
+    // need implementing here (and also documented as a customisation and
+    // perhaps gated on a capability/argument).
+    this.vmService = vmService;
+
+    _subscriptions.addAll([
+      vmService.onIsolateEvent.listen(_handleIsolateEvent),
+      vmService.onDebugEvent.listen(_handleDebugEvent),
+      vmService.onLoggingEvent.listen(_handleLoggingEvent),
+      // TODO(dantup): Implement these.
+      // vmService.onExtensionEvent.listen(_handleExtensionEvent),
+      // vmService.onServiceEvent.listen(_handleServiceEvent),
+      // vmService.onStdoutEvent.listen(_handleStdoutEvent),
+      // vmService.onStderrEvent.listen(_handleStderrEvent),
+    ]);
+    await Future.wait([
+      vmService.streamListen(vm.EventStreams.kIsolate),
+      vmService.streamListen(vm.EventStreams.kDebug),
+      vmService.streamListen(vm.EventStreams.kLogging),
+      // vmService.streamListen(vm.EventStreams.kExtension),
+      // vmService.streamListen(vm.EventStreams.kService),
+      // vmService.streamListen(vm.EventStreams.kStdout),
+      // vmService.streamListen(vm.EventStreams.kStderr),
+    ]);
+
+    final vmInfo = await vmService.getVM();
+    logger?.call('Connected to ${vmInfo.name} on ${vmInfo.operatingSystem}');
+
+    // Let the subclass do any existing setup once we have a connection.
+    await debuggerConnected(vmInfo);
+
+    // Process any existing isolates that may have been created before the
+    // streams above were set up.
+    final existingIsolateRefs = vmInfo.isolates;
+    final existingIsolates = existingIsolateRefs != null
+        ? await Future.wait(existingIsolateRefs
+            .map((isolateRef) => isolateRef.id)
+            .whereNotNull()
+            .map(vmService.getIsolate))
+        : <vm.Isolate>[];
+    await Future.wait(existingIsolates.map((isolate) async {
+      // Isolates may have the "None" pauseEvent kind at startup, so infer it
+      // from the runnable field.
+      final pauseEventKind = isolate.runnable ?? false
+          ? vm.EventKind.kIsolateRunnable
+          : vm.EventKind.kIsolateStart;
+      await _isolateManager.registerIsolate(isolate, pauseEventKind);
+
+      // If the Isolate already has a Pause event we can give it to the
+      // IsolateManager to handle (if it's PausePostStart it will re-configure
+      // the isolate before resuming), otherwise we can just resume it (if it's
+      // runnable - otherwise we'll handle this when it becomes runnable in an
+      // event later).
+      if (isolate.pauseEvent?.kind?.startsWith('Pause') ?? false) {
+        await _isolateManager.handleEvent(isolate.pauseEvent!);
+      } else if (isolate.runnable == true) {
+        await _isolateManager.resumeIsolate(isolate);
+      }
+    }));
+
+    _debuggerInitializedCompleter.complete();
+  }
+
+  /// Overridden by sub-classes to perform any additional setup after the VM
+  /// Service is connected.
+  FutureOr<void> debuggerConnected(vm.VM vmInfo);
+
   /// Overridden by sub-classes to handle when the client sends a
   /// `disconnectRequest` (a forceful request to shut down).
   FutureOr<void> disconnectImpl();
@@ -159,6 +305,7 @@
     void Function(void) sendResponse,
   ) async {
     this.args = args;
+    isAttach = false;
 
     // Don't start launching until configurationDone.
     if (!_configurationDoneCompleter.isCompleted) {
@@ -178,6 +325,18 @@
     sendEvent(OutputEventBody(category: category, output: message));
   }
 
+  /// Sends an OutputEvent for [message], prefixed with [prefix] and with [message]
+  /// indented to after the prefix.
+  ///
+  /// Assumes the output is in full lines and will always include a terminating
+  /// newline.
+  void sendPrefixedOutput(String category, String prefix, String message) {
+    final indentString = ' ' * prefix.length;
+    final indentedMessage =
+        message.trimRight().split('\n').join('\n$indentString');
+    sendOutput(category, '$prefix$indentedMessage\n');
+  }
+
   /// Overridden by sub-classes to handle when the client sends a
   /// `terminateRequest` (a request for a graceful shut down).
   FutureOr<void> terminateImpl();
@@ -199,6 +358,84 @@
     terminateImpl();
     sendResponse(null);
   }
+
+  void _handleDebugEvent(vm.Event event) {
+    _isolateManager.handleEvent(event);
+  }
+
+  void _handleIsolateEvent(vm.Event event) {
+    _isolateManager.handleEvent(event);
+  }
+
+  /// Handles a dart:developer log() event, sending output to the client.
+  Future<void> _handleLoggingEvent(vm.Event event) async {
+    final record = event.logRecord;
+    final thread = _isolateManager.threadForIsolate(event.isolate);
+    if (record == null || thread == null) {
+      return;
+    }
+
+    /// Helper to convert to InstanceRef to a String, taking into account
+    /// [vm.InstanceKind.kNull] which is the type for the unused fields of a
+    /// log event.
+    FutureOr<String?> asString(vm.InstanceRef? ref) {
+      if (ref == null || ref.kind == vm.InstanceKind.kNull) {
+        return null;
+      }
+      // TODO(dantup): This should handle truncation and complex types.
+      return ref.valueAsString;
+    }
+
+    var loggerName = await asString(record.loggerName);
+    if (loggerName?.isEmpty ?? true) {
+      loggerName = 'log';
+    }
+    final message = await asString(record.message);
+    final error = await asString(record.error);
+    final stack = await asString(record.stackTrace);
+
+    final prefix = '[$loggerName] ';
+
+    if (message != null) {
+      sendPrefixedOutput('stdout', prefix, '$message\n');
+    }
+    if (error != null) {
+      sendPrefixedOutput('stderr', prefix, '$error\n');
+    }
+    if (stack != null) {
+      sendPrefixedOutput('stderr', prefix, '$stack\n');
+    }
+  }
+
+  /// A wrapper around the same name function from package:vm_service that
+  /// allows logging all traffic over the VM Service.
+  Future<vm.VmService> _vmServiceConnectUri(
+    String wsUri, {
+    Logger? logger,
+  }) async {
+    final socket = await WebSocket.connect(wsUri);
+    final controller = StreamController();
+    final streamClosedCompleter = Completer();
+
+    socket.listen(
+      (data) {
+        logger?.call('<== [VM] $data');
+        controller.add(data);
+      },
+      onDone: () => streamClosedCompleter.complete(),
+    );
+
+    return vm.VmService(
+      controller.stream,
+      (String message) {
+        logger?.call('==> [VM] $message');
+        socket.add(message);
+      },
+      log: logger != null ? VmServiceLogger(logger) : null,
+      disposeHandler: () => socket.close(),
+      streamClosed: streamClosedCompleter.future,
+    );
+  }
 }
 
 /// An implementation of [LaunchRequestArguments] that includes all fields used
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli.dart b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
index 2a472d0..311955e9 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
@@ -6,7 +6,9 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:path/path.dart' as path;
 import 'package:pedantic/pedantic.dart';
+import 'package:vm_service/vm_service.dart' as vm;
 
 import '../logging.dart';
 import '../protocol_generated.dart';
@@ -17,18 +19,53 @@
 class DartCliDebugAdapter extends DartDebugAdapter<DartLaunchRequestArguments> {
   Process? _process;
 
+  /// The location of the vm-service-info file (if debugging).
+  ///
+  /// This may be provided by the user (eg. if attaching) or generated by the DA.
+  File? _vmServiceInfoFile;
+
+  /// A watcher for [_vmServiceInfoFile] to detect when the VM writes the service
+  /// info file.
+  ///
+  /// Should be cancelled once the file has been successfully read.
+  StreamSubscription<FileSystemEvent>? _vmServiceInfoFileWatcher;
+
+  /// Process IDs to terminate during shutdown.
+  ///
+  /// This may be populated with pids from the VM Service to ensure we clean up
+  /// properly where signals may not be passed through the shell to the
+  /// underlying VM process.
+  /// https://github.com/Dart-Code/Dart-Code/issues/907
+  final pidsToTerminate = <int>{};
+
   @override
   final parseLaunchArgs = DartLaunchRequestArguments.fromJson;
 
   DartCliDebugAdapter(ByteStreamServerChannel channel, [Logger? logger])
       : super(channel, logger);
 
+  FutureOr<void> debuggerConnected(vm.VM vmInfo) {
+    if (!isAttach) {
+      // Capture the PID from the VM Service so that we can terminate it when
+      // cleaning up. Terminating the process might not be enough as it could be
+      // just a shell script (eg. pub on Windows) and may not pass the
+      // signal on correctly.
+      // See: https://github.com/Dart-Code/Dart-Code/issues/907
+      final pid = vmInfo.pid;
+      if (pid != null) {
+        pidsToTerminate.add(pid);
+      }
+    }
+  }
+
   /// Called by [disconnectRequest] to request that we forcefully shut down the
   /// app being run (or in the case of an attach, disconnect).
   FutureOr<void> disconnectImpl() {
-    // TODO(dantup): In Dart-Code DAP, we first try again with SIGINT and wait
+    // TODO(dantup): In Dart-Code DAP, we first try again with sigint and wait
     // for a few seconds before sending sigkill.
-    _process?.kill(ProcessSignal.sigkill);
+    pidsToTerminate.forEach(
+      (pid) => Process.killPid(pid, ProcessSignal.sigkill),
+    );
   }
 
   /// Called by [launchRequest] to request that we actually start the app to be
@@ -38,8 +75,46 @@
   /// breakpoints, and resume.
   Future<void> launchImpl() async {
     final vmPath = Platform.resolvedExecutable;
-    final vmArgs = <String>[]; // TODO(dantup): enable-asserts, debug, etc.
 
+    final debug = !(args.noDebug ?? false);
+    if (debug) {
+      // Create a temp folder for the VM to write the service-info-file into.
+      // Using tmpDir.createTempory() is flakey on Windows+Linux (at least
+      // on GitHub Actions) complaining the file does not exist when creating a
+      // watcher. Creating/watching a folder and writing the file into it seems
+      // to be reliable.
+      final serviceInfoFilePath = path.join(
+        Directory.systemTemp.createTempSync('dart-vm-service').path,
+        'vm.json',
+      );
+      _vmServiceInfoFile = File(serviceInfoFilePath);
+      _vmServiceInfoFileWatcher = _vmServiceInfoFile?.parent
+          .watch(events: FileSystemEvent.all)
+          .where((event) => event.path == _vmServiceInfoFile?.path)
+          .listen(
+            _handleVmServiceInfoEvent,
+            onError: (e) => logger?.call('Ignoring exception from watcher: $e'),
+          );
+    }
+
+    // TODO(dantup): Currently this just spawns the new VM and completely
+    // ignores DDS. Figure out how this will ultimately work - will we just wrap
+    // the call to initDebugger() with something that starts DDS?
+    final vmServiceInfoFile = _vmServiceInfoFile;
+    final vmArgs = <String>[
+      '--no-serve-devtools',
+      if (debug) ...[
+        '--enable-vm-service=${args.vmServicePort ?? 0}',
+        '--pause_isolates_on_start=true',
+      ],
+      if (debug && vmServiceInfoFile != null) ...[
+        '-DSILENT_OBSERVATORY=true',
+        '--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
+      ],
+      // Default to asserts on, this seems like the most useful behaviour for
+      // editor-spawned debug sessions.
+      if (args.enableAsserts ?? true) '--enable-asserts'
+    ];
     final processArgs = [
       ...vmArgs,
       args.program,
@@ -53,6 +128,7 @@
       workingDirectory: args.cwd,
     );
     _process = process;
+    pidsToTerminate.add(process.pid);
 
     process.stdout.listen(_handleStdout);
     process.stderr.listen(_handleStderr);
@@ -62,7 +138,9 @@
   /// Called by [terminateRequest] to request that we gracefully shut down the
   /// app being run (or in the case of an attach, disconnect).
   FutureOr<void> terminateImpl() async {
-    _process?.kill(ProcessSignal.sigint);
+    pidsToTerminate.forEach(
+      (pid) => Process.killPid(pid, ProcessSignal.sigint),
+    );
     await _process?.exitCode;
   }
 
@@ -82,4 +160,24 @@
   void _handleStdout(List<int> data) {
     sendOutput('stdout', utf8.decode(data));
   }
+
+  /// Handles file watcher events for the vm-service-info file and connects the
+  /// debugger.
+  ///
+  /// The vm-service-info file is written by the VM when we start the app/script
+  /// to debug and contains the VM Service URI. This allows us to access the
+  /// auth token without needing to have the URI printed to/scraped from stdout.
+  void _handleVmServiceInfoEvent(FileSystemEvent event) {
+    try {
+      final content = _vmServiceInfoFile!.readAsStringSync();
+      final json = jsonDecode(content);
+      final uri = Uri.parse(json['uri']);
+      unawaited(connectDebugger(uri));
+      _vmServiceInfoFileWatcher?.cancel();
+    } catch (e) {
+      // It's possible we tried to read the file before it was completely
+      // written so ignore and try again on the next event.
+      logger?.call('Ignoring error parsing vm-service-info file: $e');
+    }
+  }
 }
diff --git a/pkg/dds/lib/src/dap/base_debug_adapter.dart b/pkg/dds/lib/src/dap/base_debug_adapter.dart
index d0a05ac..0c00630 100644
--- a/pkg/dds/lib/src/dap/base_debug_adapter.dart
+++ b/pkg/dds/lib/src/dap/base_debug_adapter.dart
@@ -9,6 +9,9 @@
 import 'protocol_generated.dart';
 import 'protocol_stream.dart';
 
+typedef _FromJsonHandler<T> = T Function(Map<String, Object?>);
+typedef _NullableFromJsonHandler<T> = T? Function(Map<String, Object?>?);
+
 /// A base class for debug adapters.
 ///
 /// Communicates over a [ByteStreamServerChannel] and turns messages into
@@ -31,6 +34,12 @@
   /// Dart CLI, Dart tests, Flutter, Flutter tests).
   TLaunchArgs Function(Map<String, Object?>) get parseLaunchArgs;
 
+  FutureOr<void> attachRequest(
+    Request request,
+    TLaunchArgs args,
+    void Function(void) sendResponse,
+  );
+
   FutureOr<void> configurationDoneRequest(
     Request request,
     ConfigurationDoneArguments? args,
@@ -138,8 +147,8 @@
   );
 
   /// Wraps a fromJson handler for requests that allow null arguments.
-  T? Function(Map<String, Object?>?) _allowNullArg<T extends RequestArguments>(
-    T Function(Map<String, Object?>) fromJson,
+  _NullableFromJsonHandler<T> _allowNullArg<T extends RequestArguments>(
+    _FromJsonHandler<T> fromJson,
   ) {
     return (data) => data == null ? null : fromJson(data);
   }
@@ -161,6 +170,8 @@
       handle(request, initializeRequest, InitializeRequestArguments.fromJson);
     } else if (request.command == 'launch') {
       handle(request, launchRequest, parseLaunchArgs);
+    } else if (request.command == 'attach') {
+      handle(request, attachRequest, parseLaunchArgs);
     } else if (request.command == 'terminate') {
       handle(
         request,
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
new file mode 100644
index 0000000..3bbc226
--- /dev/null
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -0,0 +1,269 @@
+// 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:async';
+
+import 'package:vm_service/vm_service.dart' as vm;
+
+import 'adapters/dart.dart';
+import 'protocol_generated.dart';
+
+/// Manages state of Isolates (called Threads by the DAP protocol).
+///
+/// Handles incoming Isolate and Debug events to track the lifetime of isolates
+/// and updating breakpoints for each isolate as necessary.
+class IsolateManager {
+  // TODO(dantup): This class has a lot of overlap with the same-named class
+  //  in DDS. Review what can be shared.
+  final DartDebugAdapter _adapter;
+  final Map<String, Completer<void>> _isolateRegistrations = {};
+  final Map<String, ThreadInfo> _threadsByIsolateId = {};
+  final Map<int, ThreadInfo> _threadsByThreadId = {};
+  int _nextThreadNumber = 1;
+
+  IsolateManager(this._adapter);
+
+  /// A list of all current active isolates.
+  ///
+  /// When isolates exit, they will no longer be returned in this list, although
+  /// due to the async nature, it's not guaranteed that threads in this list have
+  /// not exited between accessing this list and trying to use the results.
+  List<ThreadInfo> get threads => _threadsByIsolateId.values.toList();
+
+  Future<T> getObject<T extends vm.Response>(
+      vm.IsolateRef isolate, vm.ObjRef object) async {
+    final res = await _adapter.vmService?.getObject(isolate.id!, object.id!);
+    return res as T;
+  }
+
+  /// Handles Isolate and Debug events
+  FutureOr<void> handleEvent(vm.Event event) async {
+    final isolateId = event.isolate?.id;
+    if (isolateId == null) {
+      return;
+    }
+
+    // Delay processing any events until the debugger initialization has
+    // finished running, as events may arrive (for ex. IsolateRunnable) while
+    // it's doing is own initialization that this may interfere with.
+    await _adapter.debuggerInitialized;
+
+    final eventKind = event.kind;
+    if (eventKind == vm.EventKind.kIsolateStart ||
+        eventKind == vm.EventKind.kIsolateRunnable) {
+      await registerIsolate(event.isolate!, eventKind!);
+    }
+
+    // Additionally, ensure the thread registration has completed before trying
+    // to process any other events. This is to cover the case where we are
+    // processing the above registerIsolate call in the handler for one isolate
+    // event but another one arrives and gets us here before the registration
+    // above (in the other event handler) has finished.
+    await _isolateRegistrations[isolateId]?.future;
+
+    if (eventKind == vm.EventKind.kIsolateExit) {
+      await _handleExit(event);
+    } else if (eventKind?.startsWith('Pause') ?? false) {
+      await _handlePause(event);
+    } else if (eventKind == vm.EventKind.kResume) {
+      await _handleResumed(event);
+    }
+  }
+
+  /// Registers a new isolate that exists at startup, or has subsequently been
+  /// created.
+  ///
+  /// New isolates will be configured with the correct pause-exception behaviour,
+  /// libraries will be marked as debuggable if appropriate, and breakpoints
+  /// sent.
+  FutureOr<void> registerIsolate(
+    vm.IsolateRef isolate,
+    String eventKind,
+  ) async {
+    // Ensure the completer is set up before doing any async work, so future
+    // events can wait on it.
+    final registrationCompleter =
+        _isolateRegistrations.putIfAbsent(isolate.id!, () => Completer<void>());
+
+    final info = _threadsByIsolateId.putIfAbsent(
+      isolate.id!,
+      () {
+        // The first time we see an isolate, start tracking it.
+        final info = ThreadInfo(_nextThreadNumber++, isolate);
+        _threadsByThreadId[info.threadId] = info;
+        // And notify the client about it.
+        _adapter.sendEvent(
+          ThreadEventBody(reason: 'started', threadId: info.threadId),
+        );
+        return info;
+      },
+    );
+
+    // If it's just become runnable (IsolateRunnable), configure the isolate
+    // by sending breakpoints etc.
+    if (eventKind == vm.EventKind.kIsolateRunnable && !info.runnable) {
+      info.runnable = true;
+      await _configureIsolate(isolate);
+      registrationCompleter.complete();
+    }
+  }
+
+  FutureOr<void> resumeIsolate(vm.IsolateRef isolateRef,
+      [String? resumeType]) async {
+    final isolateId = isolateRef.id;
+    if (isolateId == null) {
+      return;
+    }
+
+    final thread = _threadsByIsolateId[isolateId];
+    if (thread == null) {
+      return;
+    }
+
+    await resumeThread(thread.threadId);
+  }
+
+  /// Resumes (or steps) an isolate using its client [threadId].
+  ///
+  /// If the isolate is not paused, or already has a pending resume request
+  /// in-flight, a request will not be sent.
+  ///
+  /// If the isolate is paused at an async suspension and the [resumeType] is
+  /// [vm.StepOption.kOver], a [StepOption.kOverAsyncSuspension] step will be
+  /// sent instead.
+  Future<void> resumeThread(int threadId, [String? resumeType]) async {
+    final thread = _threadsByThreadId[threadId];
+    if (thread == null) {
+      throw 'Thread $threadId was not found';
+    }
+
+    // Check this thread hasn't already been resumed by another handler in the
+    // meantime (for example if the user performs a hot restart or something
+    // while we processing some previous events).
+    if (!thread.paused || thread.hasPendingResume) {
+      return;
+    }
+
+    // We always assume that a step when at an async suspension is intended to
+    // be an async step.
+    if (resumeType == vm.StepOption.kOver && thread.atAsyncSuspension) {
+      resumeType = vm.StepOption.kOverAsyncSuspension;
+    }
+
+    thread.hasPendingResume = true;
+    try {
+      await _adapter.vmService?.resume(thread.isolate.id!, step: resumeType);
+    } finally {
+      thread.hasPendingResume = false;
+    }
+  }
+
+  ThreadInfo? threadForIsolate(vm.IsolateRef? isolate) =>
+      isolate?.id != null ? _threadsByIsolateId[isolate!.id!] : null;
+
+  /// Configures a new isolate, setting it's exception-pause mode, which
+  /// libraries are debuggable, and sending all breakpoints.
+  FutureOr<void> _configureIsolate(vm.IsolateRef isolate) async {
+    // TODO(dantup): set library debuggable, exception pause mode, breakpoints
+  }
+
+  FutureOr<void> _handleExit(vm.Event event) {
+    final isolate = event.isolate!;
+    final isolateId = isolate.id!;
+    final thread = _threadsByIsolateId[isolateId];
+    if (thread != null) {
+      // Notify the client.
+      _adapter.sendEvent(
+        ThreadEventBody(reason: 'exited', threadId: thread.threadId),
+      );
+      _threadsByIsolateId.remove(isolateId);
+      _threadsByThreadId.remove(thread.threadId);
+    }
+  }
+
+  /// Handles a pause event.
+  ///
+  /// For [vm.EventKind.kPausePostRequest] which occurs after a restart, the isolate
+  /// will be re-configured (pause-exception behaviour, debuggable libraries,
+  /// breakpoints) and then resumed.
+  ///
+  /// For [vm.EventKind.kPauseStart], the isolate will be resumed.
+  ///
+  /// For breakpoints with conditions that are not met and for logpoints, the
+  /// isolate will be automatically resumed.
+  ///
+  /// For all other pause types, the isolate will remain paused and a
+  /// corresponding "Stopped" event sent to the editor.
+  FutureOr<void> _handlePause(vm.Event event) async {
+    final eventKind = event.kind;
+    final isolate = event.isolate!;
+    final thread = _threadsByIsolateId[isolate.id!];
+
+    if (thread == null) {
+      return;
+    }
+
+    thread.atAsyncSuspension = event.atAsyncSuspension ?? false;
+    thread.paused = true;
+    thread.pauseEvent = event;
+
+    // For PausePostRequest we need to re-send all breakpoints; this happens
+    // after a hot restart.
+    if (eventKind == vm.EventKind.kPausePostRequest) {
+      _configureIsolate(isolate);
+      await resumeThread(thread.threadId);
+    } else if (eventKind == vm.EventKind.kPauseStart) {
+      await resumeThread(thread.threadId);
+    } else {
+      // PauseExit, PauseBreakpoint, PauseInterrupted, PauseException
+      var reason = 'pause';
+
+      if (eventKind == vm.EventKind.kPauseBreakpoint &&
+          (event.pauseBreakpoints?.isNotEmpty ?? false)) {
+        reason = 'breakpoint';
+      } else if (eventKind == vm.EventKind.kPauseBreakpoint) {
+        reason = 'step';
+      } else if (eventKind == vm.EventKind.kPauseException) {
+        reason = 'exception';
+      }
+
+      // TODO(dantup): Store exception.
+
+      // Notify the client.
+      _adapter.sendEvent(
+        StoppedEventBody(reason: reason, threadId: thread.threadId),
+      );
+    }
+  }
+
+  /// Handles a resume event from the VM, updating our local state.
+  FutureOr<void> _handleResumed(vm.Event event) {
+    final isolate = event.isolate!;
+    final thread = _threadsByIsolateId[isolate.id!];
+    if (thread != null) {
+      thread.paused = false;
+      thread.pauseEvent = null;
+      thread.exceptionReference = null;
+    }
+  }
+}
+
+/// Holds state for a single Isolate/Thread.
+class ThreadInfo {
+  final vm.IsolateRef isolate;
+  final int threadId;
+  var runnable = false;
+  var atAsyncSuspension = false;
+  int? exceptionReference;
+  var paused = false;
+
+  // The most recent pauseEvent for this isolate.
+  vm.Event? pauseEvent;
+
+  /// Whether this isolate has an in-flight resume request that has not yet
+  /// been responded to.
+  var hasPendingResume = false;
+
+  ThreadInfo(this.threadId, this.isolate);
+}
diff --git a/pkg/dds/lib/src/dap/logging.dart b/pkg/dds/lib/src/dap/logging.dart
index d5c8a3f..a7a7ffd 100644
--- a/pkg/dds/lib/src/dap/logging.dart
+++ b/pkg/dds/lib/src/dap/logging.dart
@@ -2,4 +2,19 @@
 // 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:vm_service/vm_service.dart' as vm;
+
 typedef Logger = void Function(String);
+
+/// Wraps a [Logger] as a [vm/Log] to be passed to the VM Service library.
+class VmServiceLogger extends vm.Log {
+  final Logger _logger;
+
+  VmServiceLogger(this._logger);
+
+  @override
+  void severe(String message) => _logger.call('ERROR: $message');
+
+  @override
+  void warning(String message) => _logger.call('WARN: $message');
+}
diff --git a/pkg/dds/lib/src/dap/server.dart b/pkg/dds/lib/src/dap/server.dart
index 50dcd16..f110e4e 100644
--- a/pkg/dds/lib/src/dap/server.dart
+++ b/pkg/dds/lib/src/dap/server.dart
@@ -15,6 +15,8 @@
 
 /// A DAP server that binds to a port and runs in multi-session mode.
 class DapServer {
+  static const defaultPort = 9200;
+
   final ServerSocket _socket;
   final Logger? _logger;
   final _channels = <ByteStreamServerChannel>{};
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 9b226bf..cf7e081 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -12,6 +12,7 @@
 
 dependencies:
   async: ^2.4.1
+  collection: ^1.15.0
   devtools_shared: ^2.3.0
   json_rpc_2: ^3.0.0
   meta: ^1.1.8
@@ -29,7 +30,6 @@
 
 dev_dependencies:
   args: ^2.0.0
-  collection: ^1.15.0
   http: ^0.13.0
   test: ^1.0.0
   webdriver: ^3.0.0
diff --git a/pkg/dds/test/dap/integration/debug_logging_test.dart b/pkg/dds/test/dap/integration/debug_logging_test.dart
new file mode 100644
index 0000000..1fc81bc1
--- /dev/null
+++ b/pkg/dds/test/dap/integration/debug_logging_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 'package:test/test.dart';
+
+import 'test_support.dart';
+
+main() {
+  testDap((dap) async {
+    group('debug mode', () {
+      test('prints messages from dart:developer log()', () async {
+        final testFile = dap.createTestFile(r'''
+import 'dart:developer';
+
+void main(List<String> args) async {
+  log('this is a test\nacross two lines');
+  log('this is a test', name: 'foo');
+}
+    ''');
+
+        var outputEvents = await dap.client.collectOutput(file: testFile);
+
+        // Skip the first line because it's the VM Service connection info.
+        final output = outputEvents.skip(1).map((e) => e.output).join();
+        expectLines(output, [
+          '[log] this is a test',
+          '      across two lines',
+          '[foo] this is a test',
+          '',
+          'Exited.',
+        ]);
+      });
+    });
+  });
+}
diff --git a/pkg/dds/test/dap/integration/debug_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
new file mode 100644
index 0000000..a934e42
--- /dev/null
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -0,0 +1,47 @@
+// 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 'package:test/test.dart';
+
+import 'test_support.dart';
+
+main() {
+  testDap((dap) async {
+    group('debug mode', () {
+      test('runs a simple script', () async {
+        final testFile = dap.createTestFile(r'''
+void main(List<String> args) async {
+  print('Hello!');
+  print('World!');
+  print('args: $args');
+}
+    ''');
+
+        var outputEvents = await dap.client.collectOutput(
+          launch: () => dap.client.launch(
+            testFile.path,
+            args: ['one', 'two'],
+          ),
+        );
+
+        // Expect a "console" output event that prints the URI of the VM Service
+        // the debugger connects to.
+        final vmConnection = outputEvents.first;
+        expect(vmConnection.output,
+            startsWith('Connecting to VM Service at ws://127.0.0.1:'));
+        expect(vmConnection.category, equals('console'));
+
+        // Expect the normal applications output.
+        final output = outputEvents.skip(1).map((e) => e.output).join();
+        expectLines(output, [
+          'Hello!',
+          'World!',
+          'args: [one, two]',
+          '',
+          'Exited.',
+        ]);
+      });
+    });
+  });
+}
diff --git a/pkg/dds/test/dap/integration/no_debug_test.dart b/pkg/dds/test/dap/integration/no_debug_test.dart
index 064716c6..72509b0 100644
--- a/pkg/dds/test/dap/integration/no_debug_test.dart
+++ b/pkg/dds/test/dap/integration/no_debug_test.dart
@@ -7,12 +7,10 @@
 import 'test_support.dart';
 
 main() {
-  setUpAll(startServerAndClient);
-  tearDownAll(stopServerAndClient);
-
-  group('noDebug', () {
-    test('runs a simple script', () async {
-      final testFile = createTestFile(r'''
+  testDap((dap) async {
+    group('noDebug mode', () {
+      test('runs a simple script', () async {
+        final testFile = dap.createTestFile(r'''
 void main(List<String> args) async {
   print('Hello!');
   print('World!');
@@ -20,22 +18,23 @@
 }
     ''');
 
-      final outputEvents = await dapClient.collectOutput(
-        launch: () => dapClient.launch(
-          testFile.path,
-          noDebug: true,
-          args: ['one', 'two'],
-        ),
-      );
+        final outputEvents = await dap.client.collectOutput(
+          launch: () => dap.client.launch(
+            testFile.path,
+            noDebug: true,
+            args: ['one', 'two'],
+          ),
+        );
 
-      final output = outputEvents.map((e) => e.output).join();
-      expectLines(output, [
-        'Hello!',
-        'World!',
-        'args: [one, two]',
-        '',
-        'Exited.',
-      ]);
+        final output = outputEvents.map((e) => e.output).join();
+        expectLines(output, [
+          'Hello!',
+          'World!',
+          'args: [one, two]',
+          '',
+          'Exited.',
+        ]);
+      });
     });
   });
 }
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index 8a3a380..e5fecdc 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -19,10 +19,10 @@
   final Socket _socket;
   final ByteStreamServerChannel _channel;
   late final StreamSubscription<String> _subscription;
+
   final Logger? _logger;
   final bool captureVmServiceTraffic;
   final _requestWarningDuration = const Duration(seconds: 2);
-
   final Map<int, _OutgoingRequest> _pendingRequests = {};
   final _eventController = StreamController<Event>.broadcast();
   int _seq = 1;
diff --git a/pkg/dds/test/dap/integration/test_server.dart b/pkg/dds/test/dap/integration/test_server.dart
index 3676fa7..7e4c526 100644
--- a/pkg/dds/test/dap/integration/test_server.dart
+++ b/pkg/dds/test/dap/integration/test_server.dart
@@ -3,15 +3,17 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:isolate';
 
 import 'package:dds/src/dap/server.dart';
+import 'package:path/path.dart' as path;
+import 'package:pedantic/pedantic.dart';
 
 abstract class DapTestServer {
-  String get host => _server.host;
-
-  int get port => _server.port;
-  DapServer get _server;
-
+  String get host;
+  int get port;
   FutureOr<void> stop();
 }
 
@@ -25,6 +27,9 @@
 
   InProcessDapTestServer._(this._server);
 
+  String get host => _server.host;
+  int get port => _server.port;
+
   @override
   FutureOr<void> stop() async {
     await _server.stop();
@@ -35,3 +40,61 @@
     return InProcessDapTestServer._(server);
   }
 }
+
+/// An instance of a DAP server running out-of-process.
+///
+/// This is how an editor will usually consume DAP so is a more accurate test
+/// but will be a little more difficult to debug tests as the debugger will not
+/// be attached to the process.
+class OutOfProcessDapTestServer extends DapTestServer {
+  /// Since each test library will spawn its own server (setup/teardown are
+  /// library-scoped) we'll use a different port for each one to avoid any issues
+  /// with overlapping tests.
+  static var _nextPort = DapServer.defaultPort;
+
+  var _isShuttingDown = false;
+  final Process _process;
+  final int port;
+  final String host;
+
+  OutOfProcessDapTestServer._(this._process, this.host, this.port) {
+    // The DAP server should generally not write to stdout/stderr (unless -v is
+    // passed), but it may do if it fails to start or crashes. If this happens,
+    // ensure these are included in the test output.
+    _process.stdout.transform(utf8.decoder).listen(print);
+    _process.stderr.transform(utf8.decoder).listen((s) => throw s);
+    unawaited(_process.exitCode.then((code) {
+      if (!_isShuttingDown && code != 0) {
+        throw 'Out-of-process DAP server terminated with code $code';
+      }
+    }));
+  }
+
+  @override
+  FutureOr<void> stop() async {
+    _isShuttingDown = true;
+    await _process.kill();
+    await _process.exitCode;
+  }
+
+  static Future<OutOfProcessDapTestServer> create() async {
+    final ddsEntryScript =
+        await Isolate.resolvePackageUri(Uri.parse('package:dds/dds.dart'));
+    final ddsLibFolder = path.dirname(ddsEntryScript!.toFilePath());
+    final dapServerScript =
+        path.join(ddsLibFolder, '../tool/dap/run_server.dart');
+
+    final port = OutOfProcessDapTestServer._nextPort++;
+    final host = 'localhost';
+    final _process = await Process.start(
+      Platform.resolvedExecutable,
+      [
+        dapServerScript,
+        '--host=$host',
+        '--port=$port',
+      ],
+    );
+
+    return OutOfProcessDapTestServer._(_process, host, port);
+  }
+}
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index 2784bf6..7c66534 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -11,19 +11,14 @@
 import 'test_client.dart';
 import 'test_server.dart';
 
-late DapTestClient dapClient;
-late DapTestServer dapServer;
-
-final _testFolders = <Directory>[];
-
-/// Creates a file in a temporary folder to be used as an application for testing.
-File createTestFile(String content) {
-  final testAppDir = Directory.systemTemp.createTempSync('dart-sdk-dap-test');
-  _testFolders.add(testAppDir);
-  final testFile = File(path.join(testAppDir.path, 'test_file.dart'));
-  testFile.writeAsStringSync(content);
-  return testFile;
-}
+/// Whether to run the DAP server in-process with the tests, or externally in
+/// another process.
+///
+/// By default tests will run the DAP server out-of-process to match the real
+/// use from editors, but this complicates debugging the adapter. Set this env
+/// variables to run the server in-process for easier debugging (this can be
+/// simplified in VS Code by using a launch config with custom CodeLens links).
+final useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true';
 
 /// Expects [actual] to equal the lines [expected], ignoring differences in line
 /// endings.
@@ -31,18 +26,77 @@
   expect(actual.replaceAll('\r\n', '\n'), equals(expected.join('\n')));
 }
 
-/// Starts a DAP server and a DAP client that connects to it for use in tests.
-FutureOr<void> startServerAndClient() async {
-  // TODO(dantup): An Out-of-process option.
-  dapServer = await InProcessDapTestServer.create();
-  dapClient = await DapTestClient.connect(dapServer.port);
+/// A helper function to wrap all tests in a library with setup/teardown functions
+/// to start a shared server for all tests in the library and an individual
+/// client for each test.
+testDap(FutureOr<void> Function(DapTestSession session) tests) {
+  final session = DapTestSession();
+
+  setUpAll(session.setUpAll);
+  tearDownAll(session.tearDownAll);
+  setUp(session.setUp);
+  tearDown(session.tearDown);
+
+  return tests(session);
 }
 
-/// Shuts down the DAP server and client created by [startServerAndClient].
-FutureOr<void> stopServerAndClient() async {
-  await dapClient.stop();
-  await dapServer.stop();
+/// A helper class provided to DAP integration tests run with [testDap] to
+/// easily share setup/teardown without sharing state across tests from different
+/// files.
+class DapTestSession {
+  late DapTestServer server;
+  late DapTestClient client;
+  final _testFolders = <Directory>[];
 
-  // Clean up any temp folders created during the test run.
-  _testFolders.forEach((dir) => dir.deleteSync(recursive: true));
+  /// Creates a file in a temporary folder to be used as an application for testing.
+  ///
+  /// The file will be deleted at the end of the test run.
+  File createTestFile(String content) {
+    final testAppDir = Directory.systemTemp.createTempSync('dart-sdk-dap-test');
+    _testFolders.add(testAppDir);
+    final testFile = File(path.join(testAppDir.path, 'test_file.dart'));
+    testFile.writeAsStringSync(content);
+    return testFile;
+  }
+
+  FutureOr<void> setUp() async {
+    client = await _startClient(server);
+  }
+
+  FutureOr<void> setUpAll() async {
+    server = await _startServer();
+  }
+
+  FutureOr<void> tearDown() => client.stop();
+
+  FutureOr<void> tearDownAll() async {
+    await server.stop();
+
+    // Clean up any temp folders created during the test runs.
+    _testFolders.forEach((dir) => dir.deleteSync(recursive: true));
+  }
+
+  /// Creates and connects a new [DapTestClient] to [server].
+  FutureOr<DapTestClient> _startClient(DapTestServer server) async {
+    // Since we don't get a signal from the DAP server when it's ready and we
+    // just started it, add a short retry to connections.
+    var attempt = 1;
+    while (attempt++ <= 20) {
+      try {
+        return await DapTestClient.connect(server.port);
+      } catch (e) {
+        await Future.delayed(const Duration(milliseconds: 200));
+      }
+    }
+
+    throw 'Failed to connect to DAP server on port ${server.port}'
+        ' after $attempt attempts. Did the server start correctly?';
+  }
+
+  /// Starts a DAP server that can be shared across tests.
+  FutureOr<DapTestServer> _startServer() async {
+    return useInProcessDap
+        ? await InProcessDapTestServer.create()
+        : await OutOfProcessDapTestServer.create();
+  }
 }
diff --git a/pkg/dds/tool/dap/run_server.dart b/pkg/dds/tool/dap/run_server.dart
new file mode 100644
index 0000000..69f90f1
--- /dev/null
+++ b/pkg/dds/tool/dap/run_server.dart
@@ -0,0 +1,46 @@
+// 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 'package:args/args.dart';
+import 'package:dds/src/dap/server.dart';
+
+Future<void> main(List<String> arguments) async {
+  final args = argParser.parse(arguments);
+  if (args[argHelp]) {
+    print(argParser.usage);
+    return;
+  }
+
+  final port = int.parse(args[argPort]);
+  final host = args[argHost];
+
+  await DapServer.create(
+    host: host,
+    port: port,
+    logger: args[argVerbose] ? print : null,
+  );
+}
+
+const argHelp = 'help';
+const argHost = 'host';
+const argPort = 'port';
+const argVerbose = 'verbose';
+final argParser = ArgParser()
+  ..addFlag(argHelp, hide: true)
+  ..addOption(
+    argHost,
+    defaultsTo: 'localhost',
+    help: 'The hostname/IP to bind the server to',
+  )
+  ..addOption(
+    argPort,
+    abbr: 'p',
+    defaultsTo: DapServer.defaultPort.toString(),
+    help: 'The port to bind the server to',
+  )
+  ..addFlag(
+    argVerbose,
+    abbr: 'v',
+    help: 'Whether to print diagnostic output to stdout',
+  );
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 99bf9ab..9e7c46c6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -6590,6 +6590,17 @@
     }
     return name.isEmpty ? className : "$className.$name";
   }
+
+  @override
+  void handleNewAsIdentifier(Token token) {
+    // TODO(johnniwinther, paulberry): disable this error when the
+    // "constructor-tearoffs" feature is enabled.
+    addProblem(
+        templateExperimentNotEnabled.withArguments('constructor-tearoffs',
+            libraryBuilder.enableConstructorTearoffsVersionInLibrary.toText()),
+        token.charOffset,
+        token.length);
+  }
 }
 
 abstract class EnsureLoaded {
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 4304a9d..d924fc7 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -2169,6 +2169,17 @@
   void debugEvent(String name) {
     // printEvent('OutlineBuilder: $name');
   }
+
+  @override
+  void handleNewAsIdentifier(Token token) {
+    // TODO(johnniwinther, paulberry): disable this error when the
+    // "constructor-tearoffs" feature is enabled.
+    addProblem(
+        templateExperimentNotEnabled.withArguments('constructor-tearoffs',
+            libraryBuilder.enableConstructorTearoffsVersionInLibrary.toText()),
+        token.charOffset,
+        token.length);
+  }
 }
 
 enum _MethodKind {
diff --git a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
index 5c14977..c6cc986 100644
--- a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
+++ b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
@@ -2550,6 +2550,14 @@
             openAngleBracket: openAngleBracket);
     seen(data);
   }
+
+  void handleNewAsIdentifier(Token token) {
+    DirectParserASTContentNewAsIdentifierHandle data =
+        new DirectParserASTContentNewAsIdentifierHandle(
+            DirectParserASTType.HANDLE,
+            token: token);
+    seen(data);
+  }
 }
 
 class DirectParserASTContentArgumentsBegin extends DirectParserASTContent {
@@ -6882,3 +6890,16 @@
         "openAngleBracket": openAngleBracket,
       };
 }
+
+class DirectParserASTContentNewAsIdentifierHandle
+    extends DirectParserASTContent {
+  final Token token;
+
+  DirectParserASTContentNewAsIdentifierHandle(DirectParserASTType type,
+      {required this.token})
+      : super("NewAsIdentifier", type);
+
+  Map<String, Object?> get deprecatedArguments => {
+        "token": token,
+      };
+}
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart b/pkg/front_end/parser_testcases/general/new_as_identifier.dart
new file mode 100644
index 0000000..32a868f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart
@@ -0,0 +1,48 @@
+// 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.md file.
+
+// These test cases verify that the identifier `new` can be used anywhere a
+// constructor name might appear.
+//
+// Unless otherwise noted, these tests cases should not result in a parse error.
+
+class C {
+  C.new();
+
+  // This should be result in a parse error--even though `C() : this.new();` is
+  // allowed, `C() : this.new = ...;` should not be.
+  C.constructor_field_initializer() : this.new = null;
+}
+
+class D {
+  factory D.new() => C();
+  factory D.factory_redirection() = C.new;
+  factory D.factory_redirection_generic() = C<int>.new;
+  factory D.factory_redirection_prefixed() = prefix.C.new;
+  factory D.factory_redirection_prefixed_generic() = prefix.C<int>.new;
+  D.super_invocation() : super.new();
+  D.this_redirection() : this.new();
+}
+
+var constructor_invocation_const = const C.new();
+var constructor_invocation_const_generic = const C<int>.new();
+var constructor_invocation_const_prefixed = const prefix.C.new();
+var constructor_invocation_const_prefixed_generic = const prefix.C<int>.new();
+var constructor_invocation_explicit = new C.new();
+var constructor_invocation_explicit_generic = new C<int>.new();
+var constructor_invocation_explicit_prefixed = new prefix.C.new();
+var constructor_invocation_explicit_prefixed_generic = new prefix.C<int>.new();
+var constructor_invocation_implicit = C.new();
+var constructor_invocation_implicit_generic = C<int>.new();
+var constructor_invocation_implicit_prefixed = prefix.C.new();
+var constructor_invocation_implicit_prefixed_generic = prefix.C<int>.new();
+var constructor_tearoff = C.new;
+var constructor_tearoff_generic = C<int>.new;
+var constructor_tearoff_generic_method_invocation = C<int>.new.toString();
+var constructor_tearoff_method_invocation = C.new.toString();
+var constructor_tearoff_prefixed = prefix.C.new;
+var constructor_tearoff_prefixed_generic = prefix.C<int>.new;
+var constructor_tearoff_prefixed_generic_method_invocation =
+    prefix.C<int>.new.toString();
+var constructor_tearoff_prefixed_method_invocation = prefix.C.new.toString();
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect
new file mode 100644
index 0000000..da22a5b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.expect
@@ -0,0 +1,845 @@
+Problems reported:
+
+parser/general/new_as_identifier:15:44: Expected an identifier, but got 'new'.
+  C.constructor_field_initializer() : this.new = null;
+                                           ^^^
+
+parser/general/new_as_identifier:15:39: Expected an assignment after the field name.
+  C.constructor_field_initializer() : this.new = null;
+                                      ^^^^
+
+parser/general/new_as_identifier:15:44: Expected a function body, but got 'new'.
+  C.constructor_field_initializer() : this.new = null;
+                                           ^^^
+
+parser/general/new_as_identifier:15:44: Expected a class member, but got 'new'.
+  C.constructor_field_initializer() : this.new = null;
+                                           ^^^
+
+parser/general/new_as_identifier:15:48: Operator declarations must be preceded by the keyword 'operator'.
+  C.constructor_field_initializer() : this.new = null;
+                                               ^
+
+parser/general/new_as_identifier:15:48: The string '=' isn't a user-definable operator.
+  C.constructor_field_initializer() : this.new = null;
+                                               ^
+
+parser/general/new_as_identifier:15:48: A method declaration needs an explicit list of parameters.
+  C.constructor_field_initializer() : this.new = null;
+                                               ^
+
+parser/general/new_as_identifier:15:50: Expected a function body, but got 'null'.
+  C.constructor_field_initializer() : this.new = null;
+                                                 ^^^^
+
+parser/general/new_as_identifier:15:50: Expected a class member, but got 'null'.
+  C.constructor_field_initializer() : this.new = null;
+                                                 ^^^^
+
+parser/general/new_as_identifier:15:54: Expected a class member, but got ';'.
+  C.constructor_field_initializer() : this.new = null;
+                                                     ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(C, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, C)
+      handleNoType(C)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, C)
+            handleNoType({)
+            handleIdentifier(C, methodDeclaration)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleEmptyFunctionBody(;)
+          endClassConstructor(null, C, (, null, ;)
+        endMember()
+        beginMetadataStar(C)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, C)
+            handleNoType(;)
+            handleIdentifier(C, methodDeclaration)
+            handleIdentifier(constructor_field_initializer, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(this)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., Try inserting an identifier before 'new'., {lexeme: new}], new, new)
+                handleRecoverableError(MissingAssignmentInInitializer, this, this)
+                handleIdentifier(, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(, =)
+                handleThisExpression(this, expression)
+                handleIdentifier(, expressionContinuation)
+                handleNoTypeArguments(new)
+                handleNoArguments(new)
+                handleSend(, new)
+                handleEndingBinaryExpression(.)
+                handleAssignmentExpression(=)
+              endInitializer(new)
+            endInitializers(1, :, new)
+            handleAsyncModifier(null, null)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got 'new'., null, {lexeme: new}], new, new)
+            handleInvalidFunctionBody({)
+          endClassConstructor(null, C, (, :, })
+        endMember()
+        beginMetadataStar(new)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got 'new'., null, {lexeme: new}], new, new)
+          handleInvalidMember(new)
+        endMember()
+        beginMetadataStar(=)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(MissingOperatorKeyword, =, =)
+          beginMethod(null, null, null, null, null, operator)
+            handleNoType(new)
+            handleRecoverableError(Message[InvalidOperator, The string '=' isn't a user-definable operator., null, {lexeme: =}], =, =)
+            handleInvalidOperatorName(operator, =)
+            handleNoTypeVariables(null)
+            handleRecoverableError(MissingMethodParameters, =, =)
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got 'null'., null, {lexeme: null}], null, null)
+            handleInvalidFunctionBody({)
+          endClassMethod(null, operator, (, null, })
+        endMember()
+        beginMetadataStar(null)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got 'null'., null, {lexeme: null}], null, null)
+          handleInvalidMember(null)
+        endMember()
+        beginMetadataStar(;)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+          handleInvalidMember(;)
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 6, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(D, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, D)
+      handleNoType(D)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(factory)
+        endMetadataStar(0)
+        beginMember()
+          beginFactoryMethod({, null, null)
+            handleIdentifier(D, methodDeclaration)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.Factory)
+            endFormalParameters(0, (, ), MemberKind.Factory)
+            handleAsyncModifier(null, null)
+            handleIdentifier(C, expression)
+            handleNoTypeArguments(()
+            beginArguments(()
+            endArguments(0, (, ))
+            handleSend(C, ;)
+            handleExpressionFunctionBody(=>, ;)
+          endClassFactoryMethod(factory, factory, ;)
+        endMember()
+        beginMetadataStar(factory)
+        endMetadataStar(0)
+        beginMember()
+          beginFactoryMethod(;, null, null)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(factory_redirection, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.Factory)
+            endFormalParameters(0, (, ), MemberKind.Factory)
+            handleAsyncModifier(null, null)
+            beginRedirectingFactoryBody(=)
+              handleIdentifier(C, constructorReference)
+              beginConstructorReference(C)
+                handleNewAsIdentifier(new)
+                handleIdentifier(new, constructorReferenceContinuation)
+                handleQualified(.)
+                handleNoTypeArguments(;)
+                handleNoConstructorReferenceContinuationAfterTypeArguments(;)
+              endConstructorReference(C, null, ;)
+            endRedirectingFactoryBody(=, ;)
+          endClassFactoryMethod(factory, factory, ;)
+        endMember()
+        beginMetadataStar(factory)
+        endMetadataStar(0)
+        beginMember()
+          beginFactoryMethod(;, null, null)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(factory_redirection_generic, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.Factory)
+            endFormalParameters(0, (, ), MemberKind.Factory)
+            handleAsyncModifier(null, null)
+            beginRedirectingFactoryBody(=)
+              handleIdentifier(C, constructorReference)
+              beginConstructorReference(C)
+                beginTypeArguments(<)
+                  handleIdentifier(int, typeReference)
+                  handleNoTypeArguments(>)
+                  handleType(int, null)
+                endTypeArguments(1, <, >)
+                handleNewAsIdentifier(new)
+                handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+              endConstructorReference(C, ., ;)
+            endRedirectingFactoryBody(=, ;)
+          endClassFactoryMethod(factory, factory, ;)
+        endMember()
+        beginMetadataStar(factory)
+        endMetadataStar(0)
+        beginMember()
+          beginFactoryMethod(;, null, null)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(factory_redirection_prefixed, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.Factory)
+            endFormalParameters(0, (, ), MemberKind.Factory)
+            handleAsyncModifier(null, null)
+            beginRedirectingFactoryBody(=)
+              handleIdentifier(prefix, constructorReference)
+              beginConstructorReference(prefix)
+                handleIdentifier(C, constructorReferenceContinuation)
+                handleQualified(.)
+                handleNoTypeArguments(.)
+                handleNewAsIdentifier(new)
+                handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+              endConstructorReference(prefix, ., ;)
+            endRedirectingFactoryBody(=, ;)
+          endClassFactoryMethod(factory, factory, ;)
+        endMember()
+        beginMetadataStar(factory)
+        endMetadataStar(0)
+        beginMember()
+          beginFactoryMethod(;, null, null)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(factory_redirection_prefixed_generic, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.Factory)
+            endFormalParameters(0, (, ), MemberKind.Factory)
+            handleAsyncModifier(null, null)
+            beginRedirectingFactoryBody(=)
+              handleIdentifier(prefix, constructorReference)
+              beginConstructorReference(prefix)
+                handleIdentifier(C, constructorReferenceContinuation)
+                handleQualified(.)
+                beginTypeArguments(<)
+                  handleIdentifier(int, typeReference)
+                  handleNoTypeArguments(>)
+                  handleType(int, null)
+                endTypeArguments(1, <, >)
+                handleNewAsIdentifier(new)
+                handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+              endConstructorReference(prefix, ., ;)
+            endRedirectingFactoryBody(=, ;)
+          endClassFactoryMethod(factory, factory, ;)
+        endMember()
+        beginMetadataStar(D)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, D)
+            handleNoType(;)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(super_invocation, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(super)
+                handleNewAsIdentifier(new)
+                handleSuperExpression(super, expression)
+                handleIdentifier(new, expressionContinuation)
+                handleNoTypeArguments(()
+                beginArguments(()
+                endArguments(0, (, ))
+                handleSend(new, ;)
+                handleEndingBinaryExpression(.)
+              endInitializer(;)
+            endInitializers(1, :, ;)
+            handleAsyncModifier(null, null)
+            handleEmptyFunctionBody(;)
+          endClassConstructor(null, D, (, :, ;)
+        endMember()
+        beginMetadataStar(D)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, D)
+            handleNoType(;)
+            handleIdentifier(D, methodDeclaration)
+            handleIdentifier(this_redirection, methodDeclarationContinuation)
+            handleQualified(.)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(this)
+                handleNewAsIdentifier(new)
+                handleThisExpression(this, expression)
+                handleIdentifier(new, expressionContinuation)
+                handleNoTypeArguments(()
+                beginArguments(()
+                endArguments(0, (, ))
+                handleSend(new, ;)
+                handleEndingBinaryExpression(.)
+              endInitializer(;)
+            endInitializers(1, :, ;)
+            handleAsyncModifier(null, null)
+            handleEmptyFunctionBody(;)
+          endClassConstructor(null, D, (, :, ;)
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 7, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(})
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_const, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginConstExpression(const)
+          handleIdentifier(C, constructorReference)
+          beginConstructorReference(C)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuation)
+            handleQualified(.)
+            handleNoTypeArguments(()
+            handleNoConstructorReferenceContinuationAfterTypeArguments(()
+          endConstructorReference(C, null, ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endConstExpression(const)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_const_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginConstExpression(const)
+          handleIdentifier(C, constructorReference)
+          beginConstructorReference(C)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(C, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endConstExpression(const)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_const_prefixed, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginConstExpression(const)
+          handleIdentifier(prefix, constructorReference)
+          beginConstructorReference(prefix)
+            handleIdentifier(C, constructorReferenceContinuation)
+            handleQualified(.)
+            handleNoTypeArguments(.)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(prefix, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endConstExpression(const)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_const_prefixed_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginConstExpression(const)
+          handleIdentifier(prefix, constructorReference)
+          beginConstructorReference(prefix)
+            handleIdentifier(C, constructorReferenceContinuation)
+            handleQualified(.)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(prefix, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endConstExpression(const)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_explicit, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginNewExpression(new)
+          handleIdentifier(C, constructorReference)
+          beginConstructorReference(C)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuation)
+            handleQualified(.)
+            handleNoTypeArguments(()
+            handleNoConstructorReferenceContinuationAfterTypeArguments(()
+          endConstructorReference(C, null, ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endNewExpression(new)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_explicit_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginNewExpression(new)
+          handleIdentifier(C, constructorReference)
+          beginConstructorReference(C)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(C, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endNewExpression(new)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_explicit_prefixed, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginNewExpression(new)
+          handleIdentifier(prefix, constructorReference)
+          beginConstructorReference(prefix)
+            handleIdentifier(C, constructorReferenceContinuation)
+            handleQualified(.)
+            handleNoTypeArguments(.)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(prefix, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endNewExpression(new)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_explicit_prefixed_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginNewExpression(new)
+          handleIdentifier(prefix, constructorReference)
+          beginConstructorReference(prefix)
+            handleIdentifier(C, constructorReferenceContinuation)
+            handleQualified(.)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(prefix, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endNewExpression(new)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_implicit, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(C, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_implicit_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginImplicitCreationExpression(=)
+          handleIdentifier(C, constructorReference)
+          beginConstructorReference(C)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(C, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endImplicitCreationExpression(=)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_implicit_prefixed, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(prefix, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(prefix, .)
+        handleIdentifier(C, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleEndingBinaryExpression(.)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_invocation_implicit_prefixed_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        beginImplicitCreationExpression(=)
+          handleIdentifier(prefix, constructorReference)
+          beginConstructorReference(prefix)
+            handleIdentifier(C, constructorReferenceContinuation)
+            handleQualified(.)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleNewAsIdentifier(new)
+            handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+          endConstructorReference(prefix, ., ()
+          beginArguments(()
+          endArguments(0, (, ))
+        endImplicitCreationExpression(=)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(C, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(;)
+        handleNoArguments(;)
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(C, expression)
+        handleNoTypeArguments(<)
+        handleNoArguments(<)
+        handleSend(C, <)
+        beginTypeArguments(<)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(>)
+          handleType(int, null)
+        endTypeArguments(1, <, >)
+        handleTypeArgumentApplication(<)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(;)
+        handleNoArguments(;)
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_generic_method_invocation, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(C, expression)
+        handleNoTypeArguments(<)
+        handleNoArguments(<)
+        handleSend(C, <)
+        beginTypeArguments(<)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(>)
+          handleType(int, null)
+        endTypeArguments(1, <, >)
+        handleTypeArgumentApplication(<)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(new, .)
+        handleEndingBinaryExpression(.)
+        handleIdentifier(toString, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(toString, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_method_invocation, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(C, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(new, .)
+        handleEndingBinaryExpression(.)
+        handleIdentifier(toString, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(toString, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_prefixed, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(prefix, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(prefix, .)
+        handleIdentifier(C, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleEndingBinaryExpression(.)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(;)
+        handleNoArguments(;)
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_prefixed_generic, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(prefix, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(prefix, .)
+        handleIdentifier(C, expressionContinuation)
+        handleNoTypeArguments(<)
+        handleNoArguments(<)
+        handleSend(C, <)
+        handleEndingBinaryExpression(.)
+        beginTypeArguments(<)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(>)
+          handleType(int, null)
+        endTypeArguments(1, <, >)
+        handleTypeArgumentApplication(<)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(;)
+        handleNoArguments(;)
+        handleSend(new, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_prefixed_generic_method_invocation, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(prefix, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(prefix, .)
+        handleIdentifier(C, expressionContinuation)
+        handleNoTypeArguments(<)
+        handleNoArguments(<)
+        handleSend(C, <)
+        handleEndingBinaryExpression(.)
+        beginTypeArguments(<)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(>)
+          handleType(int, null)
+        endTypeArguments(1, <, >)
+        handleTypeArgumentApplication(<)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(new, .)
+        handleEndingBinaryExpression(.)
+        handleIdentifier(toString, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(toString, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration(var)
+  beginMetadataStar(var)
+  endMetadataStar(0)
+  beginTopLevelMember(var)
+    beginFields(;)
+      handleNoType(var)
+      handleIdentifier(constructor_tearoff_prefixed_method_invocation, topLevelVariableDeclaration)
+      beginFieldInitializer(=)
+        handleIdentifier(prefix, expression)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(prefix, .)
+        handleIdentifier(C, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(C, .)
+        handleEndingBinaryExpression(.)
+        handleNewAsIdentifier(new)
+        handleIdentifier(new, expressionContinuation)
+        handleNoTypeArguments(.)
+        handleNoArguments(.)
+        handleSend(new, .)
+        handleEndingBinaryExpression(.)
+        handleIdentifier(toString, expressionContinuation)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(toString, ;)
+        handleEndingBinaryExpression(.)
+      endFieldInitializer(=, ;)
+    endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(22, )
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect
new file mode 100644
index 0000000..318a32c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.intertwined.expect
@@ -0,0 +1,1623 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(class)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(C, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, C)
+        parseClass(C, class, class, C)
+          parseClassHeaderOpt(C, class, class)
+            parseClassExtendsOpt(C)
+              listener: handleNoType(C)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(C)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(C)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(C, DeclarationKind.Class, C)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, C)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, C)
+              parseMetadataStar({)
+                listener: beginMetadataStar(C)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(.)
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'NoType', null, C, DeclarationKind.Class, C, false)
+                listener: beginMethod(null, null, null, null, null, C)
+                listener: handleNoType({)
+                ensureIdentifierPotentiallyRecovered({, methodDeclaration, false)
+                  listener: handleIdentifier(C, methodDeclaration)
+                parseQualifiedRestOpt(C, methodDeclarationContinuation)
+                  parseQualifiedRest(C, methodDeclarationContinuation)
+                    rewriter()
+                    listener: handleNewAsIdentifier(new)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(new, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(new)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(new, C, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(new, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: handleEmptyFunctionBody(;)
+                listener: endClassConstructor(null, C, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, C)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, C)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(C)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(.)
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'NoType', null, C, DeclarationKind.Class, C, false)
+                listener: beginMethod(null, null, null, null, null, C)
+                listener: handleNoType(;)
+                ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false)
+                  listener: handleIdentifier(C, methodDeclaration)
+                parseQualifiedRestOpt(C, methodDeclarationContinuation)
+                  parseQualifiedRest(C, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(constructor_field_initializer, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(constructor_field_initializer)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(constructor_field_initializer, C, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(constructor_field_initializer, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(this)
+                      insertSyntheticIdentifier(., fieldInitializer, message: null, messageOnToken: null)
+                        reportRecoverableError(new, Message[ExpectedIdentifier, Expected an identifier, but got 'new'., Try inserting an identifier before 'new'., {lexeme: new}])
+                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., Try inserting an identifier before 'new'., {lexeme: new}], new, new)
+                        rewriter()
+                      insertSyntheticIdentifier(:, fieldInitializer, message: MissingAssignmentInInitializer, messageOnToken: null)
+                        reportRecoverableError(this, MissingAssignmentInInitializer)
+                          listener: handleRecoverableError(MissingAssignmentInInitializer, this, this)
+                        rewriter()
+                      rewriter()
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    isNextIdentifier(:)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt()
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseThisExpression(=, expression)
+                                    listener: handleThisExpression(this, expression)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    isNextIdentifier(.)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(, expressionContinuation)
+                                    listener: handleNoTypeArguments(new)
+                                    parseArgumentsOpt()
+                                      listener: handleNoArguments(new)
+                                    listener: handleSend(, new)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(new)
+                    listener: endInitializers(1, :, new)
+                parseAsyncModifierOpt()
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(, false, true)
+                  ensureBlock(, Instance of 'Template<(Token) => Message>', null)
+                    reportRecoverableError(new, Message[ExpectedFunctionBody, Expected a function body, but got 'new'., null, {lexeme: new}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got 'new'., null, {lexeme: new}], new, new)
+                    insertBlock()
+                      rewriter()
+                      rewriter()
+                  listener: handleInvalidFunctionBody({)
+                listener: endClassConstructor(null, C, (, :, })
+              listener: endMember()
+            notEofOrValue(}, new)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, C)
+              parseMetadataStar(})
+                listener: beginMetadataStar(new)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(}, }, null, null, null, null, null, null, }, Instance of 'NoType', null, DeclarationKind.Class, C)
+                reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got 'new'., null, {lexeme: new}], new, new)
+                listener: handleInvalidMember(new)
+                listener: endMember()
+            notEofOrValue(}, =)
+            parseClassOrMixinOrExtensionMemberImpl(new, DeclarationKind.Class, C)
+              parseMetadataStar(new)
+                listener: beginMetadataStar(=)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(new, new, null, null, null, null, null, null, new, Instance of 'NoType', null, DeclarationKind.Class, C)
+                parseInvalidOperatorDeclaration(new, null, null, null, null, null, null, new, DeclarationKind.Class, C)
+                  reportRecoverableError(=, MissingOperatorKeyword)
+                    listener: handleRecoverableError(MissingOperatorKeyword, =, =)
+                  rewriter()
+                  parseMethod(new, null, null, null, null, null, null, new, Instance of 'NoType', null, operator, DeclarationKind.Class, C, false)
+                    listener: beginMethod(null, null, null, null, null, operator)
+                    listener: handleNoType(new)
+                    parseOperatorName(new)
+                      isUnaryMinus(=)
+                      reportRecoverableErrorWithToken(=, Instance of 'Template<(Token) => Message>')
+                        listener: handleRecoverableError(Message[InvalidOperator, The string '=' isn't a user-definable operator., null, {lexeme: =}], =, =)
+                      listener: handleInvalidOperatorName(operator, =)
+                    parseMethodTypeVar(=)
+                      listener: handleNoTypeVariables(null)
+                    parseGetterOrFormalParameters(=, operator, false, MemberKind.NonStaticMethod)
+                      missingParameterMessage(MemberKind.NonStaticMethod)
+                      reportRecoverableError(=, MissingMethodParameters)
+                        listener: handleRecoverableError(MissingMethodParameters, =, =)
+                      rewriter()
+                      parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                        listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                        listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                    parseInitializersOpt())
+                      listener: handleNoInitializers()
+                    parseAsyncModifierOpt())
+                      listener: handleAsyncModifier(null, null)
+                      inPlainSync()
+                    inPlainSync()
+                    parseFunctionBody(), false, true)
+                      ensureBlock(), Instance of 'Template<(Token) => Message>', null)
+                        reportRecoverableError(null, Message[ExpectedFunctionBody, Expected a function body, but got 'null'., null, {lexeme: null}])
+                          listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got 'null'., null, {lexeme: null}], null, null)
+                        insertBlock())
+                          rewriter()
+                          rewriter()
+                      listener: handleInvalidFunctionBody({)
+                    listener: endClassMethod(null, operator, (, null, })
+                  listener: endMember()
+            notEofOrValue(}, null)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, C)
+              parseMetadataStar(})
+                listener: beginMetadataStar(null)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(}, }, null, null, null, null, null, null, }, Instance of 'NoType', null, DeclarationKind.Class, C)
+                reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got 'null'., null, {lexeme: null}], null, null)
+                listener: handleInvalidMember(null)
+                listener: endMember()
+            notEofOrValue(}, ;)
+            parseClassOrMixinOrExtensionMemberImpl(null, DeclarationKind.Class, C)
+              parseMetadataStar(null)
+                listener: beginMetadataStar(;)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(null, null, null, null, null, null, null, null, null, Instance of 'NoType', null, DeclarationKind.Class, C)
+                reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+                listener: handleInvalidMember(;)
+                listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 6, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration(class)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(}, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(}, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(D, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, D)
+        parseClass(D, class, class, D)
+          parseClassHeaderOpt(D, class, class)
+            parseClassExtendsOpt(D)
+              listener: handleNoType(D)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(D)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(D)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(D, DeclarationKind.Class, D)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, factory)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, D)
+              parseMetadataStar({)
+                listener: beginMetadataStar(factory)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFactoryMethod({, DeclarationKind.Class, {, null, null, null)
+                listener: beginFactoryMethod({, null, null)
+                ensureIdentifier(factory, methodDeclaration)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    rewriter()
+                    listener: handleNewAsIdentifier(new)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(new, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(new)
+                  listener: handleNoTypeVariables(()
+                parseFormalParametersRequiredOpt(new, MemberKind.Factory)
+                  parseFormalParametersRest((, MemberKind.Factory)
+                    listener: beginFormalParameters((, MemberKind.Factory)
+                    listener: endFormalParameters(0, (, ), MemberKind.Factory)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, false)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              looksLikeFunctionBody(;)
+                              parseSend(=>, expression)
+                                isNextIdentifier(=>)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(C, expression)
+                                listener: handleNoTypeArguments(()
+                                parseArgumentsOpt(C)
+                                  parseArguments(C)
+                                    parseArgumentsRest(()
+                                      listener: beginArguments(()
+                                      listener: endArguments(0, (, ))
+                                listener: handleSend(C, ;)
+                    ensureSemicolon())
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassFactoryMethod(factory, factory, ;)
+              listener: endMember()
+            notEofOrValue(}, factory)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(factory)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFactoryMethod(;, DeclarationKind.Class, ;, null, null, null)
+                listener: beginFactoryMethod(;, null, null)
+                ensureIdentifier(factory, methodDeclaration)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(factory_redirection, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(factory_redirection)
+                  listener: handleNoTypeVariables(()
+                parseFormalParametersRequiredOpt(factory_redirection, MemberKind.Factory)
+                  parseFormalParametersRest((, MemberKind.Factory)
+                    listener: beginFormalParameters((, MemberKind.Factory)
+                    listener: endFormalParameters(0, (, ), MemberKind.Factory)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseRedirectingFactoryBody())
+                  listener: beginRedirectingFactoryBody(=)
+                  parseConstructorReference(=, null)
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(C, constructorReference)
+                    listener: beginConstructorReference(C)
+                    parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                      parseQualifiedRest(C, constructorReferenceContinuation)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        ensureIdentifier(., constructorReferenceContinuation)
+                          listener: handleIdentifier(new, constructorReferenceContinuation)
+                        listener: handleQualified(.)
+                    listener: handleNoTypeArguments(;)
+                    listener: handleNoConstructorReferenceContinuationAfterTypeArguments(;)
+                    listener: endConstructorReference(C, null, ;)
+                  ensureSemicolon(new)
+                  listener: endRedirectingFactoryBody(=, ;)
+                listener: endClassFactoryMethod(factory, factory, ;)
+              listener: endMember()
+            notEofOrValue(}, factory)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(factory)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFactoryMethod(;, DeclarationKind.Class, ;, null, null, null)
+                listener: beginFactoryMethod(;, null, null)
+                ensureIdentifier(factory, methodDeclaration)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(factory_redirection_generic, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(factory_redirection_generic)
+                  listener: handleNoTypeVariables(()
+                parseFormalParametersRequiredOpt(factory_redirection_generic, MemberKind.Factory)
+                  parseFormalParametersRest((, MemberKind.Factory)
+                    listener: beginFormalParameters((, MemberKind.Factory)
+                    listener: endFormalParameters(0, (, ), MemberKind.Factory)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseRedirectingFactoryBody())
+                  listener: beginRedirectingFactoryBody(=)
+                  parseConstructorReference(=, null)
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(C, constructorReference)
+                    listener: beginConstructorReference(C)
+                    parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                    listener: beginTypeArguments(<)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(>)
+                    listener: handleType(int, null)
+                    listener: endTypeArguments(1, <, >)
+                    ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                    listener: endConstructorReference(C, ., ;)
+                  ensureSemicolon(new)
+                  listener: endRedirectingFactoryBody(=, ;)
+                listener: endClassFactoryMethod(factory, factory, ;)
+              listener: endMember()
+            notEofOrValue(}, factory)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(factory)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFactoryMethod(;, DeclarationKind.Class, ;, null, null, null)
+                listener: beginFactoryMethod(;, null, null)
+                ensureIdentifier(factory, methodDeclaration)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(factory_redirection_prefixed, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(factory_redirection_prefixed)
+                  listener: handleNoTypeVariables(()
+                parseFormalParametersRequiredOpt(factory_redirection_prefixed, MemberKind.Factory)
+                  parseFormalParametersRest((, MemberKind.Factory)
+                    listener: beginFormalParameters((, MemberKind.Factory)
+                    listener: endFormalParameters(0, (, ), MemberKind.Factory)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseRedirectingFactoryBody())
+                  listener: beginRedirectingFactoryBody(=)
+                  parseConstructorReference(=, null)
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(prefix, constructorReference)
+                    listener: beginConstructorReference(prefix)
+                    parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                      parseQualifiedRest(prefix, constructorReferenceContinuation)
+                        ensureIdentifier(., constructorReferenceContinuation)
+                          listener: handleIdentifier(C, constructorReferenceContinuation)
+                        listener: handleQualified(.)
+                    listener: handleNoTypeArguments(.)
+                    ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                    listener: endConstructorReference(prefix, ., ;)
+                  ensureSemicolon(new)
+                  listener: endRedirectingFactoryBody(=, ;)
+                listener: endClassFactoryMethod(factory, factory, ;)
+              listener: endMember()
+            notEofOrValue(}, factory)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(factory)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFactoryMethod(;, DeclarationKind.Class, ;, null, null, null)
+                listener: beginFactoryMethod(;, null, null)
+                ensureIdentifier(factory, methodDeclaration)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(factory_redirection_prefixed_generic, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(factory_redirection_prefixed_generic)
+                  listener: handleNoTypeVariables(()
+                parseFormalParametersRequiredOpt(factory_redirection_prefixed_generic, MemberKind.Factory)
+                  parseFormalParametersRest((, MemberKind.Factory)
+                    listener: beginFormalParameters((, MemberKind.Factory)
+                    listener: endFormalParameters(0, (, ), MemberKind.Factory)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseRedirectingFactoryBody())
+                  listener: beginRedirectingFactoryBody(=)
+                  parseConstructorReference(=, null)
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(prefix, constructorReference)
+                    listener: beginConstructorReference(prefix)
+                    parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                      parseQualifiedRest(prefix, constructorReferenceContinuation)
+                        ensureIdentifier(., constructorReferenceContinuation)
+                          listener: handleIdentifier(C, constructorReferenceContinuation)
+                        listener: handleQualified(.)
+                    listener: beginTypeArguments(<)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(>)
+                    listener: handleType(int, null)
+                    listener: endTypeArguments(1, <, >)
+                    ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                    listener: endConstructorReference(prefix, ., ;)
+                  ensureSemicolon(new)
+                  listener: endRedirectingFactoryBody(=, ;)
+                listener: endClassFactoryMethod(factory, factory, ;)
+              listener: endMember()
+            notEofOrValue(}, D)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(D)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(.)
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'NoType', null, D, DeclarationKind.Class, D, false)
+                listener: beginMethod(null, null, null, null, null, D)
+                listener: handleNoType(;)
+                ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(super_invocation, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(super_invocation)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(super_invocation, D, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(super_invocation, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(super)
+                      parseSuperInitializerExpression(:)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        parseInitializerExpressionRest(:)
+                          parseExpression(:)
+                            parsePrecedenceExpression(:, 1, true)
+                              parseUnaryExpression(:, true)
+                                parsePrimary(:, expression)
+                                  parseSuperExpression(:, expression)
+                                    listener: handleSuperExpression(super, expression)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    isNextIdentifier(.)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(new, expressionContinuation)
+                                    listener: handleNoTypeArguments(()
+                                    parseArgumentsOpt(new)
+                                      parseArguments(new)
+                                        parseArgumentsRest(()
+                                          listener: beginArguments(()
+                                          listener: endArguments(0, (, ))
+                                    listener: handleSend(new, ;)
+                              listener: handleEndingBinaryExpression(.)
+                          listener: endInitializer(;)
+                    listener: endInitializers(1, :, ;)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: handleEmptyFunctionBody(;)
+                listener: endClassConstructor(null, D, (, :, ;)
+              listener: endMember()
+            notEofOrValue(}, D)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, D)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(D)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(.)
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'NoType', null, D, DeclarationKind.Class, D, false)
+                listener: beginMethod(null, null, null, null, null, D)
+                listener: handleNoType(;)
+                ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false)
+                  listener: handleIdentifier(D, methodDeclaration)
+                parseQualifiedRestOpt(D, methodDeclarationContinuation)
+                  parseQualifiedRest(D, methodDeclarationContinuation)
+                    ensureIdentifier(., methodDeclarationContinuation)
+                      listener: handleIdentifier(this_redirection, methodDeclarationContinuation)
+                    listener: handleQualified(.)
+                parseMethodTypeVar(this_redirection)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(this_redirection, D, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(this_redirection, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(this)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseThisExpression(:, expression)
+                                  listener: handleThisExpression(this, expression)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  isNextIdentifier(.)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(new, expressionContinuation)
+                                  listener: handleNoTypeArguments(()
+                                  parseArgumentsOpt(new)
+                                    parseArguments(new)
+                                      parseArgumentsRest(()
+                                        listener: beginArguments(()
+                                        listener: endArguments(0, (, ))
+                                  listener: handleSend(new, ;)
+                            listener: handleEndingBinaryExpression(.)
+                        listener: endInitializer(;)
+                    listener: endInitializers(1, :, ;)
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: handleEmptyFunctionBody(;)
+                listener: endClassConstructor(null, D, (, :, ;)
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 7, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(})
+      listener: beginTopLevelMember(var)
+      parseFields(}, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_const, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(})
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_const, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_const, constructor_invocation_const, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseConstExpression(=)
+                    listener: beginConstExpression(const)
+                    parseConstructorReference(const, null)
+                      ensureIdentifier(const, constructorReference)
+                        listener: handleIdentifier(C, constructorReference)
+                      listener: beginConstructorReference(C)
+                      parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                        parseQualifiedRest(C, constructorReferenceContinuation)
+                          rewriter()
+                          listener: handleNewAsIdentifier(new)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(new, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: handleNoTypeArguments(()
+                      listener: handleNoConstructorReferenceContinuationAfterTypeArguments(()
+                      listener: endConstructorReference(C, null, ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endConstExpression(const)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_const_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_const_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_const_generic, constructor_invocation_const_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseConstExpression(=)
+                    listener: beginConstExpression(const)
+                    parseConstructorReference(const, null)
+                      ensureIdentifier(const, constructorReference)
+                        listener: handleIdentifier(C, constructorReference)
+                      listener: beginConstructorReference(C)
+                      parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                      listener: beginTypeArguments(<)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(>)
+                      listener: handleType(int, null)
+                      listener: endTypeArguments(1, <, >)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(C, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endConstExpression(const)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_const_prefixed, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_const_prefixed, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_const_prefixed, constructor_invocation_const_prefixed, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseConstExpression(=)
+                    listener: beginConstExpression(const)
+                    parseConstructorReference(const, null)
+                      ensureIdentifier(const, constructorReference)
+                        listener: handleIdentifier(prefix, constructorReference)
+                      listener: beginConstructorReference(prefix)
+                      parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                        parseQualifiedRest(prefix, constructorReferenceContinuation)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(C, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: handleNoTypeArguments(.)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(prefix, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endConstExpression(const)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_const_prefixed_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_const_prefixed_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_const_prefixed_generic, constructor_invocation_const_prefixed_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseConstExpression(=)
+                    listener: beginConstExpression(const)
+                    parseConstructorReference(const, null)
+                      ensureIdentifier(const, constructorReference)
+                        listener: handleIdentifier(prefix, constructorReference)
+                      listener: beginConstructorReference(prefix)
+                      parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                        parseQualifiedRest(prefix, constructorReferenceContinuation)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(C, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: beginTypeArguments(<)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(>)
+                      listener: handleType(int, null)
+                      listener: endTypeArguments(1, <, >)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(prefix, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endConstExpression(const)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_explicit, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_explicit, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_explicit, constructor_invocation_explicit, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseNewExpression(=)
+                    isNextIdentifier(new)
+                    listener: beginNewExpression(new)
+                    parseConstructorReference(new, null)
+                      ensureIdentifier(new, constructorReference)
+                        listener: handleIdentifier(C, constructorReference)
+                      listener: beginConstructorReference(C)
+                      parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                        parseQualifiedRest(C, constructorReferenceContinuation)
+                          rewriter()
+                          listener: handleNewAsIdentifier(new)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(new, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: handleNoTypeArguments(()
+                      listener: handleNoConstructorReferenceContinuationAfterTypeArguments(()
+                      listener: endConstructorReference(C, null, ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endNewExpression(new)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_explicit_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_explicit_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_explicit_generic, constructor_invocation_explicit_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseNewExpression(=)
+                    isNextIdentifier(new)
+                    listener: beginNewExpression(new)
+                    parseConstructorReference(new, null)
+                      ensureIdentifier(new, constructorReference)
+                        listener: handleIdentifier(C, constructorReference)
+                      listener: beginConstructorReference(C)
+                      parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                      listener: beginTypeArguments(<)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(>)
+                      listener: handleType(int, null)
+                      listener: endTypeArguments(1, <, >)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(C, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endNewExpression(new)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_explicit_prefixed, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_explicit_prefixed, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_explicit_prefixed, constructor_invocation_explicit_prefixed, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseNewExpression(=)
+                    isNextIdentifier(new)
+                    listener: beginNewExpression(new)
+                    parseConstructorReference(new, null)
+                      ensureIdentifier(new, constructorReference)
+                        listener: handleIdentifier(prefix, constructorReference)
+                      listener: beginConstructorReference(prefix)
+                      parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                        parseQualifiedRest(prefix, constructorReferenceContinuation)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(C, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: handleNoTypeArguments(.)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(prefix, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endNewExpression(new)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_explicit_prefixed_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_explicit_prefixed_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_explicit_prefixed_generic, constructor_invocation_explicit_prefixed_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseNewExpression(=)
+                    isNextIdentifier(new)
+                    listener: beginNewExpression(new)
+                    parseConstructorReference(new, null)
+                      ensureIdentifier(new, constructorReference)
+                        listener: handleIdentifier(prefix, constructorReference)
+                      listener: beginConstructorReference(prefix)
+                      parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                        parseQualifiedRest(prefix, constructorReferenceContinuation)
+                          ensureIdentifier(., constructorReferenceContinuation)
+                            listener: handleIdentifier(C, constructorReferenceContinuation)
+                          listener: handleQualified(.)
+                      listener: beginTypeArguments(<)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(>)
+                      listener: handleType(int, null)
+                      listener: endTypeArguments(1, <, >)
+                      ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                        rewriter()
+                        listener: handleNewAsIdentifier(new)
+                        listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                      listener: endConstructorReference(prefix, ., ()
+                    parseConstructorInvocationArguments(new)
+                      parseArgumentsRest(()
+                        listener: beginArguments(()
+                        listener: endArguments(0, (, ))
+                    listener: endNewExpression(new)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_implicit, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_implicit, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_implicit, constructor_invocation_implicit, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(C, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(C)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(C, .)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(new)
+                      parseArguments(new)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_implicit_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_implicit_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_implicit_generic, constructor_invocation_implicit_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parseImplicitCreationExpression(=, Instance of 'SimpleTypeArgument1')
+                  listener: beginImplicitCreationExpression(=)
+                  parseConstructorReference(=, Instance of 'SimpleTypeArgument1')
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(C, constructorReference)
+                    listener: beginConstructorReference(C)
+                    parseQualifiedRestOpt(C, constructorReferenceContinuation)
+                    listener: beginTypeArguments(<)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(>)
+                    listener: handleType(int, null)
+                    listener: endTypeArguments(1, <, >)
+                    ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                    listener: endConstructorReference(C, ., ()
+                  parseConstructorInvocationArguments(new)
+                    parseArgumentsRest(()
+                      listener: beginArguments(()
+                      listener: endArguments(0, (, ))
+                  listener: endImplicitCreationExpression(=)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_implicit_prefixed, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_implicit_prefixed, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_implicit_prefixed, constructor_invocation_implicit_prefixed, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(prefix, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(prefix)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(prefix, .)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(C, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(C)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(C, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(new)
+                      parseArguments(new)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_invocation_implicit_prefixed_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_invocation_implicit_prefixed_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_invocation_implicit_prefixed_generic, constructor_invocation_implicit_prefixed_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parseImplicitCreationExpression(=, Instance of 'SimpleTypeArgument1')
+                  listener: beginImplicitCreationExpression(=)
+                  parseConstructorReference(=, Instance of 'SimpleTypeArgument1')
+                    ensureIdentifier(=, constructorReference)
+                      listener: handleIdentifier(prefix, constructorReference)
+                    listener: beginConstructorReference(prefix)
+                    parseQualifiedRestOpt(prefix, constructorReferenceContinuation)
+                      parseQualifiedRest(prefix, constructorReferenceContinuation)
+                        ensureIdentifier(., constructorReferenceContinuation)
+                          listener: handleIdentifier(C, constructorReferenceContinuation)
+                        listener: handleQualified(.)
+                    listener: beginTypeArguments(<)
+                    listener: handleIdentifier(int, typeReference)
+                    listener: handleNoTypeArguments(>)
+                    listener: handleType(int, null)
+                    listener: endTypeArguments(1, <, >)
+                    ensureIdentifier(., constructorReferenceContinuationAfterTypeArguments)
+                      rewriter()
+                      listener: handleNewAsIdentifier(new)
+                      listener: handleIdentifier(new, constructorReferenceContinuationAfterTypeArguments)
+                    listener: endConstructorReference(prefix, ., ()
+                  parseConstructorInvocationArguments(new)
+                    parseArgumentsRest(()
+                      listener: beginArguments(()
+                      listener: endArguments(0, (, ))
+                  listener: endImplicitCreationExpression(=)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff, constructor_tearoff, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(C, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(C)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(C, .)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(;)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(;)
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_generic, constructor_tearoff_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(C, expression)
+                      listener: handleNoTypeArguments(<)
+                      parseArgumentsOpt(C)
+                        listener: handleNoArguments(<)
+                      listener: handleSend(C, <)
+              listener: beginTypeArguments(<)
+              listener: handleIdentifier(int, typeReference)
+              listener: handleNoTypeArguments(>)
+              listener: handleType(int, null)
+              listener: endTypeArguments(1, <, >)
+              listener: handleTypeArgumentApplication(<)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(;)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(;)
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_generic_method_invocation, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_generic_method_invocation, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_generic_method_invocation, constructor_tearoff_generic_method_invocation, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(C, expression)
+                      listener: handleNoTypeArguments(<)
+                      parseArgumentsOpt(C)
+                        listener: handleNoArguments(<)
+                      listener: handleSend(C, <)
+              listener: beginTypeArguments(<)
+              listener: handleIdentifier(int, typeReference)
+              listener: handleNoTypeArguments(>)
+              listener: handleType(int, null)
+              listener: endTypeArguments(1, <, >)
+              listener: handleTypeArgumentApplication(<)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(new, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(toString, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(toString)
+                      parseArguments(toString)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(toString, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_method_invocation, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_method_invocation, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_method_invocation, constructor_tearoff_method_invocation, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(C, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(C)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(C, .)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(new, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(toString, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(toString)
+                      parseArguments(toString)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(toString, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_prefixed, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_prefixed, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_prefixed, constructor_tearoff_prefixed, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(prefix, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(prefix)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(prefix, .)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(C, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(C)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(C, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(;)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(;)
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_prefixed_generic, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_prefixed_generic, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_prefixed_generic, constructor_tearoff_prefixed_generic, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(prefix, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(prefix)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(prefix, .)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(C, expressionContinuation)
+                    listener: handleNoTypeArguments(<)
+                    parseArgumentsOpt(C)
+                      listener: handleNoArguments(<)
+                    listener: handleSend(C, <)
+              listener: handleEndingBinaryExpression(.)
+              listener: beginTypeArguments(<)
+              listener: handleIdentifier(int, typeReference)
+              listener: handleNoTypeArguments(>)
+              listener: handleType(int, null)
+              listener: endTypeArguments(1, <, >)
+              listener: handleTypeArgumentApplication(<)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(;)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(;)
+                    listener: handleSend(new, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_prefixed_generic_method_invocation, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_prefixed_generic_method_invocation, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_prefixed_generic_method_invocation, constructor_tearoff_prefixed_generic_method_invocation, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(prefix, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(prefix)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(prefix, .)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(C, expressionContinuation)
+                    listener: handleNoTypeArguments(<)
+                    parseArgumentsOpt(C)
+                      listener: handleNoArguments(<)
+                    listener: handleSend(C, <)
+              listener: handleEndingBinaryExpression(.)
+              listener: beginTypeArguments(<)
+              listener: handleIdentifier(int, typeReference)
+              listener: handleNoTypeArguments(>)
+              listener: handleType(int, null)
+              listener: endTypeArguments(1, <, >)
+              listener: handleTypeArgumentApplication(<)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(new, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(toString, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(toString)
+                      parseArguments(toString)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(toString, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration(var)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(var)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(var)
+      parseFields(;, null, null, null, null, null, var, var, Instance of 'NoType', constructor_tearoff_prefixed_method_invocation, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleNoType(var)
+        ensureIdentifierPotentiallyRecovered(var, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(constructor_tearoff_prefixed_method_invocation, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(constructor_tearoff_prefixed_method_invocation, constructor_tearoff_prefixed_method_invocation, null, null, null, var, DeclarationKind.TopLevel, null)
+          listener: beginFieldInitializer(=)
+          parseExpression(=)
+            parsePrecedenceExpression(=, 1, true)
+              parseUnaryExpression(=, true)
+                parsePrimary(=, expression)
+                  parseSendOrFunctionLiteral(=, expression)
+                    parseSend(=, expression)
+                      isNextIdentifier(=)
+                      ensureIdentifier(=, expression)
+                        listener: handleIdentifier(prefix, expression)
+                      listener: handleNoTypeArguments(.)
+                      parseArgumentsOpt(prefix)
+                        listener: handleNoArguments(.)
+                      listener: handleSend(prefix, .)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(C, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(C)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(C, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                rewriter()
+                listener: handleNewAsIdentifier(new)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(new, expressionContinuation)
+                    listener: handleNoTypeArguments(.)
+                    parseArgumentsOpt(new)
+                      listener: handleNoArguments(.)
+                    listener: handleSend(new, .)
+              listener: handleEndingBinaryExpression(.)
+              parsePrimary(., expressionContinuation)
+                parseSendOrFunctionLiteral(., expressionContinuation)
+                  looksLikeFunctionBody(;)
+                  parseSend(., expressionContinuation)
+                    isNextIdentifier(.)
+                    ensureIdentifier(., expressionContinuation)
+                      listener: handleIdentifier(toString, expressionContinuation)
+                    listener: handleNoTypeArguments(()
+                    parseArgumentsOpt(toString)
+                      parseArguments(toString)
+                        parseArgumentsRest(()
+                          listener: beginArguments(()
+                          listener: endArguments(0, (, ))
+                    listener: handleSend(toString, ;)
+              listener: handleEndingBinaryExpression(.)
+          listener: endFieldInitializer(=, ;)
+        listener: endTopLevelFields(null, null, null, null, var, 1, var, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(22, )
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.parser.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.parser.expect
new file mode 100644
index 0000000..f91e9be
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.parser.expect
@@ -0,0 +1,83 @@
+NOTICE: Stream was rewritten by parser!
+
+class C {
+C.new();
+
+
+
+C.constructor_field_initializer() : =this.{}new operator= (){}null;
+}
+
+class D {
+factory D.new() => C();
+factory D.factory_redirection() = C.new;
+factory D.factory_redirection_generic() = C<int>.new;
+factory D.factory_redirection_prefixed() = prefix.C.new;
+factory D.factory_redirection_prefixed_generic() = prefix.C<int>.new;
+D.super_invocation() : super.new();
+D.this_redirection() : this.new();
+}
+
+var constructor_invocation_const = const C.new();
+var constructor_invocation_const_generic = const C<int>.new();
+var constructor_invocation_const_prefixed = const prefix.C.new();
+var constructor_invocation_const_prefixed_generic = const prefix.C<int>.new();
+var constructor_invocation_explicit = new C.new();
+var constructor_invocation_explicit_generic = new C<int>.new();
+var constructor_invocation_explicit_prefixed = new prefix.C.new();
+var constructor_invocation_explicit_prefixed_generic = new prefix.C<int>.new();
+var constructor_invocation_implicit = C.new();
+var constructor_invocation_implicit_generic = C<int>.new();
+var constructor_invocation_implicit_prefixed = prefix.C.new();
+var constructor_invocation_implicit_prefixed_generic = prefix.C<int>.new();
+var constructor_tearoff = C.new;
+var constructor_tearoff_generic = C<int>.new;
+var constructor_tearoff_generic_method_invocation = C<int>.new.toString();
+var constructor_tearoff_method_invocation = C.new.toString();
+var constructor_tearoff_prefixed = prefix.C.new;
+var constructor_tearoff_prefixed_generic = prefix.C<int>.new;
+var constructor_tearoff_prefixed_generic_method_invocation =
+prefix.C<int>.new.toString();
+var constructor_tearoff_prefixed_method_invocation = prefix.C.new.toString();
+
+
+class[KeywordToken] C[StringToken] {[BeginToken]
+C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+
+
+
+C[StringToken].[SimpleToken]constructor_field_initializer[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] [SyntheticStringToken]=[SyntheticToken]this[KeywordToken].[SimpleToken][SyntheticStringToken]{[SyntheticBeginToken]}[SyntheticToken]new[KeywordToken] operator[SyntheticKeywordToken]=[SimpleToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken]null[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] D[StringToken] {[BeginToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken] =>[SimpleToken] C[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] C[StringToken].[SimpleToken]new[StringToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_generic[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_prefixed[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_prefixed_generic[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken];[SimpleToken]
+D[StringToken].[SimpleToken]super_invocation[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] super[KeywordToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+D[StringToken].[SimpleToken]this_redirection[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] this[KeywordToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+var[KeywordToken] constructor_invocation_const[StringToken] =[SimpleToken] const[KeywordToken] C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_generic[StringToken] =[SimpleToken] const[KeywordToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_prefixed[StringToken] =[SimpleToken] const[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_prefixed_generic[StringToken] =[SimpleToken] const[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit[StringToken] =[SimpleToken] new[KeywordToken] C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_generic[StringToken] =[SimpleToken] new[KeywordToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_prefixed[StringToken] =[SimpleToken] new[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_prefixed_generic[StringToken] =[SimpleToken] new[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_generic[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_prefixed[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_prefixed_generic[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[StringToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_generic[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_generic_method_invocation[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_method_invocation[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[StringToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_generic[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_generic_method_invocation[StringToken] =[SimpleToken]
+prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[StringToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_method_invocation[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[StringToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/new_as_identifier.dart.scanner.expect b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.scanner.expect
new file mode 100644
index 0000000..aac6a0f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/new_as_identifier.dart.scanner.expect
@@ -0,0 +1,81 @@
+class C {
+C.new();
+
+
+
+C.constructor_field_initializer() : this.new = null;
+}
+
+class D {
+factory D.new() => C();
+factory D.factory_redirection() = C.new;
+factory D.factory_redirection_generic() = C<int>.new;
+factory D.factory_redirection_prefixed() = prefix.C.new;
+factory D.factory_redirection_prefixed_generic() = prefix.C<int>.new;
+D.super_invocation() : super.new();
+D.this_redirection() : this.new();
+}
+
+var constructor_invocation_const = const C.new();
+var constructor_invocation_const_generic = const C<int>.new();
+var constructor_invocation_const_prefixed = const prefix.C.new();
+var constructor_invocation_const_prefixed_generic = const prefix.C<int>.new();
+var constructor_invocation_explicit = new C.new();
+var constructor_invocation_explicit_generic = new C<int>.new();
+var constructor_invocation_explicit_prefixed = new prefix.C.new();
+var constructor_invocation_explicit_prefixed_generic = new prefix.C<int>.new();
+var constructor_invocation_implicit = C.new();
+var constructor_invocation_implicit_generic = C<int>.new();
+var constructor_invocation_implicit_prefixed = prefix.C.new();
+var constructor_invocation_implicit_prefixed_generic = prefix.C<int>.new();
+var constructor_tearoff = C.new;
+var constructor_tearoff_generic = C<int>.new;
+var constructor_tearoff_generic_method_invocation = C<int>.new.toString();
+var constructor_tearoff_method_invocation = C.new.toString();
+var constructor_tearoff_prefixed = prefix.C.new;
+var constructor_tearoff_prefixed_generic = prefix.C<int>.new;
+var constructor_tearoff_prefixed_generic_method_invocation =
+prefix.C<int>.new.toString();
+var constructor_tearoff_prefixed_method_invocation = prefix.C.new.toString();
+
+
+class[KeywordToken] C[StringToken] {[BeginToken]
+C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+
+
+
+C[StringToken].[SimpleToken]constructor_field_initializer[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] this[KeywordToken].[SimpleToken]new[KeywordToken] =[SimpleToken] null[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] D[StringToken] {[BeginToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken] =>[SimpleToken] C[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] C[StringToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_generic[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_prefixed[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+factory[KeywordToken] D[StringToken].[SimpleToken]factory_redirection_prefixed_generic[StringToken]([BeginToken])[SimpleToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+D[StringToken].[SimpleToken]super_invocation[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] super[KeywordToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+D[StringToken].[SimpleToken]this_redirection[StringToken]([BeginToken])[SimpleToken] :[SimpleToken] this[KeywordToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+var[KeywordToken] constructor_invocation_const[StringToken] =[SimpleToken] const[KeywordToken] C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_generic[StringToken] =[SimpleToken] const[KeywordToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_prefixed[StringToken] =[SimpleToken] const[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_const_prefixed_generic[StringToken] =[SimpleToken] const[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit[StringToken] =[SimpleToken] new[KeywordToken] C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_generic[StringToken] =[SimpleToken] new[KeywordToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_prefixed[StringToken] =[SimpleToken] new[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_explicit_prefixed_generic[StringToken] =[SimpleToken] new[KeywordToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_generic[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_prefixed[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_invocation_implicit_prefixed_generic[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_generic[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_generic_method_invocation[StringToken] =[SimpleToken] C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_method_invocation[StringToken] =[SimpleToken] C[StringToken].[SimpleToken]new[KeywordToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_generic[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_generic_method_invocation[StringToken] =[SimpleToken]
+prefix[StringToken].[SimpleToken]C[StringToken]<[BeginToken]int[StringToken]>[SimpleToken].[SimpleToken]new[KeywordToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] constructor_tearoff_prefixed_method_invocation[StringToken] =[SimpleToken] prefix[StringToken].[SimpleToken]C[StringToken].[SimpleToken]new[KeywordToken].[SimpleToken]toString[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index ca40095..824db8e 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -2214,4 +2214,9 @@
     seen(openAngleBracket);
     doPrint('handleTypeArgumentApplication(' '$openAngleBracket)');
   }
+
+  void handleNewAsIdentifier(Token token) {
+    seen(token);
+    doPrint('handleNewAsIdentifier(' '$token)');
+  }
 }
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index dab3f99..2926fdd 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -202,6 +202,7 @@
 class6b
 clazz
 cli
+client's
 clil
 clock
 cls
@@ -876,6 +877,7 @@
 perf
 permanently
 permit
+permits
 physically
 pi
 picking
diff --git a/pkg/wasm/analysis_options.yaml b/pkg/wasm/analysis_options.yaml
index 84a5e26..486705d 100644
--- a/pkg/wasm/analysis_options.yaml
+++ b/pkg/wasm/analysis_options.yaml
@@ -1 +1 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
+include: package:pedantic/analysis_options.1.9.0.yaml
diff --git a/pkg/wasm/bin/setup.dart b/pkg/wasm/bin/setup.dart
index 868c189..badaac9 100644
--- a/pkg/wasm/bin/setup.dart
+++ b/pkg/wasm/bin/setup.dart
@@ -45,7 +45,7 @@
       return root.resolve('.dart_tool/wasm/');
     }
   } while (root != (root = root.resolve('..')));
-  throw Exception(".dart_tool/package_config.json not found");
+  throw Exception('.dart_tool/package_config.json not found');
 }
 
 String getOutLib(String target) {
@@ -183,15 +183,7 @@
   // Link wasmer, dart_api_dl, and finalizers to create the output library.
   await run('clang++', [
     '-shared',
-    '-Wl,--no-as-needed',
-    '-Wl,--fatal-warnings',
-    '-Wl,-z,now',
-    '-Wl,-z,noexecstack',
-    '-Wl,-z,relro',
-    '-Wl,--build-id=none',
     '-fPIC',
-    '-Wl,-O1',
-    '-Wl,--gc-sections',
     '-target',
     target,
     outDir.resolve('dart_api_dl.o').path,
diff --git a/pkg/wasm/example/README.md b/pkg/wasm/example/README.md
index c809dc66..e6ff491 100644
--- a/pkg/wasm/example/README.md
+++ b/pkg/wasm/example/README.md
@@ -1,29 +1,49 @@
-# Example usage of package:wasm
+# Example usage of `package:wasm`
 
-This example demonstrates how to use package:wasm to run a wasm build of the [Brotli compression library](https://github.com/google/brotli).
+This example demonstrates how to use package:wasm to run a wasm build of the
+[Brotli compression library](https://github.com/google/brotli).
 
 ### Running the example
 
 `dart brotli.dart lipsum.txt`
 
-This will compress lipsum.txt, report the compression ratio, then decompress it and verify that the result matches the input.
+This will compress lipsum.txt, report the compression ratio, then decompress it
+and verify that the result matches the input.
 
 ### Generating wasm code
 
-libbrotli.wasm was built by cloning the [Brotli repo](https://github.com/google/brotli), and compiling it using [wasienv](https://github.com/wasienv/wasienv).
+`libbrotli.wasm` was built by cloning the
+[Brotli repo](https://github.com/google/brotli), and compiling it using
+[wasienv](https://github.com/wasienv/wasienv).
 
-There are several ways of building wasm code. The most important difference between the tool sets is how the wasm code they generate interacts with the OS. For very simple code this difference doesn't matter. But if the library does any sort of OS interaction, such as file IO, or even using malloc, it will need to use either Emscripten or WASI for that interaction. package:wasm only supports WASI at the moment.
+There are several ways of building wasm code. The most important difference
+between the tool sets is how the wasm code they generate interacts with the OS.
+For very simple code this difference doesn't matter. But if the library does any
+sort of OS interaction, such as file IO, or even using malloc, it will need to
+use either Emscripten or WASI for that interaction. package:wasm only supports
+WASI at the moment.
 
-To target WASI, one option is to use [wasi-libc](https://github.com/WebAssembly/wasi-libc) and a recent version of clang. Set the target to `--target=wasm32-unknown-wasi` and the `--sysroot` to wasi-libc.
+To target WASI, one option is to use
+[wasi-libc](https://github.com/WebAssembly/wasi-libc) and a recent version of
+clang. Set the target to `--target=wasm32-unknown-wasi` and the `--sysroot` to
+wasi-libc.
 
-Another option is to build using [wasienv](https://github.com/wasienv/wasienv), which is a set of tools that are essentially just an ergonomic wrapper around the clang + wasi-libc approach. This is how libbrotli.wasm was built:
+Another option is to build using [wasienv](https://github.com/wasienv/wasienv),
+which is a set of tools that are essentially just an ergonomic wrapper around
+the clang + wasi-libc approach. This is how libbrotli.wasm was built:
 
-1. Install [wasienv](https://github.com/wasienv/wasienv) and clone the [Brotli repo](https://github.com/google/brotli).
+1. Install [wasienv](https://github.com/wasienv/wasienv) and clone the
+   [Brotli repo](https://github.com/google/brotli).
 2. Compile every .c file in brotli/c/common/, dec/, and enc/, using wasicc:
-`wasicc -c foo.c -o out/foo.o -I c/include`
+   `wasicc -c foo.c -o out/foo.o -I c/include`
 3. Link all the .o files together using wasild:
-`wasild --no-entry --export=bar out/foo.o $wasienv_sysroot/lib/wasm32-wasi/libc.a`
-The `--no-entry` flag tells the linker to ignore the fact that there's no `main()` function, which is important for libraries.
-`--export=bar` will export the `bar()` function from the library, so that it can be found by package:wasm. For libbrotli.wasm, every function in c/include/brotli/encode.h and decode.h was exported.
-Brotli used functions from libc, so the wasm version of libc that comes with wasienv was also linked in.
-If there are still undefined symbols after linking in the wasi libraries, the `--allow-undefined` flag tells the linker to treat undefined symbols as function imports. These functions can then be supplied from Dart code.
+   `wasild --no-entry --export=bar out/foo.o $wasienv_sysroot/lib/wasm32-wasi/libc.a`
+   The `--no-entry` flag tells the linker to ignore the fact that there's no
+   `main()` function, which is important for libraries. `--export=bar` will
+   export the `bar()` function from the library, so that it can be found by
+   package:wasm. For libbrotli.wasm, every function in c/include/brotli/encode.h
+   and decode.h was exported. Brotli used functions from libc, so the wasm
+   version of libc that comes with wasienv was also linked in. If there are
+   still undefined symbols after linking in the wasi libraries, the
+   `--allow-undefined` flag tells the linker to treat undefined symbols as
+   function imports. These functions can then be supplied from Dart code.
diff --git a/pkg/wasm/example/brotli.dart b/pkg/wasm/example/brotli.dart
index d8cea14..726c333 100644
--- a/pkg/wasm/example/brotli.dart
+++ b/pkg/wasm/example/brotli.dart
@@ -6,17 +6,17 @@
 // library. Usage:
 // dart brotli.dart input.txt
 
-import "dart:io";
-import "dart:typed_data";
+import 'dart:io';
+import 'dart:typed_data';
 
-import "package:wasm/wasm.dart";
+import 'package:wasm/wasm.dart';
 
 // Brotli compression parameters.
 const int kDefaultQuality = 11;
 const int kDefaultWindow = 22;
 const int kDefaultMode = 0;
 
-main(List<String> args) {
+void main(List<String> args) {
   var brotliPath = Platform.script.resolve('libbrotli.wasm');
   var moduleData = File(brotliPath.path).readAsBytesSync();
   var module = WasmModule(moduleData);
@@ -24,12 +24,12 @@
 
   var instance = module.instantiate().enableWasi().build();
   var memory = instance.memory;
-  var compress = instance.lookupFunction("BrotliEncoderCompress");
-  var decompress = instance.lookupFunction("BrotliDecoderDecompress");
+  var compress = instance.lookupFunction('BrotliEncoderCompress');
+  var decompress = instance.lookupFunction('BrotliDecoderDecompress');
 
-  print("Loading ${args[0]}");
+  print('Loading ${args[0]}');
   var inputData = File(args[0]).readAsBytesSync();
-  print("Input size: ${inputData.length} bytes");
+  print('Input size: ${inputData.length} bytes');
 
   // Grow the module's memory to get unused space to put our data.
   // [initial memory][input data][output data][size][decoded data][size]
@@ -48,36 +48,36 @@
   memoryView.setRange(
       outSizePtr, outSizePtr + 4, sizeBytes.buffer.asUint8List());
 
-  print("\nCompressing...");
+  print('\nCompressing...');
   var status = compress(kDefaultQuality, kDefaultWindow, kDefaultMode,
       inputData.length, inputPtr, outSizePtr, outputPtr);
-  print("Compression status: $status");
+  print('Compression status: $status');
 
   var compressedSize =
       ByteData.sublistView(memoryView, outSizePtr, outSizePtr + 4)
           .getUint32(0, Endian.host);
-  print("Compressed size: $compressedSize bytes");
+  print('Compressed size: $compressedSize bytes');
   var spaceSaving = 100 * (1 - compressedSize / inputData.length);
-  print("Space saving: ${spaceSaving.toStringAsFixed(2)}%");
+  print('Space saving: ${spaceSaving.toStringAsFixed(2)}%');
 
   var decSizeBytes = ByteData(4);
   decSizeBytes.setUint32(0, inputData.length, Endian.host);
   memoryView.setRange(
       decSizePtr, decSizePtr + 4, decSizeBytes.buffer.asUint8List());
 
-  print("\nDecompressing...");
+  print('\nDecompressing...');
   status = decompress(compressedSize, outputPtr, decSizePtr, decodedPtr);
-  print("Decompression status: $status");
+  print('Decompression status: $status');
 
   var decompressedSize =
       ByteData.sublistView(memoryView, decSizePtr, decSizePtr + 4)
           .getUint32(0, Endian.host);
-  print("Decompressed size: $decompressedSize bytes");
+  print('Decompressed size: $decompressedSize bytes');
 
-  print("\nVerifying decompression...");
+  print('\nVerifying decompression...');
   assert(inputData.length == decompressedSize);
   for (var i = 0; i < inputData.length; ++i) {
     assert(inputData[i] == memoryView[decodedPtr + i]);
   }
-  print("Decompression succeeded :)");
+  print('Decompression succeeded :)');
 }
diff --git a/pkg/wasm/lib/src/function.dart b/pkg/wasm/lib/src/function.dart
index bc5e44c..3816e59 100644
--- a/pkg/wasm/lib/src/function.dart
+++ b/pkg/wasm/lib/src/function.dart
@@ -11,12 +11,12 @@
 
 /// WasmFunction is a callable function from a WasmInstance.
 class WasmFunction {
-  String _name;
-  Pointer<WasmerFunc> _func;
-  List<int> _argTypes;
-  int _returnType;
-  Pointer<WasmerValVec> _args = calloc<WasmerValVec>();
-  Pointer<WasmerValVec> _results = calloc<WasmerValVec>();
+  final String _name;
+  final Pointer<WasmerFunc> _func;
+  final List<int> _argTypes;
+  final int _returnType;
+  final Pointer<WasmerValVec> _args = calloc<WasmerValVec>();
+  final Pointer<WasmerValVec> _results = calloc<WasmerValVec>();
 
   WasmFunction(this._name, this._func, this._argTypes, this._returnType) {
     _args.ref.length = _argTypes.length;
@@ -30,6 +30,7 @@
     }
   }
 
+  @override
   String toString() {
     return WasmRuntime.getSignatureString(_name, _argTypes, _returnType);
   }
@@ -58,11 +59,11 @@
 
   dynamic apply(List<dynamic> args) {
     if (args.length != _argTypes.length) {
-      throw ArgumentError("Wrong number arguments for WASM function: $this");
+      throw ArgumentError('Wrong number arguments for WASM function: $this');
     }
     for (var i = 0; i < args.length; ++i) {
       if (!_fillArg(args[i], i)) {
-        throw ArgumentError("Bad argument type for WASM function: $this");
+        throw ArgumentError('Bad argument type for WASM function: $this');
       }
     }
     WasmRuntime().call(_func, _args, _results, toString());
@@ -84,6 +85,7 @@
     }
   }
 
+  @override
   dynamic noSuchMethod(Invocation invocation) {
     if (invocation.memberName == #call) {
       return apply(invocation.positionalArguments);
diff --git a/pkg/wasm/lib/src/module.dart b/pkg/wasm/lib/src/module.dart
index 5687b2e..8e71597 100644
--- a/pkg/wasm/lib/src/module.dart
+++ b/pkg/wasm/lib/src/module.dart
@@ -42,11 +42,11 @@
     var runtime = WasmRuntime();
     var imports = runtime.importDescriptors(_module);
     for (var imp in imports) {
-      description.write("import $imp\n");
+      description.write('import $imp\n');
     }
     var exports = runtime.exportDescriptors(_module);
     for (var exp in exports) {
-      description.write("export $exp\n");
+      description.write('export $exp\n');
     }
     return description.toString();
   }
@@ -83,7 +83,7 @@
 
   static void _call(Pointer<_WasmFnImport> imp, Pointer<WasmerValVec> rawArgs,
       Pointer<WasmerValVec> rawResult) {
-    Function fn = _wasmFnImportToFn[imp.address] as Function;
+    var fn = _wasmFnImportToFn[imp.address] as Function;
     var args = [];
     for (var i = 0; i < rawArgs.ref.length; ++i) {
       args.add(rawArgs.ref.data[i].toDynamic);
@@ -116,12 +116,12 @@
 /// WasmInstanceBuilder is used collect all the imports that a WasmModule
 /// requires before it is instantiated.
 class WasmInstanceBuilder {
-  WasmModule _module;
+  final WasmModule _module;
   late List<WasmImportDescriptor> _importDescs;
-  Map<String, int> _importIndex;
-  Pointer<WasmerExternVec> _imports = calloc<WasmerExternVec>();
+  final Map<String, int> _importIndex;
+  final Pointer<WasmerExternVec> _imports = calloc<WasmerExternVec>();
   Pointer<WasmerWasiEnv> _wasiEnv = nullptr;
-  _WasmImportOwner _importOwner = _WasmImportOwner();
+  final _WasmImportOwner _importOwner = _WasmImportOwner();
 
   WasmInstanceBuilder(this._module) : _importIndex = {} {
     _importDescs = WasmRuntime().importDescriptors(_module._module);
@@ -129,17 +129,17 @@
     _imports.ref.data = calloc<Pointer<WasmerExtern>>(_importDescs.length);
     for (var i = 0; i < _importDescs.length; ++i) {
       var imp = _importDescs[i];
-      _importIndex["${imp.moduleName}::${imp.name}"] = i;
+      _importIndex['${imp.moduleName}::${imp.name}'] = i;
       _imports.ref.data[i] = nullptr;
     }
   }
 
   int _getIndex(String moduleName, String name) {
-    var index = _importIndex["${moduleName}::${name}"];
+    var index = _importIndex['${moduleName}::${name}'];
     if (index == null) {
-      throw Exception("Import not found: ${moduleName}::${name}");
+      throw Exception('Import not found: ${moduleName}::${name}');
     } else if (_imports.ref.data[index] != nullptr) {
-      throw Exception("Import already filled: ${moduleName}::${name}");
+      throw Exception('Import already filled: ${moduleName}::${name}');
     } else {
       return index;
     }
@@ -151,7 +151,7 @@
     var index = _getIndex(moduleName, name);
     var imp = _importDescs[index];
     if (imp.kind != WasmerExternKindMemory) {
-      throw Exception("Import is not a memory: $imp");
+      throw Exception('Import is not a memory: $imp');
     }
     _imports.ref.data[index] = WasmRuntime().memoryToExtern(memory._mem);
     return this;
@@ -164,7 +164,7 @@
     var runtime = WasmRuntime();
 
     if (imp.kind != WasmerExternKindFunction) {
-      throw Exception("Import is not a function: $imp");
+      throw Exception('Import is not a function: $imp');
     }
 
     var returnType = runtime.getReturnType(imp.funcType);
@@ -187,7 +187,7 @@
   WasmInstanceBuilder enableWasi(
       {bool captureStdout = false, bool captureStderr = false}) {
     if (_wasiEnv != nullptr) {
-      throw Exception("WASI is already enabled.");
+      throw Exception('WASI is already enabled.');
     }
     var runtime = WasmRuntime();
     var config = runtime.newWasiConfig();
@@ -202,7 +202,7 @@
   WasmInstance build() {
     for (var i = 0; i < _importDescs.length; ++i) {
       if (_imports.ref.data[i] == nullptr) {
-        throw Exception("Missing import: ${_importDescs[i]}");
+        throw Exception('Missing import: ${_importDescs[i]}');
       }
     }
     return WasmInstance(_module, _imports, _wasiEnv, _importOwner);
@@ -211,14 +211,14 @@
 
 /// WasmInstance is an instantiated WasmModule.
 class WasmInstance {
-  WasmModule _module;
+  final WasmModule _module;
   late Pointer<WasmerInstance> _instance;
   Pointer<WasmerMemory>? _exportedMemory;
-  Pointer<WasmerWasiEnv> _wasiEnv;
+  final Pointer<WasmerWasiEnv> _wasiEnv;
   Stream<List<int>>? _stdout;
   Stream<List<int>>? _stderr;
-  Map<String, WasmFunction> _functions = {};
-  _WasmImportOwner _importOwner;
+  final Map<String, WasmFunction> _functions = {};
+  final _WasmImportOwner _importOwner;
 
   WasmInstance(this._module, Pointer<WasmerExternVec> imports, this._wasiEnv,
       this._importOwner) {
@@ -231,7 +231,7 @@
     for (var i = 0; i < exports.ref.length; ++i) {
       var e = exports.ref.data[i];
       var kind = runtime.externKind(exports.ref.data[i]);
-      String name = exportDescs[i].name;
+      var name = exportDescs[i].name;
       if (kind == WasmerExternKindFunction) {
         var f = runtime.externToFunction(e);
         var ft = exportDescs[i].funcType;
@@ -257,7 +257,7 @@
   /// Returns the memory exported from this instance.
   WasmMemory get memory {
     if (_exportedMemory == null) {
-      throw Exception("Wasm module did not export its memory.");
+      throw Exception('Wasm module did not export its memory.');
     }
     return WasmMemory._fromExport(_exportedMemory as Pointer<WasmerMemory>);
   }
diff --git a/pkg/wasm/lib/src/runtime.dart b/pkg/wasm/lib/src/runtime.dart
index 1db3ef4..dbdb986 100644
--- a/pkg/wasm/lib/src/runtime.dart
+++ b/pkg/wasm/lib/src/runtime.dart
@@ -21,15 +21,16 @@
   Pointer<WasmerFunctype> funcType;
   WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType);
 
+  @override
   String toString() {
     var kindName = wasmerExternKindName(kind);
     if (kind == WasmerExternKindFunction) {
       var runtime = WasmRuntime();
-      var sig = WasmRuntime.getSignatureString("${moduleName}::${name}",
+      var sig = WasmRuntime.getSignatureString('${moduleName}::${name}',
           runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
-      return "$kindName: $sig";
+      return '$kindName: $sig';
     } else {
-      return "$kindName: ${moduleName}::${name}";
+      return '$kindName: ${moduleName}::${name}';
     }
   }
 }
@@ -40,15 +41,16 @@
   Pointer<WasmerFunctype> funcType;
   WasmExportDescriptor(this.kind, this.name, this.funcType);
 
+  @override
   String toString() {
     var kindName = wasmerExternKindName(kind);
     if (kind == WasmerExternKindFunction) {
       var runtime = WasmRuntime();
       var sig = WasmRuntime.getSignatureString(
           name, runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
-      return "$kindName: $sig";
+      return '$kindName: $sig';
     } else {
-      return "$kindName: ${name}";
+      return '$kindName: ${name}';
     }
   }
 }
@@ -154,10 +156,10 @@
   }
 
   static String _getLibName() {
-    if (Platform.isMacOS) return "libwasmer.dylib";
-    if (Platform.isLinux) return "libwasmer.so";
+    if (Platform.isMacOS) return 'libwasmer.dylib';
+    if (Platform.isLinux) return 'libwasmer.so';
     // TODO(dartbug.com/37882): Support more platforms.
-    throw Exception("Wasm not currently supported on this platform");
+    throw Exception('Wasm not currently supported on this platform');
   }
 
   static String? _getLibPathFrom(Uri root) {
@@ -178,7 +180,7 @@
     if (path != null) return path;
     path = _getLibPathFrom(Directory.current.uri);
     if (path != null) return path;
-    throw Exception("Wasm library not found. Did you `pub run wasm:setup`?");
+    throw Exception('Wasm library not found. Did you `pub run wasm:setup`?');
   }
 
   WasmRuntime._init() : _lib = DynamicLibrary.open(_getLibPath()) {
@@ -409,16 +411,16 @@
         WasmerWasmerLastErrorMessageFn>('wasmer_last_error_message');
 
     if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
-      throw Exception("Failed to initialize Dart API");
+      throw Exception('Failed to initialize Dart API');
     }
     _engine = _engine_new();
-    _checkNotEqual(_engine, nullptr, "Failed to initialize Wasm engine.");
+    _checkNotEqual(_engine, nullptr, 'Failed to initialize Wasm engine.');
     _set_finalizer_for_engine(this, _engine);
   }
 
   Pointer<WasmerStore> newStore(Object owner) {
-    Pointer<WasmerStore> store = _checkNotEqual(
-        _store_new(_engine), nullptr, "Failed to create Wasm store.");
+    var store = _checkNotEqual(
+        _store_new(_engine), nullptr, 'Failed to create Wasm store.');
     _set_finalizer_for_store(owner, store);
     return store;
   }
@@ -426,7 +428,7 @@
   Pointer<WasmerModule> compile(
       Object owner, Pointer<WasmerStore> store, Uint8List data) {
     var dataPtr = calloc<Uint8>(data.length);
-    for (int i = 0; i < data.length; ++i) {
+    for (var i = 0; i < data.length; ++i) {
       dataPtr[i] = data[i];
     }
     var dataVec = calloc<WasmerByteVec>();
@@ -438,7 +440,7 @@
     calloc.free(dataPtr);
     calloc.free(dataVec);
 
-    _checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
+    _checkNotEqual(modulePtr, nullptr, 'Wasm module compile failed.');
     _set_finalizer_for_module(owner, modulePtr);
     return modulePtr;
   }
@@ -496,7 +498,7 @@
       } else {
         var trapMessage = calloc<WasmerByteVec>();
         _trap_message(trap, trapMessage);
-        var message = "Wasm trap when calling $source: ${trapMessage.ref}";
+        var message = 'Wasm trap when calling $source: ${trapMessage.ref}';
         _byte_vec_delete(trapMessage);
         calloc.free(trapMessage);
         _trap_delete(trap);
@@ -510,9 +512,9 @@
     var trap = calloc<Pointer<WasmerTrap>>();
     trap.value = nullptr;
     var inst = _instance_new(store, module, imports, trap);
-    maybeThrowTrap(trap.value, "module initialization function");
+    maybeThrowTrap(trap.value, 'module initialization function');
     calloc.free(trap);
-    _checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
+    _checkNotEqual(inst, nullptr, 'Wasm module instantiation failed.');
     _set_finalizer_for_instance(owner, inst);
     return inst;
   }
@@ -555,7 +557,7 @@
     if (rets.ref.length == 0) {
       return WasmerValKindVoid;
     } else if (rets.ref.length > 1) {
-      throw Exception("Multiple return values are not supported");
+      throw Exception('Multiple return values are not supported');
     }
     return _valtype_kind(rets.ref.data[0]);
   }
@@ -580,17 +582,17 @@
     limPtr.ref.max = maxPages ?? wasm_limits_max_default;
     var memType = _memorytype_new(limPtr);
     calloc.free(limPtr);
-    _checkNotEqual(memType, nullptr, "Failed to create memory type.");
+    _checkNotEqual(memType, nullptr, 'Failed to create memory type.');
     _set_finalizer_for_memorytype(owner, memType);
     var memory = _checkNotEqual(
-        _memory_new(store, memType), nullptr, "Failed to create memory.");
+        _memory_new(store, memType), nullptr, 'Failed to create memory.');
     _set_finalizer_for_memory(owner, memory);
     return memory;
   }
 
   void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
     _checkNotEqual(
-        _memory_grow(memory, deltaPages), 0, "Failed to grow memory.");
+        _memory_grow(memory, deltaPages), 0, 'Failed to grow memory.');
   }
 
   int memoryLength(Pointer<WasmerMemory> memory) {
@@ -610,7 +612,7 @@
       Pointer finalizer) {
     var f = _func_new_with_env(
         store, funcType, func.cast(), env.cast(), finalizer.cast());
-    _checkNotEqual(f, nullptr, "Failed to create function.");
+    _checkNotEqual(f, nullptr, 'Failed to create function.');
     _set_finalizer_for_func(owner, f);
     return f;
   }
@@ -623,7 +625,7 @@
     var trap = _trap_new(store, msg);
     calloc.free(msg.ref.data);
     calloc.free(msg);
-    _checkNotEqual(trap, nullptr, "Failed to create trap.");
+    _checkNotEqual(trap, nullptr, 'Failed to create trap.');
     var entry = _WasmTrapsEntry(exception);
     _set_finalizer_for_trap(entry, trap);
     traps[trap.address] = entry;
@@ -635,7 +637,7 @@
     name[0] = 0;
     var config = _wasi_config_new(name);
     calloc.free(name);
-    return _checkNotEqual(config, nullptr, "Failed to create WASI config.");
+    return _checkNotEqual(config, nullptr, 'Failed to create WASI config.');
   }
 
   void captureWasiStdout(Pointer<WasmerWasiConfig> config) {
@@ -648,7 +650,7 @@
 
   Pointer<WasmerWasiEnv> newWasiEnv(Pointer<WasmerWasiConfig> config) {
     return _checkNotEqual(
-        _wasi_env_new(config), nullptr, "Failed to create WASI environment.");
+        _wasi_env_new(config), nullptr, 'Failed to create WASI environment.');
   }
 
   void wasiEnvSetMemory(
@@ -659,7 +661,7 @@
   void getWasiImports(Pointer<WasmerStore> store, Pointer<WasmerModule> mod,
       Pointer<WasmerWasiEnv> env, Pointer<WasmerExternVec> imports) {
     _checkNotEqual(_wasi_get_imports(store, mod, env, imports), 0,
-        "Failed to fill WASI imports.");
+        'Failed to fill WASI imports.');
   }
 
   Stream<List<int>> getWasiStdoutStream(Pointer<WasmerWasiEnv> env) {
@@ -674,44 +676,46 @@
     var length = _wasmer_last_error_length();
     var buf = calloc<Uint8>(length);
     _wasmer_last_error_message(buf, length);
-    String message = utf8.decode(buf.asTypedList(length));
+    var message = utf8.decode(buf.asTypedList(length));
     calloc.free(buf);
     return message;
   }
 
   T _checkNotEqual<T>(T x, T y, String errorMessage) {
     if (x == y) {
-      throw Exception("$errorMessage\n${_getLastError()}");
+      throw Exception('$errorMessage\n${_getLastError()}');
     }
     return x;
   }
 
   static String getSignatureString(
       String name, List<int> argTypes, int returnType) {
-    return "${wasmerValKindName(returnType)} $name" +
+    return '${wasmerValKindName(returnType)} $name'
         "(${argTypes.map(wasmerValKindName).join(", ")})";
   }
 }
 
 class _WasiStreamIterator implements Iterator<List<int>> {
   static final int _bufferLength = 1024;
-  Pointer<WasmerWasiEnv> _env;
-  Function _reader;
-  Pointer<Uint8> _buf = calloc<Uint8>(_bufferLength);
+  final Pointer<WasmerWasiEnv> _env;
+  final Function _reader;
+  final Pointer<Uint8> _buf = calloc<Uint8>(_bufferLength);
   int _length = 0;
   _WasiStreamIterator(this._env, this._reader);
 
+  @override
   bool moveNext() {
     _length = _reader(_env, _buf, _bufferLength);
     return true;
   }
 
+  @override
   List<int> get current => _buf.asTypedList(_length);
 }
 
 class _WasiStreamIterable extends Iterable<List<int>> {
-  Pointer<WasmerWasiEnv> _env;
-  Function _reader;
+  final Pointer<WasmerWasiEnv> _env;
+  final Function _reader;
   _WasiStreamIterable(this._env, this._reader);
   @override
   Iterator<List<int>> get iterator => _WasiStreamIterator(_env, _reader);
diff --git a/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py b/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py
index a6877a7..ac7f12c 100755
--- a/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py
+++ b/pkg/wasm/lib/src/tools/generate_ffi_boilerplate.py
@@ -102,6 +102,7 @@
 
 byteVecToStringTemplate = '''
   Uint8List get list => data.asTypedList(length);
+  @override
   String toString() => utf8.decode(list);
 '''
 
diff --git a/pkg/wasm/lib/src/tools/runtime_template.dart b/pkg/wasm/lib/src/tools/runtime_template.dart
index 2798b90..072a042 100644
--- a/pkg/wasm/lib/src/tools/runtime_template.dart
+++ b/pkg/wasm/lib/src/tools/runtime_template.dart
@@ -19,15 +19,16 @@
   Pointer<WasmerFunctype> funcType;
   WasmImportDescriptor(this.kind, this.moduleName, this.name, this.funcType);
 
+  @override
   String toString() {
     var kindName = wasmerExternKindName(kind);
     if (kind == WasmerExternKindFunction) {
       var runtime = WasmRuntime();
-      var sig = WasmRuntime.getSignatureString("${moduleName}::${name}",
+      var sig = WasmRuntime.getSignatureString('${moduleName}::${name}',
           runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
-      return "$kindName: $sig";
+      return '$kindName: $sig';
     } else {
-      return "$kindName: ${moduleName}::${name}";
+      return '$kindName: ${moduleName}::${name}';
     }
   }
 }
@@ -38,15 +39,16 @@
   Pointer<WasmerFunctype> funcType;
   WasmExportDescriptor(this.kind, this.name, this.funcType);
 
+  @override
   String toString() {
     var kindName = wasmerExternKindName(kind);
     if (kind == WasmerExternKindFunction) {
       var runtime = WasmRuntime();
       var sig = WasmRuntime.getSignatureString(
           name, runtime.getArgTypes(funcType), runtime.getReturnType(funcType));
-      return "$kindName: $sig";
+      return '$kindName: $sig';
     } else {
-      return "$kindName: ${name}";
+      return '$kindName: ${name}';
     }
   }
 }
@@ -69,10 +71,10 @@
   }
 
   static String _getLibName() {
-    if (Platform.isMacOS) return "libwasmer.dylib";
-    if (Platform.isLinux) return "libwasmer.so";
+    if (Platform.isMacOS) return 'libwasmer.dylib';
+    if (Platform.isLinux) return 'libwasmer.so';
     // TODO(dartbug.com/37882): Support more platforms.
-    throw Exception("Wasm not currently supported on this platform");
+    throw Exception('Wasm not currently supported on this platform');
   }
 
   static String? _getLibPathFrom(Uri root) {
@@ -93,23 +95,23 @@
     if (path != null) return path;
     path = _getLibPathFrom(Directory.current.uri);
     if (path != null) return path;
-    throw Exception("Wasm library not found. Did you `pub run wasm:setup`?");
+    throw Exception('Wasm library not found. Did you `pub run wasm:setup`?');
   }
 
   WasmRuntime._init() : _lib = DynamicLibrary.open(_getLibPath()) {
 /* <RUNTIME_LOAD> */
 
     if (_Dart_InitializeApiDL(NativeApi.initializeApiDLData) != 0) {
-      throw Exception("Failed to initialize Dart API");
+      throw Exception('Failed to initialize Dart API');
     }
     _engine = _engine_new();
-    _checkNotEqual(_engine, nullptr, "Failed to initialize Wasm engine.");
+    _checkNotEqual(_engine, nullptr, 'Failed to initialize Wasm engine.');
     _set_finalizer_for_engine(this, _engine);
   }
 
   Pointer<WasmerStore> newStore(Object owner) {
-    Pointer<WasmerStore> store = _checkNotEqual(
-        _store_new(_engine), nullptr, "Failed to create Wasm store.");
+    var store = _checkNotEqual(
+        _store_new(_engine), nullptr, 'Failed to create Wasm store.');
     _set_finalizer_for_store(owner, store);
     return store;
   }
@@ -117,7 +119,7 @@
   Pointer<WasmerModule> compile(
       Object owner, Pointer<WasmerStore> store, Uint8List data) {
     var dataPtr = calloc<Uint8>(data.length);
-    for (int i = 0; i < data.length; ++i) {
+    for (var i = 0; i < data.length; ++i) {
       dataPtr[i] = data[i];
     }
     var dataVec = calloc<WasmerByteVec>();
@@ -129,7 +131,7 @@
     calloc.free(dataPtr);
     calloc.free(dataVec);
 
-    _checkNotEqual(modulePtr, nullptr, "Wasm module compile failed.");
+    _checkNotEqual(modulePtr, nullptr, 'Wasm module compile failed.');
     _set_finalizer_for_module(owner, modulePtr);
     return modulePtr;
   }
@@ -187,7 +189,7 @@
       } else {
         var trapMessage = calloc<WasmerByteVec>();
         _trap_message(trap, trapMessage);
-        var message = "Wasm trap when calling $source: ${trapMessage.ref}";
+        var message = 'Wasm trap when calling $source: ${trapMessage.ref}';
         _byte_vec_delete(trapMessage);
         calloc.free(trapMessage);
         _trap_delete(trap);
@@ -201,9 +203,9 @@
     var trap = calloc<Pointer<WasmerTrap>>();
     trap.value = nullptr;
     var inst = _instance_new(store, module, imports, trap);
-    maybeThrowTrap(trap.value, "module initialization function");
+    maybeThrowTrap(trap.value, 'module initialization function');
     calloc.free(trap);
-    _checkNotEqual(inst, nullptr, "Wasm module instantiation failed.");
+    _checkNotEqual(inst, nullptr, 'Wasm module instantiation failed.');
     _set_finalizer_for_instance(owner, inst);
     return inst;
   }
@@ -246,7 +248,7 @@
     if (rets.ref.length == 0) {
       return WasmerValKindVoid;
     } else if (rets.ref.length > 1) {
-      throw Exception("Multiple return values are not supported");
+      throw Exception('Multiple return values are not supported');
     }
     return _valtype_kind(rets.ref.data[0]);
   }
@@ -271,17 +273,17 @@
     limPtr.ref.max = maxPages ?? wasm_limits_max_default;
     var memType = _memorytype_new(limPtr);
     calloc.free(limPtr);
-    _checkNotEqual(memType, nullptr, "Failed to create memory type.");
+    _checkNotEqual(memType, nullptr, 'Failed to create memory type.');
     _set_finalizer_for_memorytype(owner, memType);
     var memory = _checkNotEqual(
-        _memory_new(store, memType), nullptr, "Failed to create memory.");
+        _memory_new(store, memType), nullptr, 'Failed to create memory.');
     _set_finalizer_for_memory(owner, memory);
     return memory;
   }
 
   void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
     _checkNotEqual(
-        _memory_grow(memory, deltaPages), 0, "Failed to grow memory.");
+        _memory_grow(memory, deltaPages), 0, 'Failed to grow memory.');
   }
 
   int memoryLength(Pointer<WasmerMemory> memory) {
@@ -301,7 +303,7 @@
       Pointer finalizer) {
     var f = _func_new_with_env(
         store, funcType, func.cast(), env.cast(), finalizer.cast());
-    _checkNotEqual(f, nullptr, "Failed to create function.");
+    _checkNotEqual(f, nullptr, 'Failed to create function.');
     _set_finalizer_for_func(owner, f);
     return f;
   }
@@ -314,7 +316,7 @@
     var trap = _trap_new(store, msg);
     calloc.free(msg.ref.data);
     calloc.free(msg);
-    _checkNotEqual(trap, nullptr, "Failed to create trap.");
+    _checkNotEqual(trap, nullptr, 'Failed to create trap.');
     var entry = _WasmTrapsEntry(exception);
     _set_finalizer_for_trap(entry, trap);
     traps[trap.address] = entry;
@@ -326,7 +328,7 @@
     name[0] = 0;
     var config = _wasi_config_new(name);
     calloc.free(name);
-    return _checkNotEqual(config, nullptr, "Failed to create WASI config.");
+    return _checkNotEqual(config, nullptr, 'Failed to create WASI config.');
   }
 
   void captureWasiStdout(Pointer<WasmerWasiConfig> config) {
@@ -339,7 +341,7 @@
 
   Pointer<WasmerWasiEnv> newWasiEnv(Pointer<WasmerWasiConfig> config) {
     return _checkNotEqual(
-        _wasi_env_new(config), nullptr, "Failed to create WASI environment.");
+        _wasi_env_new(config), nullptr, 'Failed to create WASI environment.');
   }
 
   void wasiEnvSetMemory(
@@ -350,7 +352,7 @@
   void getWasiImports(Pointer<WasmerStore> store, Pointer<WasmerModule> mod,
       Pointer<WasmerWasiEnv> env, Pointer<WasmerExternVec> imports) {
     _checkNotEqual(_wasi_get_imports(store, mod, env, imports), 0,
-        "Failed to fill WASI imports.");
+        'Failed to fill WASI imports.');
   }
 
   Stream<List<int>> getWasiStdoutStream(Pointer<WasmerWasiEnv> env) {
@@ -365,44 +367,46 @@
     var length = _wasmer_last_error_length();
     var buf = calloc<Uint8>(length);
     _wasmer_last_error_message(buf, length);
-    String message = utf8.decode(buf.asTypedList(length));
+    var message = utf8.decode(buf.asTypedList(length));
     calloc.free(buf);
     return message;
   }
 
   T _checkNotEqual<T>(T x, T y, String errorMessage) {
     if (x == y) {
-      throw Exception("$errorMessage\n${_getLastError()}");
+      throw Exception('$errorMessage\n${_getLastError()}');
     }
     return x;
   }
 
   static String getSignatureString(
       String name, List<int> argTypes, int returnType) {
-    return "${wasmerValKindName(returnType)} $name" +
+    return '${wasmerValKindName(returnType)} $name'
         "(${argTypes.map(wasmerValKindName).join(", ")})";
   }
 }
 
 class _WasiStreamIterator implements Iterator<List<int>> {
   static final int _bufferLength = 1024;
-  Pointer<WasmerWasiEnv> _env;
-  Function _reader;
-  Pointer<Uint8> _buf = calloc<Uint8>(_bufferLength);
+  final Pointer<WasmerWasiEnv> _env;
+  final Function _reader;
+  final Pointer<Uint8> _buf = calloc<Uint8>(_bufferLength);
   int _length = 0;
   _WasiStreamIterator(this._env, this._reader);
 
+  @override
   bool moveNext() {
     _length = _reader(_env, _buf, _bufferLength);
     return true;
   }
 
+  @override
   List<int> get current => _buf.asTypedList(_length);
 }
 
 class _WasiStreamIterable extends Iterable<List<int>> {
-  Pointer<WasmerWasiEnv> _env;
-  Function _reader;
+  final Pointer<WasmerWasiEnv> _env;
+  final Function _reader;
   _WasiStreamIterable(this._env, this._reader);
   @override
   Iterator<List<int>> get iterator => _WasiStreamIterator(_env, _reader);
diff --git a/pkg/wasm/lib/src/tools/wasmer_api_template.dart b/pkg/wasm/lib/src/tools/wasmer_api_template.dart
index 62c2ac0..f901c6e 100644
--- a/pkg/wasm/lib/src/tools/wasmer_api_template.dart
+++ b/pkg/wasm/lib/src/tools/wasmer_api_template.dart
@@ -26,32 +26,32 @@
 String wasmerExternKindName(int kind) {
   switch (kind) {
     case WasmerExternKindFunction:
-      return "function";
+      return 'function';
     case WasmerExternKindGlobal:
-      return "global";
+      return 'global';
     case WasmerExternKindTable:
-      return "table";
+      return 'table';
     case WasmerExternKindMemory:
-      return "memory";
+      return 'memory';
     default:
-      return "unknown";
+      return 'unknown';
   }
 }
 
 String wasmerValKindName(int kind) {
   switch (kind) {
     case WasmerValKindI32:
-      return "int32";
+      return 'int32';
     case WasmerValKindI64:
-      return "int64";
+      return 'int64';
     case WasmerValKindF32:
-      return "float32";
+      return 'float32';
     case WasmerValKindF64:
-      return "float64";
+      return 'float64';
     case WasmerValKindVoid:
-      return "void";
+      return 'void';
     default:
-      return "unknown";
+      return 'unknown';
   }
 }
 
diff --git a/pkg/wasm/lib/src/wasmer_api.dart b/pkg/wasm/lib/src/wasmer_api.dart
index 8a28af1..25bb8ba 100644
--- a/pkg/wasm/lib/src/wasmer_api.dart
+++ b/pkg/wasm/lib/src/wasmer_api.dart
@@ -28,32 +28,32 @@
 String wasmerExternKindName(int kind) {
   switch (kind) {
     case WasmerExternKindFunction:
-      return "function";
+      return 'function';
     case WasmerExternKindGlobal:
-      return "global";
+      return 'global';
     case WasmerExternKindTable:
-      return "table";
+      return 'table';
     case WasmerExternKindMemory:
-      return "memory";
+      return 'memory';
     default:
-      return "unknown";
+      return 'unknown';
   }
 }
 
 String wasmerValKindName(int kind) {
   switch (kind) {
     case WasmerValKindI32:
-      return "int32";
+      return 'int32';
     case WasmerValKindI64:
-      return "int64";
+      return 'int64';
     case WasmerValKindF32:
-      return "float32";
+      return 'float32';
     case WasmerValKindF64:
-      return "float64";
+      return 'float64';
     case WasmerValKindVoid:
-      return "void";
+      return 'void';
     default:
-      return "unknown";
+      return 'unknown';
   }
 }
 
@@ -171,6 +171,7 @@
   external Pointer<Uint8> data;
 
   Uint8List get list => data.asTypedList(length);
+  @override
   String toString() => utf8.decode(list);
 }
 
diff --git a/pkg/wasm/test/basic_test.dart b/pkg/wasm/test/basic_test.dart
index 5986a34..cd6020e 100644
--- a/pkg/wasm/test/basic_test.dart
+++ b/pkg/wasm/test/basic_test.dart
@@ -3,16 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test that we can load a wasm module, find a function, and call it.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("basics", () {
+  test('basics', () {
     // int64_t square(int64_t n) { return n * n; }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, //
       0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
       0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
       0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
@@ -22,11 +22,11 @@
     ]);
 
     var inst = WasmModule(data).instantiate().build();
-    var fn = inst.lookupFunction("square");
+    var fn = inst.lookupFunction('square');
     int n = fn(1234);
 
     expect(n, 1234 * 1234);
 
-    expect(inst.lookupFunction("not_a_function"), isNull);
+    expect(inst.lookupFunction('not_a_function'), isNull);
   });
 }
diff --git a/pkg/wasm/test/corrupted_error_test.dart b/pkg/wasm/test/corrupted_error_test.dart
index ac94ae8..f051dd4 100644
--- a/pkg/wasm/test/corrupted_error_test.dart
+++ b/pkg/wasm/test/corrupted_error_test.dart
@@ -3,15 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test error thrown when the wasm module is corrupted.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("corrupted module", () {
+  test('corrupted module', () {
     var data = Uint8List.fromList([
-      0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7e, 0x01, 0x7e,
+      0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7e, 0x01, 0x7e, //
       0x07, 0x13, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00,
       0x06, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x20, 0x00,
       0x7e, 0x0b,
diff --git a/pkg/wasm/test/fn_call_error_test.dart b/pkg/wasm/test/fn_call_error_test.dart
index bcaf64c..6415ba3 100644
--- a/pkg/wasm/test/fn_call_error_test.dart
+++ b/pkg/wasm/test/fn_call_error_test.dart
@@ -2,17 +2,18 @@
 // 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:typed_data';
+
 // Test error thrown when a function is called with the wrong args.
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("function with wrong arguments", () {
+  test('function with wrong arguments', () {
     // int64_t square(int64_t n) { return n * n; }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, //
       0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
       0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
       0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
@@ -22,7 +23,7 @@
     ]);
 
     var inst = WasmModule(data).instantiate().build();
-    var fn = inst.lookupFunction("square");
+    var fn = inst.lookupFunction('square');
 
     expect(() => fn(), throwsA(isArgumentError));
     expect(() => fn(1, 2, 3), throwsA(isArgumentError));
diff --git a/pkg/wasm/test/fn_import_error_test.dart b/pkg/wasm/test/fn_import_error_test.dart
index 71482bd..5642878 100644
--- a/pkg/wasm/test/fn_import_error_test.dart
+++ b/pkg/wasm/test/fn_import_error_test.dart
@@ -2,18 +2,19 @@
 // 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:typed_data';
+
 // Test errors thrown by function imports.
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("bad function imports", () {
+  test('bad function imports', () {
     // This module expects a function import like:
     // int64_t someFn(int32_t a, int64_t b, float c, double d);
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x60, //
       0x04, 0x7f, 0x7e, 0x7d, 0x7c, 0x01, 0x7e, 0x60, 0x00, 0x00, 0x02, 0x0e,
       0x01, 0x03, 0x65, 0x6e, 0x76, 0x06, 0x73, 0x6f, 0x6d, 0x65, 0x46, 0x6e,
       0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
@@ -30,48 +31,48 @@
     // Valid instantiation.
     var inst = mod
         .instantiate()
-        .addFunction("env", "someFn", (int a, int b, num c, double d) => 123)
+        .addFunction('env', 'someFn', (int a, int b, num c, double d) => 123)
         .build();
 
     // Missing imports.
     expect(() => mod.instantiate().build(),
-        throwsA(predicate((Exception e) => "$e".contains("Missing import"))));
+        throwsA(predicate((Exception e) => '$e'.contains('Missing import'))));
 
     // Wrong kind of import.
     expect(
         () =>
-            mod.instantiate().addMemory("env", "someFn", mod.createMemory(10)),
+            mod.instantiate().addMemory('env', 'someFn', mod.createMemory(10)),
         throwsA(predicate(
-            (Exception e) => "$e".contains("Import is not a memory"))));
+            (Exception e) => '$e'.contains('Import is not a memory'))));
 
     // Wrong namespace.
     expect(
         () => mod
             .instantiate()
             .addFunction(
-                "foo", "someFn", (int a, int b, num c, double d) => 123)
+                'foo', 'someFn', (int a, int b, num c, double d) => 123)
             .build(),
-        throwsA(predicate((Exception e) => "$e".contains("Import not found"))));
+        throwsA(predicate((Exception e) => '$e'.contains('Import not found'))));
 
     // Wrong name.
     expect(
         () => mod
             .instantiate()
             .addFunction(
-                "env", "otherFn", (int a, int b, num c, double d) => 123)
+                'env', 'otherFn', (int a, int b, num c, double d) => 123)
             .build(),
-        throwsA(predicate((Exception e) => "$e".contains("Import not found"))));
+        throwsA(predicate((Exception e) => '$e'.contains('Import not found'))));
 
     // Already filled.
     expect(
         () => mod
             .instantiate()
             .addFunction(
-                "env", "someFn", (int a, int b, num c, double d) => 123)
+                'env', 'someFn', (int a, int b, num c, double d) => 123)
             .addFunction(
-                "env", "someFn", (int a, int b, num c, double d) => 456)
+                'env', 'someFn', (int a, int b, num c, double d) => 456)
             .build(),
         throwsA(predicate(
-            (Exception e) => "$e".contains("Import already filled"))));
+            (Exception e) => '$e'.contains('Import already filled'))));
   });
 }
diff --git a/pkg/wasm/test/fn_import_exception_test.dart b/pkg/wasm/test/fn_import_exception_test.dart
index e9de6ca..e62d3b1 100644
--- a/pkg/wasm/test/fn_import_exception_test.dart
+++ b/pkg/wasm/test/fn_import_exception_test.dart
@@ -3,19 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test throwing exceptions from an imported function.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("exception thrown from imported function", () {
+  test('exception thrown from imported function', () {
     // void fn() {
     //   a();
     //   b();
     // }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60, //
       0x00, 0x00, 0x02, 0x11, 0x02, 0x03, 0x65, 0x6e, 0x76, 0x01, 0x61, 0x00,
       0x00, 0x03, 0x65, 0x6e, 0x76, 0x01, 0x62, 0x00, 0x00, 0x03, 0x02, 0x01,
       0x00, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00,
@@ -25,24 +25,24 @@
       0x80, 0x80, 0x00, 0x10, 0x81, 0x80, 0x80, 0x80, 0x00, 0x0b,
     ]);
 
-    bool called_b = false;
-    var thrownException = Exception("Hello exception!");
-    var inst = WasmModule(data).instantiate().addFunction("env", "a", () {
+    var called_b = false;
+    var thrownException = Exception('Hello exception!');
+    var inst = WasmModule(data).instantiate().addFunction('env', 'a', () {
       throw thrownException;
-    }).addFunction("env", "b", () {
+    }).addFunction('env', 'b', () {
       called_b = true;
     }).build();
-    var fn = inst.lookupFunction("fn");
+    var fn = inst.lookupFunction('fn');
     expect(() => fn(), throwsA(thrownException));
     expect(called_b, isFalse);
 
-    bool called_a = false;
-    inst = WasmModule(data).instantiate().addFunction("env", "a", () {
+    var called_a = false;
+    inst = WasmModule(data).instantiate().addFunction('env', 'a', () {
       called_a = true;
-    }).addFunction("env", "b", () {
+    }).addFunction('env', 'b', () {
       called_b = true;
     }).build();
-    fn = inst.lookupFunction("fn");
+    fn = inst.lookupFunction('fn');
     fn();
     expect(called_a, isTrue);
     expect(called_b, isTrue);
diff --git a/pkg/wasm/test/fn_import_test.dart b/pkg/wasm/test/fn_import_test.dart
index 3543f0b..862983b 100644
--- a/pkg/wasm/test/fn_import_test.dart
+++ b/pkg/wasm/test/fn_import_test.dart
@@ -3,16 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test that we can load a wasm module, find a function, and call it.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("function import", () {
+  test('function import', () {
     // void reportStuff() { report(123, 456); }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60, //
       0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x02, 0x0e, 0x01, 0x03, 0x65,
       0x6e, 0x76, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x03,
       0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03,
@@ -23,15 +23,15 @@
       0xc8, 0x03, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x0b,
     ]);
 
-    int report_x = -1;
-    int report_y = -1;
+    var report_x = -1;
+    var report_y = -1;
 
-    var inst = WasmModule(data).instantiate()
-      .addFunction("env", "report", (int x, int y) {
-        report_x = x;
-        report_y = y;
-      }).build();
-    var fn = inst.lookupFunction("reportStuff");
+    var inst = WasmModule(data).instantiate().addFunction('env', 'report',
+        (int x, int y) {
+      report_x = x;
+      report_y = y;
+    }).build();
+    var fn = inst.lookupFunction('reportStuff');
     fn();
     expect(123, report_x);
     expect(456, report_y);
diff --git a/pkg/wasm/test/hello_wasi_test.dart b/pkg/wasm/test/hello_wasi_test.dart
index f41bd50..a4398c8 100644
--- a/pkg/wasm/test/hello_wasi_test.dart
+++ b/pkg/wasm/test/hello_wasi_test.dart
@@ -3,18 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Variant of hello_world_test that uses the default WASI imports.
+import 'dart:convert';
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:convert";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("hello wasi", () async {
+  test('hello wasi', () async {
     // Hello world module generated by emscripten+WASI. Exports a function like
     // `void _start()`, and prints using `int fd_write(int, int, int, int)`.
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60, //
       0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f,
       0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
       0x01, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60,
@@ -174,9 +174,9 @@
     var inst =
         WasmModule(data).instantiate().enableWasi(captureStdout: true).build();
 
-    var fn = inst.lookupFunction("_start");
+    var fn = inst.lookupFunction('_start');
     fn();
     var out = utf8.decode(await inst.stdout.first);
-    expect(out, "hello, world!\n");
+    expect(out, 'hello, world!\n');
   });
 }
diff --git a/pkg/wasm/test/hello_world_test.dart b/pkg/wasm/test/hello_world_test.dart
index 8a49ae2..1f0514c 100644
--- a/pkg/wasm/test/hello_world_test.dart
+++ b/pkg/wasm/test/hello_world_test.dart
@@ -3,19 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // @dart = 2.12
-
 // Test for hello world built using emscripten with WASI.
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'dart:typed_data';
+
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("hello world", () {
+  test('hello world', () {
     // Hello world module generated by emscripten+WASI. Exports a function like
     // `void _start()`, and prints using `int fd_write(int, int, int, int)`.
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60, //
       0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f,
       0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
       0x01, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60,
@@ -173,10 +173,10 @@
     ]);
 
     late WasmMemory mem;
-    String out = "";
+    var out = '';
     var getI32 = (int p) {
       // Read a little-endian I32.
-      int n = 0;
+      var n = 0;
       for (var i = p + 3; i >= p; --i) {
         n *= 256;
         n += mem[i];
@@ -185,11 +185,11 @@
     };
     var inst = WasmModule(data)
         .instantiate()
-        .addFunction("wasi_unstable", "fd_write",
+        .addFunction('wasi_unstable', 'fd_write',
             (int fd, int iovs, int iovs_len, int unused) {
       // iovs points to an array of length iovs_len. Each element is two I32s,
       // a char* and a length.
-      String o = "";
+      var o = '';
       for (var i = 0; i < iovs_len; ++i) {
         var str = getI32(iovs + 8 * i);
         var len = getI32(iovs + 4 + 8 * i);
@@ -202,8 +202,8 @@
     }).build();
     mem = inst.memory;
 
-    var fn = inst.lookupFunction("_start");
+    var fn = inst.lookupFunction('_start');
     fn();
-    expect(out, "hello, world!\n");
+    expect(out, 'hello, world!\n');
   });
 }
diff --git a/pkg/wasm/test/memory_error_test.dart b/pkg/wasm/test/memory_error_test.dart
index 6409022..0c8dbd1 100644
--- a/pkg/wasm/test/memory_error_test.dart
+++ b/pkg/wasm/test/memory_error_test.dart
@@ -3,16 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test errors thrown by WasmMemory.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("memory errors", () {
+  test('memory errors', () {
     // Empty wasm module.
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00, //
     ]);
     var module = WasmModule(data);
 
diff --git a/pkg/wasm/test/memory_test.dart b/pkg/wasm/test/memory_test.dart
index 95ea288..483c225 100644
--- a/pkg/wasm/test/memory_test.dart
+++ b/pkg/wasm/test/memory_test.dart
@@ -3,16 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test that we can create a WasmMemory, edit it, and grow it.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("memory", () {
+  test('memory', () {
     // Empty wasm module.
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00, //
     ]);
     var module = WasmModule(data);
 
diff --git a/pkg/wasm/test/numerics_test.dart b/pkg/wasm/test/numerics_test.dart
index 5fa19d0..b88457d 100644
--- a/pkg/wasm/test/numerics_test.dart
+++ b/pkg/wasm/test/numerics_test.dart
@@ -3,19 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test numeric types.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("numerics", () {
+  test('numerics', () {
     // int64_t addI64(int64_t x, int64_t y) { return x + y; }
     // int32_t addI32(int32_t x, int32_t y) { return x + y; }
     // double addF64(double x, double y) { return x + y; }
     // float addF32(float x, float y) { return x + y; }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x19, 0x04, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x19, 0x04, 0x60, //
       0x02, 0x7e, 0x7e, 0x01, 0x7e, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
       0x02, 0x7c, 0x7c, 0x01, 0x7c, 0x60, 0x02, 0x7d, 0x7d, 0x01, 0x7d, 0x03,
       0x05, 0x04, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
@@ -31,10 +31,10 @@
     ]);
 
     var inst = WasmModule(data).instantiate().build();
-    var addI64 = inst.lookupFunction("addI64");
-    var addI32 = inst.lookupFunction("addI32");
-    var addF64 = inst.lookupFunction("addF64");
-    var addF32 = inst.lookupFunction("addF32");
+    var addI64 = inst.lookupFunction('addI64');
+    var addI32 = inst.lookupFunction('addI32');
+    var addF64 = inst.lookupFunction('addF64');
+    var addF32 = inst.lookupFunction('addF32');
 
     int i64 = addI64(0x123456789ABCDEF, 0xFEDCBA987654321);
     expect(i64, 0x1111111111111110);
diff --git a/pkg/wasm/test/void_test.dart b/pkg/wasm/test/void_test.dart
index d1804eb..7f082e2 100644
--- a/pkg/wasm/test/void_test.dart
+++ b/pkg/wasm/test/void_test.dart
@@ -3,18 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test functions with void return type, and functions that take no args.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("void return type", () {
+  test('void return type', () {
     // int64_t x = 0;
     // void set(int64_t a, int64_t b) { x = a + b; }
     // int64_t get() { return x; }
     var data = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x02, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x02, 0x60, //
       0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x01, 0x7e, 0x03, 0x03, 0x02, 0x00,
       0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00,
       0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x90, 0x88, 0x04, 0x0b, 0x07,
@@ -27,8 +27,8 @@
     ]);
 
     var inst = WasmModule(data).instantiate().build();
-    var setFn = inst.lookupFunction("set");
-    var getFn = inst.lookupFunction("get");
+    var setFn = inst.lookupFunction('set');
+    var getFn = inst.lookupFunction('get');
     expect(setFn(123, 456), isNull);
     int n = getFn();
     expect(n, 123 + 456);
diff --git a/pkg/wasm/test/wasi_error_test.dart b/pkg/wasm/test/wasi_error_test.dart
index 3c6f46d..d8e7945 100644
--- a/pkg/wasm/test/wasi_error_test.dart
+++ b/pkg/wasm/test/wasi_error_test.dart
@@ -3,27 +3,28 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test the errors that can be thrown by WASI.
+import 'dart:typed_data';
 
-import "package:test/test.dart";
-import "package:wasm/wasm.dart";
-import "dart:typed_data";
+import 'package:test/test.dart';
+import 'package:wasm/wasm.dart';
 
 void main() {
-  test("wasi error", () {
+  test('wasi error', () {
     // Empty wasm module.
     var emptyModuleData = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x00, 0x00, //
     ]);
 
     // Failed to fill WASI imports (the empty module was not built with WASI).
-    expect(() => WasmModule(emptyModuleData).instantiate().enableWasi(),
+    expect(
+        () => WasmModule(emptyModuleData).instantiate().enableWasi(),
         throwsA(predicate(
-            (Exception e) => "$e".contains("Failed to fill WASI imports"))));
+            (Exception e) => '$e'.contains('Failed to fill WASI imports'))));
 
     // Hello world module generated by emscripten+WASI. Exports a function like
     // `void _start()`, and prints using `int fd_write(int, int, int, int)`.
     var helloWorldData = Uint8List.fromList([
-      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60,
+      0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60, //
       0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f,
       0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
       0x01, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60,
@@ -182,28 +183,29 @@
 
     // Trying to import WASI twice.
     expect(
-        () => WasmModule(helloWorldData).instantiate().enableWasi().enableWasi(),
+        () =>
+            WasmModule(helloWorldData).instantiate().enableWasi().enableWasi(),
         throwsA(predicate(
-            (Exception e) => "$e".contains("WASI is already enabled"))));
+            (Exception e) => '$e'.contains('WASI is already enabled'))));
 
     // Missing imports due to not enabling WASI.
     expect(() => WasmModule(helloWorldData).instantiate().build(),
-        throwsA(predicate((Exception e) => "$e".contains("Missing import"))));
+        throwsA(predicate((Exception e) => '$e'.contains('Missing import'))));
 
     // Trying to get stdout/stderr without WASI enabled (WASI function import has
     // been manually filled).
     var inst = WasmModule(helloWorldData)
         .instantiate()
-        .addFunction("wasi_unstable", "fd_write",
+        .addFunction('wasi_unstable', 'fd_write',
             (int fd, int iovs, int iovs_len, int unused) => 0)
         .build();
     expect(
         () => inst.stdout,
         throwsA(predicate((Exception e) =>
-            "$e".contains("Can't capture stdout without WASI enabled"))));
+            '$e'.contains("Can't capture stdout without WASI enabled"))));
     expect(
         () => inst.stderr,
         throwsA(predicate((Exception e) =>
-            "$e".contains("Can't capture stderr without WASI enabled"))));
+            '$e'.contains("Can't capture stderr without WASI enabled"))));
   });
 }
diff --git a/runtime/platform/growable_array.h b/runtime/platform/growable_array.h
index 9c906f6..c568862 100644
--- a/runtime/platform/growable_array.h
+++ b/runtime/platform/growable_array.h
@@ -66,6 +66,21 @@
     length_ = length;
   }
 
+  inline bool Contains(const T& other,
+                       bool isEqual(const T&, const T&) = nullptr) const {
+    for (const auto& value : *this) {
+      if (value == other) {
+        // Value identity should imply isEqual.
+        ASSERT(isEqual == nullptr || isEqual(value, other));
+        return true;
+      }
+      if (isEqual != nullptr && isEqual(value, other)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   void Add(const T& value) {
     Resize(length() + 1);
     Last() = value;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 503bb93..9f9eb8b 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1513,8 +1513,6 @@
       ScriptPtr script = objects_[i];
       AutoTraceObjectName(script, script->untag()->url());
       WriteFromTo(script);
-      s->Write<int32_t>(script->untag()->line_offset_);
-      s->Write<int32_t>(script->untag()->col_offset_);
       if (s->kind() != Snapshot::kFullAOT) {
         // Clear out the max position cache in snapshots to ensure no
         // differences in the snapshot due to triggering caching vs. not.
@@ -1556,8 +1554,6 @@
       Deserializer::InitializeHeader(script, kScriptCid,
                                      Script::InstanceSize());
       ReadFromTo(script);
-      script->untag()->line_offset_ = d->Read<int32_t>();
-      script->untag()->col_offset_ = d->Read<int32_t>();
 #if !defined(DART_PRECOMPILED_RUNTIME)
       script->untag()->flags_and_max_position_ = d->Read<int32_t>();
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 86f3c78..3c7f331 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -2050,13 +2050,18 @@
 
 void Assembler::EnsureHasClassIdInDEBUG(intptr_t cid,
                                         Register src,
-                                        Register scratch) {
+                                        Register scratch,
+                                        bool can_be_null) {
 #if defined(DEBUG)
   Comment("Check that object in register has cid %" Pd "", cid);
   Label matches;
   LoadClassIdMayBeSmi(scratch, src);
   CompareImmediate(scratch, cid);
   BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  if (can_be_null) {
+    CompareImmediate(scratch, kNullCid);
+    BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  }
   Breakpoint();
   Bind(&matches);
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 2c993d6..a54758b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -923,7 +923,8 @@
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
   void EnsureHasClassIdInDEBUG(intptr_t cid,
                                Register src,
-                               Register scratch) override;
+                               Register scratch,
+                               bool can_be_null = false) override;
 
   intptr_t FindImmediate(int32_t imm);
   bool CanLoadFromObjectPool(const Object& object) const;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 7380bbc..7c30d2d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1344,13 +1344,18 @@
 
 void Assembler::EnsureHasClassIdInDEBUG(intptr_t cid,
                                         Register src,
-                                        Register scratch) {
+                                        Register scratch,
+                                        bool can_be_null) {
 #if defined(DEBUG)
   Comment("Check that object in register has cid %" Pd "", cid);
   Label matches;
   LoadClassIdMayBeSmi(scratch, src);
   CompareImmediate(scratch, cid);
   BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  if (can_be_null) {
+    CompareImmediate(scratch, kNullCid);
+    BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  }
   Breakpoint();
   Bind(&matches);
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index d4f08c5..1630d87 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1893,7 +1893,8 @@
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
   void EnsureHasClassIdInDEBUG(intptr_t cid,
                                Register src,
-                               Register scratch) override;
+                               Register scratch,
+                               bool can_be_null = false) override;
 
   // Reserve specifies how much space to reserve for the Dart stack.
   void SetupDartSP(intptr_t reserve = 4096);
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index 733972d..e8b7d89 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -669,7 +669,8 @@
 
   virtual void EnsureHasClassIdInDEBUG(intptr_t cid,
                                        Register src,
-                                       Register scratch) = 0;
+                                       Register scratch,
+                                       bool can_be_null = false) = 0;
 
   intptr_t InsertAlignedRelocation(BSS::Relocation reloc);
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 2d0c3fb..421b17d 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2827,13 +2827,18 @@
 
 void Assembler::EnsureHasClassIdInDEBUG(intptr_t cid,
                                         Register src,
-                                        Register scratch) {
+                                        Register scratch,
+                                        bool can_be_null) {
 #if defined(DEBUG)
   Comment("Check that object in register has cid %" Pd "", cid);
   Label matches;
   LoadClassIdMayBeSmi(scratch, src);
   CompareImmediate(scratch, cid);
   BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  if (can_be_null) {
+    CompareImmediate(scratch, kNullCid);
+    BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  }
   Breakpoint();
   Bind(&matches);
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index f69c928..48ab1e1 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -831,7 +831,8 @@
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
   void EnsureHasClassIdInDEBUG(intptr_t cid,
                                Register src,
-                               Register scratch) override;
+                               Register scratch,
+                               bool can_be_null = false) override;
 
   void SmiUntagOrCheckClass(Register object,
                             intptr_t class_id,
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 72d30fd..956088b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2407,13 +2407,18 @@
 
 void Assembler::EnsureHasClassIdInDEBUG(intptr_t cid,
                                         Register src,
-                                        Register scratch) {
+                                        Register scratch,
+                                        bool can_be_null) {
 #if defined(DEBUG)
   Comment("Check that object in register has cid %" Pd "", cid);
   Label matches;
   LoadClassIdMayBeSmi(scratch, src);
   CompareImmediate(scratch, cid);
   BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  if (can_be_null) {
+    CompareImmediate(scratch, kNullCid);
+    BranchIf(EQUAL, &matches, Assembler::kNearJump);
+  }
   Breakpoint();
   Bind(&matches);
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index c5a2b08..3c8a165 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -885,7 +885,8 @@
 
   void EnsureHasClassIdInDEBUG(intptr_t cid,
                                Register src,
-                               Register scratch) override;
+                               Register scratch,
+                               bool can_be_null = false) override;
 
   // CheckClassIs fused with optimistic SmiUntag.
   // Value in the register object is untagged optimistically.
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 0986d22..aad4fe7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -999,6 +999,8 @@
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   locs->set_in(kFunctionPos,
                Location::RegisterLocation(AllocateClosureABI::kFunctionReg));
+  locs->set_in(kContextPos,
+               Location::RegisterLocation(AllocateClosureABI::kContextReg));
   locs->set_out(0, Location::RegisterLocation(AllocateClosureABI::kResultReg));
   return locs;
 }
@@ -2675,67 +2677,6 @@
   return this;
 }
 
-bool LoadFieldInstr::IsImmutableLengthLoad() const {
-  switch (slot().kind()) {
-    case Slot::Kind::kArray_length:
-    case Slot::Kind::kTypedDataBase_length:
-    case Slot::Kind::kString_length:
-    case Slot::Kind::kTypeArguments_length:
-      return true;
-    case Slot::Kind::kGrowableObjectArray_length:
-      return false;
-
-    // Not length loads.
-#define UNBOXED_NATIVE_SLOT_CASE(Class, Untagged, Field, Rep, IsFinal)         \
-  case Slot::Kind::k##Class##_##Field:
-      UNBOXED_NATIVE_SLOTS_LIST(UNBOXED_NATIVE_SLOT_CASE)
-#undef UNBOXED_NATIVE_SLOT_CASE
-    case Slot::Kind::kLinkedHashMap_index:
-    case Slot::Kind::kLinkedHashMap_data:
-    case Slot::Kind::kLinkedHashMap_hash_mask:
-    case Slot::Kind::kLinkedHashMap_used_data:
-    case Slot::Kind::kLinkedHashMap_deleted_keys:
-    case Slot::Kind::kArgumentsDescriptor_type_args_len:
-    case Slot::Kind::kArgumentsDescriptor_positional_count:
-    case Slot::Kind::kArgumentsDescriptor_count:
-    case Slot::Kind::kArgumentsDescriptor_size:
-    case Slot::Kind::kArrayElement:
-    case Slot::Kind::kTypeArguments:
-    case Slot::Kind::kTypedDataView_offset_in_bytes:
-    case Slot::Kind::kTypedDataView_data:
-    case Slot::Kind::kGrowableObjectArray_data:
-    case Slot::Kind::kContext_parent:
-    case Slot::Kind::kClosure_context:
-    case Slot::Kind::kClosure_delayed_type_arguments:
-    case Slot::Kind::kClosure_function:
-    case Slot::Kind::kClosure_function_type_arguments:
-    case Slot::Kind::kClosure_instantiator_type_arguments:
-    case Slot::Kind::kClosure_hash:
-    case Slot::Kind::kCapturedVariable:
-    case Slot::Kind::kDartField:
-    case Slot::Kind::kFunction_data:
-    case Slot::Kind::kFunction_signature:
-    case Slot::Kind::kFunctionType_parameter_names:
-    case Slot::Kind::kFunctionType_parameter_types:
-    case Slot::Kind::kFunctionType_type_parameters:
-    case Slot::Kind::kPointerBase_data_field:
-    case Slot::Kind::kType_arguments:
-    case Slot::Kind::kTypeArgumentsIndex:
-    case Slot::Kind::kTypeParameters_names:
-    case Slot::Kind::kTypeParameters_flags:
-    case Slot::Kind::kTypeParameters_bounds:
-    case Slot::Kind::kTypeParameters_defaults:
-    case Slot::Kind::kTypeParameter_bound:
-    case Slot::Kind::kUnhandledException_exception:
-    case Slot::Kind::kUnhandledException_stacktrace:
-    case Slot::Kind::kWeakProperty_key:
-    case Slot::Kind::kWeakProperty_value:
-      return false;
-  }
-  UNREACHABLE();
-  return false;
-}
-
 bool LoadFieldInstr::IsFixedLengthArrayCid(intptr_t cid) {
   if (IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid)) {
     return true;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index b41c986..e14e142 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -6138,6 +6138,27 @@
     return InputCount();
   }
 
+  // Returns the slot in the allocated object that contains the value at the
+  // given input position. Returns nullptr if the input position is invalid
+  // or if the input is not stored in the object.
+  virtual const Slot* SlotForInput(intptr_t pos) { return nullptr; }
+
+  // Returns the input index that has a corresponding slot which is identical to
+  // the given slot. Returns a negative index if no such input found.
+  intptr_t InputForSlot(const Slot& slot) {
+    for (intptr_t i = 0; i < InputCount(); i++) {
+      auto* const input_slot = SlotForInput(i);
+      if (input_slot != nullptr && input_slot->IsIdentical(slot)) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  // Returns whether the allocated object has initialized fields and/or payload
+  // elements. Override for any subclass that returns an uninitialized object.
+  virtual bool ObjectIsInitialized() { return true; }
+
   PRINT_OPERANDS_TO_SUPPORT
 
   DEFINE_INSTRUCTION_TYPE_CHECK(Allocation);
@@ -6182,6 +6203,8 @@
     ASSERT((cls.NumTypeArguments() > 0) == (type_arguments != nullptr));
     if (type_arguments != nullptr) {
       SetInputAt(kTypeArgumentsPos, type_arguments);
+      type_arguments_slot_ =
+          &Slot::GetTypeArgumentsSlotFor(Thread::Current(), cls);
     }
   }
 
@@ -6209,6 +6232,10 @@
     return Heap::IsAllocatableInNewSpace(cls.target_instance_size());
   }
 
+  virtual const Slot* SlotForInput(intptr_t pos) {
+    return pos == kTypeArgumentsPos ? type_arguments_slot_ : nullptr;
+  }
+
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
@@ -6220,26 +6247,30 @@
 
   const Class& cls_;
   Value* type_arguments_;
+  const Slot* type_arguments_slot_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
 };
 
 // Allocates and null initializes a closure object, given the closure function
-// as a value.
-class AllocateClosureInstr : public TemplateAllocation<1> {
+// and the context as values.
+class AllocateClosureInstr : public TemplateAllocation<2> {
  public:
-  enum Inputs { kFunctionPos = 0 };
+  enum Inputs { kFunctionPos = 0, kContextPos = 1 };
   AllocateClosureInstr(const InstructionSource& source,
                        Value* closure_function,
+                       Value* context,
                        intptr_t deopt_id)
       : TemplateAllocation(source, deopt_id) {
     SetInputAt(kFunctionPos, closure_function);
+    SetInputAt(kContextPos, context);
   }
 
   DECLARE_INSTRUCTION(AllocateClosure)
   virtual CompileType ComputeType() const;
 
   Value* closure_function() const { return inputs_[kFunctionPos]; }
+  Value* context() const { return inputs_[kContextPos]; }
 
   const Function& known_function() const {
     Value* const value = closure_function();
@@ -6250,6 +6281,17 @@
     return Object::null_function();
   }
 
+  virtual const Slot* SlotForInput(intptr_t pos) {
+    switch (pos) {
+      case kFunctionPos:
+        return &Slot::Closure_function();
+      case kContextPos:
+        return &Slot::Closure_context();
+      default:
+        return TemplateAllocation::SlotForInput(pos);
+    }
+  }
+
   virtual bool HasUnknownSideEffects() const { return false; }
 
   virtual bool WillAllocateNewOrRemembered() const {
@@ -6279,6 +6321,8 @@
         num_context_variables_);
   }
 
+  virtual bool ObjectIsInitialized() { return false; }
+
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
@@ -6438,6 +6482,17 @@
         GetConstantNumElements());
   }
 
+  virtual const Slot* SlotForInput(intptr_t pos) {
+    switch (pos) {
+      case kTypeArgumentsPos:
+        return &Slot::Array_type_arguments();
+      case kLengthPos:
+        return &Slot::Array_length();
+      default:
+        return TemplateArrayAllocation::SlotForInput(pos);
+    }
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CreateArrayInstr);
 };
@@ -6467,6 +6522,15 @@
     return false;
   }
 
+  virtual const Slot* SlotForInput(intptr_t pos) {
+    switch (pos) {
+      case kLengthPos:
+        return &Slot::TypedDataBase_length();
+      default:
+        return TemplateArrayAllocation::SlotForInput(pos);
+    }
+  }
+
  private:
   const classid_t class_id_;
 
@@ -6626,7 +6690,7 @@
 
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
-  bool IsImmutableLengthLoad() const;
+  bool IsImmutableLengthLoad() const { return slot().IsImmutableLengthSlot(); }
 
   // Try evaluating this load against the given constant value of
   // the instance. Returns true if evaluation succeeded and
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 8f9792f..b954bee 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -657,10 +657,10 @@
 
 void AllocationInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   Definition::PrintOperandsTo(f);
-  if (InputCount() > 0) {
-    f->AddString(", ");
-  }
   if (Identity().IsNotAliased()) {
+    if (InputCount() > 0) {
+      f->AddString(", ");
+    }
     f->AddString("<not-aliased>");
   }
 }
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index b65bdf1..cfc40b2 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2792,6 +2792,7 @@
     case Slot::Kind::kGrowableObjectArray_data:
     case Slot::Kind::kContext_parent:
     case Slot::Kind::kTypeArguments:
+    case Slot::Kind::kArray_type_arguments:
     case Slot::Kind::kClosure_context:
     case Slot::Kind::kClosure_delayed_type_arguments:
     case Slot::Kind::kClosure_function:
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index bda4322..e00327a 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -227,6 +227,19 @@
     }
   }
 
+  // Construct a place from an allocation where the place represents a store to
+  // a slot that corresponds to the given input position.
+  // Otherwise, constructs a kNone place.
+  Place(AllocationInstr* alloc, intptr_t input_pos)
+      : flags_(0), instance_(nullptr), raw_selector_(0), id_(0) {
+    if (const Slot* slot = alloc->SlotForInput(input_pos)) {
+      set_representation(alloc->RequiredInputRepresentation(input_pos));
+      instance_ = alloc;
+      set_kind(kInstanceField);
+      instance_field_ = slot;
+    }
+  }
+
   bool IsConstant(Object* value) const {
     switch (kind()) {
       case kInstanceField:
@@ -443,12 +456,9 @@
   static Place* Wrap(Zone* zone, const Place& place, intptr_t id);
 
   static bool IsAllocation(Definition* defn) {
-    return (defn != NULL) &&
-           (defn->IsAllocateObject() || defn->IsAllocateClosure() ||
-            defn->IsCreateArray() || defn->IsAllocateTypedData() ||
-            defn->IsAllocateUninitializedContext() ||
-            (defn->IsStaticCall() &&
-             defn->AsStaticCall()->IsRecognizedFactory()));
+    return (defn != NULL) && (defn->IsAllocation() ||
+                              (defn->IsStaticCall() &&
+                               defn->AsStaticCall()->IsRecognizedFactory()));
   }
 
  private:
@@ -1083,13 +1093,46 @@
           }
         }
         return true;
+      } else if (auto* const alloc = instr->AsAllocation()) {
+        // Treat inputs to an allocation instruction exactly as if they were
+        // manually stored using a StoreInstanceField instruction.
+        if (alloc->Identity().IsAliased()) {
+          return true;
+        }
+        Place input_place(alloc, use->use_index());
+        if (HasLoadsFromPlace(alloc, &input_place)) {
+          return true;
+        }
+        if (alloc->Identity().IsUnknown()) {
+          alloc->SetIdentity(AliasIdentity::NotAliased());
+          aliasing_worklist_.Add(alloc);
+        }
       }
     }
     return false;
   }
 
+  void MarkDefinitionAsAliased(Definition* d) {
+    auto* const defn = d->OriginalDefinition();
+    if (defn->Identity().IsNotAliased()) {
+      defn->SetIdentity(AliasIdentity::Aliased());
+      identity_rollback_.Add(defn);
+
+      // Add to worklist to propagate the mark transitively.
+      aliasing_worklist_.Add(defn);
+    }
+  }
+
   // Mark any value stored into the given object as potentially aliased.
   void MarkStoredValuesEscaping(Definition* defn) {
+    // Find all inputs corresponding to fields if allocating an object.
+    if (auto* const alloc = defn->AsAllocation()) {
+      for (intptr_t i = 0; i < alloc->InputCount(); i++) {
+        if (auto* const slot = alloc->SlotForInput(i)) {
+          MarkDefinitionAsAliased(alloc->InputAt(i)->definition());
+        }
+      }
+    }
     // Find all stores into this object.
     for (Value* use = defn->input_use_list(); use != NULL;
          use = use->next_use()) {
@@ -1100,15 +1143,8 @@
       }
       if ((use->use_index() == StoreInstanceFieldInstr::kInstancePos) &&
           instr->IsStoreInstanceField()) {
-        StoreInstanceFieldInstr* store = instr->AsStoreInstanceField();
-        Definition* value = store->value()->definition()->OriginalDefinition();
-        if (value->Identity().IsNotAliased()) {
-          value->SetIdentity(AliasIdentity::Aliased());
-          identity_rollback_.Add(value);
-
-          // Add to worklist to propagate the mark transitively.
-          aliasing_worklist_.Add(value);
-        }
+        MarkDefinitionAsAliased(
+            instr->AsStoreInstanceField()->value()->definition());
       }
     }
   }
@@ -1547,7 +1583,7 @@
 }
 
 void DelayAllocations::Optimize(FlowGraph* graph) {
-  // Go through all AllocateObject instructions and move them down to their
+  // Go through all Allocation instructions and move them down to their
   // dominant use when doing so is sound.
   DirectChainedHashMap<IdentitySetKeyValueTrait<Instruction*>> moved;
   for (BlockIterator block_it = graph->reverse_postorder_iterator();
@@ -1557,10 +1593,8 @@
     for (ForwardInstructionIterator instr_it(block); !instr_it.Done();
          instr_it.Advance()) {
       Definition* def = instr_it.Current()->AsDefinition();
-      if (def != nullptr &&
-          (def->IsAllocateObject() || def->IsAllocateClosure() ||
-           def->IsCreateArray()) &&
-          def->env() == nullptr && !moved.HasKey(def)) {
+      if (def != nullptr && def->IsAllocation() && def->env() == nullptr &&
+          !moved.HasKey(def)) {
         Instruction* use = DominantUse(def);
         if (use != nullptr && !use->IsPhi() && IsOneTimeUse(use, def)) {
           instr_it.RemoveCurrentFromGraph();
@@ -2014,31 +2048,56 @@
           continue;
         }
 
-        if (auto alloc = instr->AsAllocateObject()) {
+        if (auto* const alloc = instr->AsAllocation()) {
+          if (!alloc->ObjectIsInitialized()) {
+            // Since the allocated object is uninitialized, we can't forward
+            // any values from it.
+            continue;
+          }
           for (Value* use = alloc->input_use_list(); use != NULL;
                use = use->next_use()) {
-            // Look for all immediate loads/stores from this object.
             if (use->use_index() != 0) {
+              // Not a potential immediate load or store, since they take the
+              // instance as the first input.
               continue;
             }
+            intptr_t place_id = -1;
+            Definition* forward_def = nullptr;
             const Slot* slot = nullptr;
-            intptr_t place_id = 0;
-            if (auto load = use->instruction()->AsLoadField()) {
-              slot = &load->slot();
+            if (auto* const load = use->instruction()->AsLoadField()) {
               place_id = GetPlaceId(load);
-            } else if (auto store =
+              slot = &load->slot();
+            } else if (auto* const store =
                            use->instruction()->AsStoreInstanceField()) {
-              slot = &store->slot();
+              ASSERT(!alloc->IsArrayAllocation());
               place_id = GetPlaceId(store);
+              slot = &store->slot();
+            } else if (use->instruction()->IsLoadIndexed() ||
+                       use->instruction()->IsStoreIndexed()) {
+              ASSERT(alloc->IsArrayAllocation());
+              if (alloc->IsAllocateTypedData()) {
+                // Typed data payload elements are unboxed and initialized to
+                // zero, so don't forward a tagged null value.
+                continue;
+              }
+              if (aliased_set_->CanBeAliased(alloc)) {
+                continue;
+              }
+              place_id = GetPlaceId(use->instruction());
+              if (aliased_set_->places()[place_id]->kind() !=
+                  Place::kConstantIndexed) {
+                continue;
+              }
+              // Set initial value of array element to null.
+              forward_def = graph_->constant_null();
+            } else {
+              // Not an immediate load or store.
+              continue;
             }
 
+            ASSERT(place_id != -1);
             if (slot != nullptr) {
-              // Found a load/store. For object allocation, forward initial
-              // values of the fields to subsequent loads (and potential dead
-              // stores). For most fields, this is null, except for the type
-              // arguments slot. However, we do not forward an initial null
-              // value for final fields of escaping objects.
-              //
+              ASSERT(forward_def == nullptr);
               // Final fields are initialized in constructors. However, at the
               // same time we assume that known values of final fields can be
               // forwarded across side-effects. For an escaping object, one such
@@ -2051,89 +2110,20 @@
                 continue;
               }
 
-              Definition* forward_def = graph_->constant_null();
-              if (alloc->type_arguments() != nullptr) {
-                const Slot& type_args_slot = Slot::GetTypeArgumentsSlotFor(
-                    graph_->thread(), alloc->cls());
-                if (slot->IsIdentical(type_args_slot)) {
-                  forward_def = alloc->type_arguments()->definition();
-                }
+              const intptr_t pos = alloc->InputForSlot(*slot);
+              if (pos != -1) {
+                forward_def = alloc->InputAt(pos)->definition();
+              } else {
+                // Fields not provided as an input to the instruction are
+                // initialized to null during allocation.
+                forward_def = graph_->constant_null();
               }
-              gen->Add(place_id);
-              if (out_values == nullptr) out_values = CreateBlockOutValues();
-              (*out_values)[place_id] = forward_def;
-            }
-          }
-          continue;
-        } else if (auto alloc = instr->AsAllocateClosure()) {
-          for (Value* use = alloc->input_use_list(); use != nullptr;
-               use = use->next_use()) {
-            // Look for all immediate loads/stores from this object.
-            if (use->use_index() != 0) {
-              continue;
-            }
-            const Slot* slot = nullptr;
-            intptr_t place_id = 0;
-            if (auto load = use->instruction()->AsLoadField()) {
-              slot = &load->slot();
-              place_id = GetPlaceId(load);
-            } else if (auto store =
-                           use->instruction()->AsStoreInstanceField()) {
-              slot = &store->slot();
-              place_id = GetPlaceId(store);
             }
 
-            if (slot != nullptr) {
-              // Found a load/store. Initialize current value of the field
-              // to null.
-              //
-              // Note that unlike objects in general, there is no _Closure
-              // constructor in Dart code, but instead the FlowGraphBuilder
-              // explicitly initializes each non-null closure field in the flow
-              // graph with StoreInstanceField instructions post-allocation.
-              Definition* forward_def = graph_->constant_null();
-              // Forward values passed as AllocateClosureInstr inputs.
-              if (slot->IsIdentical(Slot::Closure_function())) {
-                forward_def = alloc->closure_function()->definition();
-              }
-              gen->Add(place_id);
-              if (out_values == nullptr) out_values = CreateBlockOutValues();
-              (*out_values)[place_id] = forward_def;
-            }
-          }
-          continue;
-        } else if (auto alloc = instr->AsCreateArray()) {
-          for (Value* use = alloc->input_use_list(); use != nullptr;
-               use = use->next_use()) {
-            // Look for all immediate loads/stores from this object.
-            if (use->use_index() != 0) {
-              continue;
-            }
-            intptr_t place_id = -1;
-            Definition* forward_def = nullptr;
-            if (auto load = use->instruction()->AsLoadField()) {
-              if (load->slot().IsTypeArguments()) {
-                place_id = GetPlaceId(load);
-                forward_def = alloc->type_arguments()->definition();
-              }
-            } else if (use->instruction()->IsLoadIndexed() ||
-                       use->instruction()->IsStoreIndexed()) {
-              if (aliased_set_->CanBeAliased(alloc)) {
-                continue;
-              }
-              place_id = GetPlaceId(use->instruction());
-              if (aliased_set_->places()[place_id]->kind() !=
-                  Place::kConstantIndexed) {
-                continue;
-              }
-              // Set initial value of array element to null.
-              forward_def = graph_->constant_null();
-            }
-            if (forward_def != nullptr) {
-              gen->Add(place_id);
-              if (out_values == nullptr) out_values = CreateBlockOutValues();
-              (*out_values)[place_id] = forward_def;
-            }
+            ASSERT(forward_def != nullptr);
+            gen->Add(place_id);
+            if (out_values == nullptr) out_values = CreateBlockOutValues();
+            (*out_values)[place_id] = forward_def;
           }
           continue;
         }
@@ -3089,21 +3079,22 @@
 // Returns true if the given instruction is an allocation that
 // can be sunk by the Allocation Sinking pass.
 static bool IsSupportedAllocation(Instruction* instr) {
-  return instr->IsAllocateObject() || instr->IsAllocateUninitializedContext() ||
-         instr->IsAllocateClosure() ||
-         (instr->IsArrayAllocation() &&
+  return instr->IsAllocation() &&
+         (!instr->IsArrayAllocation() ||
           IsValidLengthForAllocationSinking(instr->AsArrayAllocation()));
 }
 
 enum SafeUseCheck { kOptimisticCheck, kStrictCheck };
 
 // Check if the use is safe for allocation sinking. Allocation sinking
-// candidates can only be used at store instructions:
+// candidates can only be used as inputs to store and allocation instructions:
 //
 //     - any store into the allocation candidate itself is unconditionally safe
 //       as it just changes the rematerialization state of this candidate;
-//     - store into another object is only safe if another object is allocation
-//       candidate.
+//     - store into another object is only safe if the other object is
+//       an allocation candidate.
+//     - use as input to another allocation is only safe if the other allocation
+//       is a candidate.
 //
 // We use a simple fix-point algorithm to discover the set of valid candidates
 // (see CollectCandidates method), that's why this IsSafeUse can operate in two
@@ -3124,6 +3115,12 @@
     return true;
   }
 
+  if (auto* const alloc = use->instruction()->AsAllocation()) {
+    return IsSupportedAllocation(alloc) &&
+           ((check_type == kOptimisticCheck) ||
+            alloc->Identity().IsAllocationSinkingCandidate());
+  }
+
   if (auto* store = use->instruction()->AsStoreInstanceField()) {
     if (use == store->value()) {
       Definition* instance = store->instance()->definition();
@@ -3191,10 +3188,13 @@
 // If the given use is a store into an object then return an object we are
 // storing into.
 static Definition* StoreDestination(Value* use) {
-  if (auto store = use->instruction()->AsStoreInstanceField()) {
+  if (auto* const alloc = use->instruction()->AsAllocation()) {
+    return alloc;
+  }
+  if (auto* const store = use->instruction()->AsStoreInstanceField()) {
     return store->instance()->definition();
   }
-  if (auto store = use->instruction()->AsStoreIndexed()) {
+  if (auto* const store = use->instruction()->AsStoreIndexed()) {
     return store->array()->definition();
   }
   return nullptr;
@@ -3222,11 +3222,36 @@
               alloc->ssa_temp_index());
   }
 
-  // As an allocation sinking candidate it is only used in stores to its own
-  // fields. Remove these stores.
-  for (Value* use = alloc->input_use_list(); use != NULL;
-       use = alloc->input_use_list()) {
-    use->instruction()->RemoveFromGraph();
+  // As an allocation sinking candidate, remove stores to this candidate.
+  // Do this in a two-step process, as this allocation may be used multiple
+  // times in a single instruction (e.g., as the instance and the value in
+  // a StoreInstanceField). This means multiple entries may be removed from the
+  // use list when removing instructions, not just the current one, so
+  // Value::Iterator cannot be safely used.
+  GrowableArray<Instruction*> stores_to_remove;
+  for (Value* use = alloc->input_use_list(); use != nullptr;
+       use = use->next_use()) {
+    Instruction* const instr = use->instruction();
+    Definition* const instance = StoreDestination(use);
+    // All uses of a candidate should be stores or other allocations.
+    ASSERT(instance != nullptr);
+    if (instance == alloc) {
+      // An allocation instruction cannot be a direct input to itself.
+      ASSERT(!instr->IsAllocation());
+      stores_to_remove.Add(instr);
+    } else {
+      // The candidate is being stored into another candidate, either through
+      // a store instruction or as the input to a to-be-eliminated allocation,
+      // so this instruction will be removed with the other candidate.
+      ASSERT(candidates_.Contains(instance));
+    }
+  }
+
+  for (auto* const store : stores_to_remove) {
+    // Avoid calling RemoveFromGraph() more than once on the same instruction.
+    if (store->previous() != nullptr) {
+      store->RemoveFromGraph();
+    }
   }
 
 // There should be no environment uses. The pass replaced them with
@@ -3236,7 +3261,7 @@
     ASSERT(use->instruction()->IsMaterializeObject());
   }
 #endif
-  ASSERT(alloc->input_use_list() == NULL);
+
   alloc->RemoveFromGraph();
 }
 
@@ -3482,7 +3507,8 @@
 
   // At this point we have computed the state of object at each deoptimization
   // point and we can eliminate it. Loads inserted above were forwarded so there
-  // are no uses of the allocation just as in the begging of the pass.
+  // are no uses of the allocation outside other candidates to eliminate, just
+  // as in the beginning of the pass.
   for (intptr_t i = 0; i < candidates_.length(); i++) {
     EliminateAllocation(candidates_[i]);
   }
@@ -3511,14 +3537,10 @@
 }
 
 // Add a field/offset to the list of fields if it is not yet present there.
-static bool AddSlot(ZoneGrowableArray<const Slot*>* slots, const Slot& slot) {
-  for (auto s : *slots) {
-    if (s == &slot) {
-      return false;
-    }
+static void AddSlot(ZoneGrowableArray<const Slot*>* slots, const Slot& slot) {
+  if (!slots->Contains(&slot)) {
+    slots->Add(&slot);
   }
-  slots->Add(&slot);
-  return true;
 }
 
 // Find deoptimization exit for the given materialization assuming that all
@@ -3611,6 +3633,9 @@
   } else if (auto instr = alloc->AsAllocateClosure()) {
     cls = &Class::ZoneHandle(
         flow_graph_->isolate_group()->object_store()->closure_class());
+  } else if (auto instr = alloc->AsAllocateContext()) {
+    cls = &Class::ZoneHandle(Object::context_class());
+    num_elements = instr->num_context_variables();
   } else if (auto instr = alloc->AsAllocateUninitializedContext()) {
     cls = &Class::ZoneHandle(Object::context_class());
     num_elements = instr->num_context_variables();
@@ -3711,6 +3736,8 @@
   for (Value* use = alloc->input_use_list(); use != NULL;
        use = use->next_use()) {
     if (StoreDestination(use) == alloc) {
+      // Allocation instructions cannot be used in as inputs to themselves.
+      ASSERT(!use->instruction()->AsAllocation());
       if (auto store = use->instruction()->AsStoreInstanceField()) {
         AddSlot(slots, store->slot());
       } else if (auto store = use->instruction()->AsStoreIndexed()) {
@@ -3729,27 +3756,18 @@
     }
   }
 
-  if (auto alloc_object = alloc->AsAllocateObject()) {
-    if (alloc_object->type_arguments() != nullptr) {
-      AddSlot(slots, Slot::GetTypeArgumentsSlotFor(flow_graph_->thread(),
-                                                   alloc_object->cls()));
+  if (auto* const allocation = alloc->AsAllocation()) {
+    for (intptr_t pos = 0; pos < allocation->InputCount(); pos++) {
+      if (auto* const slot = allocation->SlotForInput(pos)) {
+        // Don't add slots for immutable length slots if not already added
+        // above, as they are already represented as the number of elements in
+        // the MaterializeObjectInstr.
+        if (!slot->IsImmutableLengthSlot()) {
+          AddSlot(slots, *slot);
+        }
+      }
     }
   }
-  if (auto alloc_closure = alloc->AsAllocateClosure()) {
-    // Add slots for any instruction inputs. Any closure slots not listed below
-    // that are non-null are explicitly initialized post-allocation using
-    // StoreInstanceField instructions.
-    AddSlot(slots, Slot::Closure_function());
-  }
-  if (alloc->IsCreateArray()) {
-    AddSlot(
-        slots,
-        Slot::GetTypeArgumentsSlotFor(
-            flow_graph_->thread(),
-            Class::Handle(
-                Z,
-                flow_graph_->isolate_group()->object_store()->array_class())));
-  }
 
   // Collect all instructions that mention this object in the environment.
   exits_collector_.CollectTransitively(alloc);
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 473697b..aefb2d4 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -185,6 +185,68 @@
   return native_fields_.load()[static_cast<uint8_t>(kind)];
 }
 
+bool Slot::IsImmutableLengthSlot() const {
+  switch (kind()) {
+    case Slot::Kind::kArray_length:
+    case Slot::Kind::kTypedDataBase_length:
+    case Slot::Kind::kString_length:
+    case Slot::Kind::kTypeArguments_length:
+      return true;
+    case Slot::Kind::kGrowableObjectArray_length:
+      return false;
+
+      // Not length loads.
+#define UNBOXED_NATIVE_SLOT_CASE(Class, Untagged, Field, Rep, IsFinal)         \
+  case Slot::Kind::k##Class##_##Field:
+      UNBOXED_NATIVE_SLOTS_LIST(UNBOXED_NATIVE_SLOT_CASE)
+#undef UNBOXED_NATIVE_SLOT_CASE
+    case Slot::Kind::kLinkedHashMap_index:
+    case Slot::Kind::kLinkedHashMap_data:
+    case Slot::Kind::kLinkedHashMap_hash_mask:
+    case Slot::Kind::kLinkedHashMap_used_data:
+    case Slot::Kind::kLinkedHashMap_deleted_keys:
+    case Slot::Kind::kArgumentsDescriptor_type_args_len:
+    case Slot::Kind::kArgumentsDescriptor_positional_count:
+    case Slot::Kind::kArgumentsDescriptor_count:
+    case Slot::Kind::kArgumentsDescriptor_size:
+    case Slot::Kind::kArrayElement:
+    case Slot::Kind::kTypeArguments:
+    case Slot::Kind::kTypedDataView_offset_in_bytes:
+    case Slot::Kind::kTypedDataView_data:
+    case Slot::Kind::kGrowableObjectArray_data:
+    case Slot::Kind::kArray_type_arguments:
+    case Slot::Kind::kContext_parent:
+    case Slot::Kind::kClosure_context:
+    case Slot::Kind::kClosure_delayed_type_arguments:
+    case Slot::Kind::kClosure_function:
+    case Slot::Kind::kClosure_function_type_arguments:
+    case Slot::Kind::kClosure_instantiator_type_arguments:
+    case Slot::Kind::kClosure_hash:
+    case Slot::Kind::kCapturedVariable:
+    case Slot::Kind::kDartField:
+    case Slot::Kind::kFunction_data:
+    case Slot::Kind::kFunction_signature:
+    case Slot::Kind::kFunctionType_parameter_names:
+    case Slot::Kind::kFunctionType_parameter_types:
+    case Slot::Kind::kFunctionType_type_parameters:
+    case Slot::Kind::kPointerBase_data_field:
+    case Slot::Kind::kType_arguments:
+    case Slot::Kind::kTypeArgumentsIndex:
+    case Slot::Kind::kTypeParameters_names:
+    case Slot::Kind::kTypeParameters_flags:
+    case Slot::Kind::kTypeParameters_bounds:
+    case Slot::Kind::kTypeParameters_defaults:
+    case Slot::Kind::kTypeParameter_bound:
+    case Slot::Kind::kUnhandledException_exception:
+    case Slot::Kind::kUnhandledException_stacktrace:
+    case Slot::Kind::kWeakProperty_key:
+    case Slot::Kind::kWeakProperty_value:
+      return false;
+  }
+  UNREACHABLE();
+  return false;
+}
+
 // Note: should only be called with cids of array-like classes.
 const Slot& Slot::GetLengthFieldForArrayCid(intptr_t array_cid) {
   if (IsExternalTypedDataClassId(array_cid) || IsTypedDataClassId(array_cid) ||
@@ -215,6 +277,9 @@
 }
 
 const Slot& Slot::GetTypeArgumentsSlotFor(Thread* thread, const Class& cls) {
+  if (cls.id() == kArrayCid || cls.id() == kImmutableArrayCid) {
+    return Slot::Array_type_arguments();
+  }
   const intptr_t offset =
       compiler::target::Class::TypeArgumentsFieldOffset(cls);
   ASSERT(offset != Class::kNoTypeArguments);
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index a1daab1..221e371 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -52,6 +52,7 @@
 //   (i.e. initialized once at construction time and does not change after
 //   that) or like a non-final field.
 #define NULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                    \
+  V(Array, UntaggedArray, type_arguments, TypeArguments, FINAL)                \
   V(Function, UntaggedFunction, signature, FunctionType, FINAL)                \
   V(Context, UntaggedContext, parent, Context, FINAL)                          \
   V(Closure, UntaggedClosure, instantiator_type_arguments, TypeArguments,      \
@@ -237,6 +238,7 @@
   bool IsTypeArguments() const { return kind() == Kind::kTypeArguments; }
   bool IsArgumentOfType() const { return kind() == Kind::kTypeArgumentsIndex; }
   bool IsArrayElement() const { return kind() == Kind::kArrayElement; }
+  bool IsImmutableLengthSlot() const;
 
   const char* Name() const;
 
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 9e3e05f..e1f2ce3 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -890,9 +890,10 @@
 }
 
 Fragment BaseFlowGraphBuilder::AllocateClosure(TokenPosition position) {
+  auto const context = Pop();
   auto const function = Pop();
-  auto* allocate = new (Z) AllocateClosureInstr(InstructionSource(position),
-                                                function, GetNextDeoptId());
+  auto* allocate = new (Z) AllocateClosureInstr(
+      InstructionSource(position), function, context, GetNextDeoptId());
   Push(allocate);
   return Fragment(allocate);
 }
@@ -999,6 +1000,8 @@
   // here as these can be unoptimized call sites.
   LocalVariable* pointer = MakeTemporary();
 
+  code += Constant(target);
+
   auto& context_slots = CompilerState::Current().GetDummyContextSlots(
       /*context_id=*/0, /*num_variables=*/1);
   code += AllocateContext(context_slots);
@@ -1008,17 +1011,10 @@
   code += LoadLocal(pointer);
   code += StoreNativeField(*context_slots[0]);
 
-  code += Constant(target);
   code += AllocateClosure();
-  LocalVariable* closure = MakeTemporary();
 
-  code += LoadLocal(closure);
-  code += LoadLocal(context);
-  code += StoreNativeField(Slot::Closure_context(),
-                           StoreInstanceFieldInstr::Kind::kInitializing);
-
-  // Drop address and context.
-  code += DropTempsPreserveTop(2);
+  // Drop address.
+  code += DropTempsPreserveTop(1);
 
   return code;
 }
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 5c94964..d748f67 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -4380,10 +4380,12 @@
   Fragment instructions = BuildExpression();
   LocalVariable* original_closure = MakeTemporary();
 
-  // Load the target function and allocate the closure.
+  // Load the target function and context and allocate the closure.
   instructions += LoadLocal(original_closure);
   instructions +=
       flow_graph_builder_->LoadNativeField(Slot::Closure_function());
+  instructions += LoadLocal(original_closure);
+  instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
   instructions += flow_graph_builder_->AllocateClosure();
   LocalVariable* new_closure = MakeTemporary();
 
@@ -4433,13 +4435,6 @@
       Slot::Closure_function_type_arguments(),
       StoreInstanceFieldInstr::Kind::kInitializing);
 
-  // Copy over the context.
-  instructions += LoadLocal(new_closure);
-  instructions += LoadLocal(original_closure);
-  instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
-  instructions += flow_graph_builder_->StoreNativeField(
-      Slot::Closure_context(), StoreInstanceFieldInstr::Kind::kInitializing);
-
   instructions += DropTempsPreserveTop(1);  // Drop old closure.
 
   return instructions;
@@ -5604,6 +5599,7 @@
 
   Fragment instructions;
   instructions += Constant(function);
+  instructions += LoadLocal(parsed_function()->current_context_var());
   instructions += flow_graph_builder_->AllocateClosure();
   LocalVariable* closure = MakeTemporary();
 
@@ -5634,12 +5630,6 @@
         StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
-  // Store the context in the closure.
-  instructions += LoadLocal(closure);
-  instructions += LoadLocal(parsed_function()->current_context_var());
-  instructions += flow_graph_builder_->StoreNativeField(
-      Slot::Closure_context(), StoreInstanceFieldInstr::Kind::kInitializing);
-
   return instructions;
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index ff70644..a3f7ea7 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1592,8 +1592,28 @@
 
 Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
     const Function& target) {
+  // The function cannot be local and have parent generic functions.
+  ASSERT(!target.HasGenericParent());
+
   Fragment fragment;
   fragment += Constant(target);
+
+  // Allocate a context that closes over `this`.
+  // Note: this must be kept in sync with ScopeBuilder::BuildScopes.
+  const LocalScope* implicit_closure_scope =
+      MakeImplicitClosureScope(Z, Class::Handle(Z, target.Owner()));
+  fragment += AllocateContext(implicit_closure_scope->context_slots());
+  LocalVariable* context = MakeTemporary();
+
+  // Store `this`.  The context doesn't need a parent pointer because it doesn't
+  // close over anything else.
+  fragment += LoadLocal(context);
+  fragment += LoadLocal(parsed_function_->receiver_var());
+  fragment += StoreNativeField(
+      Slot::GetContextVariableSlotFor(
+          thread_, *implicit_closure_scope->context_variables()[0]),
+      StoreInstanceFieldInstr::Kind::kInitializing);
+
   fragment += AllocateClosure();
   LocalVariable* closure = MakeTemporary();
 
@@ -1605,22 +1625,6 @@
                                  StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
-  // The function cannot be local and have parent generic functions.
-  ASSERT(!target.HasGenericParent());
-
-  // Allocate a context that closes over `this`.
-  // Note: this must be kept in sync with ScopeBuilder::BuildScopes.
-  const LocalScope* implicit_closure_scope =
-      MakeImplicitClosureScope(Z, Class::Handle(Z, target.Owner()));
-  fragment += AllocateContext(implicit_closure_scope->context_slots());
-  LocalVariable* context = MakeTemporary();
-
-  // Store the context in the closure.
-  fragment += LoadLocal(closure);
-  fragment += LoadLocal(context);
-  fragment += StoreNativeField(Slot::Closure_context(),
-                               StoreInstanceFieldInstr::Kind::kInitializing);
-
   if (target.IsGeneric()) {
     // Only generic functions need to have properly initialized
     // delayed_type_arguments.
@@ -1630,15 +1634,6 @@
                                  StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
-  // The context is on top of the operand stack.  Store `this`.  The context
-  // doesn't need a parent pointer because it doesn't close over anything
-  // else.
-  fragment += LoadLocal(parsed_function_->receiver_var());
-  fragment += StoreNativeField(
-      Slot::GetContextVariableSlotFor(
-          thread_, *implicit_closure_scope->context_variables()[0]),
-      StoreInstanceFieldInstr::Kind::kInitializing);
-
   return fragment;
 }
 
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 6862f50..a880734 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -527,7 +527,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 20;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 64;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
@@ -1072,7 +1072,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 40;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 104;
+static constexpr dart::compiler::target::word Script_InstanceSize = 96;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -1607,7 +1607,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 20;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 64;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
@@ -2153,7 +2153,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 40;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 104;
+static constexpr dart::compiler::target::word Script_InstanceSize = 96;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -2697,7 +2697,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word Script_InstanceSize = 64;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -3242,7 +3242,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word Script_InstanceSize = 64;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -3776,7 +3776,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
@@ -4315,7 +4315,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -4844,7 +4844,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
@@ -5384,7 +5384,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -5922,7 +5922,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 16;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 64;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -6461,7 +6461,7 @@
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 16;
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 64;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
@@ -7062,7 +7062,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 20;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
@@ -7669,7 +7669,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -8280,7 +8280,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -8887,7 +8887,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -9495,7 +9495,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -10093,7 +10093,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
@@ -10693,7 +10693,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -11297,7 +11297,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -11897,7 +11897,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
@@ -12498,7 +12498,7 @@
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 7e42bc2..53c2924 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -768,6 +768,9 @@
       target::RoundedAllocationSize(target::Closure::InstanceSize());
   __ EnsureHasClassIdInDEBUG(kFunctionCid, AllocateClosureABI::kFunctionReg,
                              AllocateClosureABI::kScratchReg);
+  __ EnsureHasClassIdInDEBUG(kContextCid, AllocateClosureABI::kContextReg,
+                             AllocateClosureABI::kScratchReg,
+                             /*can_be_null=*/true);
   if (!FLAG_use_slow_path && FLAG_inline_alloc) {
     Label slow_case;
     __ Comment("Inline allocation of uninitialized closure");
@@ -799,7 +802,7 @@
     __ StoreToSlotNoBarrier(AllocateClosureABI::kFunctionReg,
                             AllocateClosureABI::kResultReg,
                             Slot::Closure_function());
-    __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
+    __ StoreToSlotNoBarrier(AllocateClosureABI::kContextReg,
                             AllocateClosureABI::kResultReg,
                             Slot::Closure_context());
     __ StoreToSlotNoBarrier(AllocateClosureABI::kScratchReg,
@@ -834,7 +837,9 @@
   __ EnterStubFrame();
   __ PushObject(NullObject());  // Space on the stack for the return value.
   __ PushRegister(AllocateClosureABI::kFunctionReg);
-  __ CallRuntime(kAllocateClosureRuntimeEntry, 1);
+  __ PushRegister(AllocateClosureABI::kContextReg);
+  __ CallRuntime(kAllocateClosureRuntimeEntry, 2);
+  __ PopRegister(AllocateClosureABI::kContextReg);
   __ PopRegister(AllocateClosureABI::kFunctionReg);
   __ PopRegister(AllocateClosureABI::kResultReg);
   ASSERT(target::WillAllocateNewOrRememberedObject(instance_size));
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 5380c8c..41d995d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -263,17 +263,20 @@
     __ Bind(&done);
   }
 
+  // Put context in right register for AllocateClosure call.
+  __ MoveRegister(AllocateClosureABI::kContextReg, R0);
+
   // Store receiver in context
-  __ ldr(R1, Address(FP, target::kWordSize * kReceiverOffset));
-  __ StoreIntoObject(R0, FieldAddress(R0, target::Context::variable_offset(0)),
-                     R1);
+  __ ldr(AllocateClosureABI::kScratchReg,
+         Address(FP, target::kWordSize * kReceiverOffset));
+  __ StoreIntoObject(AllocateClosureABI::kContextReg,
+                     FieldAddress(AllocateClosureABI::kContextReg,
+                                  target::Context::variable_offset(0)),
+                     AllocateClosureABI::kScratchReg);
 
-  // Pop function before pushing context.
+  // Pop function.
   __ Pop(AllocateClosureABI::kFunctionReg);
 
-  // Push context.
-  __ Push(R0);
-
   // Allocate closure. After this point, we only use the registers in
   // AllocateClosureABI.
   __ LoadObject(CODE_REG, closure_allocation_stub);
@@ -282,11 +285,6 @@
   __ blx(AllocateClosureABI::kScratchReg);
 
   // Populate closure object.
-  __ Pop(AllocateClosureABI::kScratchReg);  // Pop context.
-  __ StoreIntoObject(AllocateClosureABI::kResultReg,
-                     FieldAddress(AllocateClosureABI::kResultReg,
-                                  target::Closure::context_offset()),
-                     AllocateClosureABI::kScratchReg);
   __ Pop(AllocateClosureABI::kScratchReg);  // Pop type arguments.
   __ StoreIntoObjectNoBarrier(
       AllocateClosureABI::kResultReg,
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 7f677dd..5626553 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -500,17 +500,20 @@
     __ Bind(&done);
   }
 
+  // Put context in right register for AllocateClosure call.
+  __ MoveRegister(AllocateClosureABI::kContextReg, R0);
+
   // Store receiver in context
-  __ ldr(R1, Address(FP, target::kWordSize * kReceiverOffset));
-  __ StoreIntoObject(R0, FieldAddress(R0, target::Context::variable_offset(0)),
-                     R1);
+  __ ldr(AllocateClosureABI::kScratchReg,
+         Address(FP, target::kWordSize * kReceiverOffset));
+  __ StoreIntoObject(AllocateClosureABI::kContextReg,
+                     FieldAddress(AllocateClosureABI::kContextReg,
+                                  target::Context::variable_offset(0)),
+                     AllocateClosureABI::kScratchReg);
 
   // Pop function before pushing context.
   __ Pop(AllocateClosureABI::kFunctionReg);
 
-  // Push context.
-  __ Push(R0);
-
   // Allocate closure. After this point, we only use the registers in
   // AllocateClosureABI.
   __ LoadObject(CODE_REG, closure_allocation_stub);
@@ -519,11 +522,6 @@
   __ blr(AllocateClosureABI::kScratchReg);
 
   // Populate closure object.
-  __ Pop(AllocateClosureABI::kScratchReg);  // Pop context.
-  __ StoreIntoObject(AllocateClosureABI::kResultReg,
-                     FieldAddress(AllocateClosureABI::kResultReg,
-                                  target::Closure::context_offset()),
-                     AllocateClosureABI::kScratchReg);
   __ Pop(AllocateClosureABI::kScratchReg);  // Pop type arguments.
   __ StoreIntoObjectNoBarrier(
       AllocateClosureABI::kResultReg,
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index b65cc5e..c6339b3 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -443,28 +443,26 @@
     __ Bind(&done);
   }
 
+  // Put context in right register for AllocateClosure call.
+  __ MoveRegister(AllocateClosureABI::kContextReg, RAX);
+
   // Store receiver in context
-  __ movq(RSI, Address(RBP, target::kWordSize * kReceiverOffsetInWords));
-  __ StoreIntoObject(
-      RAX, FieldAddress(RAX, target::Context::variable_offset(0)), RSI);
+  __ movq(AllocateClosureABI::kScratchReg,
+          Address(RBP, target::kWordSize * kReceiverOffsetInWords));
+  __ StoreIntoObject(AllocateClosureABI::kContextReg,
+                     FieldAddress(AllocateClosureABI::kContextReg,
+                                  target::Context::variable_offset(0)),
+                     AllocateClosureABI::kScratchReg);
 
-  // Pop function before pushing context.
+  // Pop function.
   __ popq(AllocateClosureABI::kFunctionReg);
 
-  // Push context.
-  __ pushq(RAX);
-
   // Allocate closure. After this point, we only use the registers in
   // AllocateClosureABI.
   __ LoadObject(CODE_REG, closure_allocation_stub);
   __ call(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 
   // Populate closure object.
-  __ popq(AllocateClosureABI::kScratchReg);  // Pop context.
-  __ StoreIntoObject(AllocateClosureABI::kResultReg,
-                     FieldAddress(AllocateClosureABI::kResultReg,
-                                  target::Closure::context_offset()),
-                     AllocateClosureABI::kScratchReg);
   __ popq(AllocateClosureABI::kScratchReg);  // Pop type argument vector.
   __ StoreIntoObjectNoBarrier(
       AllocateClosureABI::kResultReg,
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 8313e51..b72a093 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -458,6 +458,7 @@
 struct AllocateClosureABI {
   static const Register kResultReg = AllocateObjectABI::kResultReg;
   static const Register kFunctionReg = R1;
+  static const Register kContextReg = R2;
   static const Register kScratchReg = R4;
 };
 
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 53d827a..28cbf1d 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -298,6 +298,7 @@
 struct AllocateClosureABI {
   static const Register kResultReg = AllocateObjectABI::kResultReg;
   static const Register kFunctionReg = R1;
+  static const Register kContextReg = R2;
   static const Register kScratchReg = R4;
 };
 
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 9216fcc..df188c2 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -209,6 +209,7 @@
 struct AllocateClosureABI {
   static const Register kResultReg = AllocateObjectABI::kResultReg;
   static const Register kFunctionReg = EBX;
+  static const Register kContextReg = ECX;
   static const Register kScratchReg = EDX;
 };
 
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index dc02fa4..e20d755 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -270,6 +270,7 @@
 struct AllocateClosureABI {
   static const Register kResultReg = AllocateObjectABI::kResultReg;
   static const Register kFunctionReg = RBX;
+  static const Register kContextReg = RDX;
   static const Register kScratchReg = R13;
 };
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 422d7b4..2b64b3f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11805,14 +11805,6 @@
   StoreNonPointer(&untag()->load_timestamp_, value);
 }
 
-void Script::SetLocationOffset(intptr_t line_offset,
-                               intptr_t col_offset) const {
-  ASSERT(line_offset >= 0);
-  ASSERT(col_offset >= 0);
-  StoreNonPointer(&untag()->line_offset_, line_offset);
-  StoreNonPointer(&untag()->col_offset_, col_offset);
-}
-
 bool Script::IsValidTokenPosition(TokenPosition token_pos) const {
   const TokenPosition& max_position = MaxPosition();
   // We may end up with scripts that have the empty string as a source file
@@ -12033,7 +12025,6 @@
   result.set_resolved_url(
       String::Handle(zone, Symbols::New(thread, resolved_url)));
   result.set_source(source);
-  result.SetLocationOffset(0, 0);
   NOT_IN_PRECOMPILED(result.SetLazyLookupSourceAndLineStarts(false));
   NOT_IN_PRECOMPILED(result.SetHasCachedMaxPosition(false));
   result.set_kernel_script_index(0);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d6a92d4..1d513f3c9 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4455,8 +4455,8 @@
   void LookupSourceAndLineStarts(Zone* zone) const;
   GrowableObjectArrayPtr GenerateLineNumberArray() const;
 
-  intptr_t line_offset() const { return untag()->line_offset_; }
-  intptr_t col_offset() const { return untag()->col_offset_; }
+  intptr_t line_offset() const { return 0; }
+  intptr_t col_offset() const { return 0; }
   // Returns the max real token position for this script, or kNoSource
   // if there is no line starts information.
   TokenPosition MaxPosition() const;
@@ -4498,8 +4498,6 @@
                        intptr_t to_line,
                        intptr_t to_column) const;
 
-  void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
-
   // For real token positions when line starts are available, returns whether or
   // not a GetTokenLocation call would succeed. Returns true for non-real token
   // positions or if there is no line starts information.
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index a2af1aa..4d2a1fc 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2368,75 +2368,6 @@
   }
 }
 
-static void CheckLinesWithOffset(Zone* zone, const intptr_t offset) {
-  const char* url_chars = "";
-  // Nine lines, mix of \n, \r, \r\n line terminators, lines 3, 4, 7, and 8
-  // are non-empty. Ends with a \r as a double-check that the \r followed by
-  // \n check doesn't go out of bounds.
-  //
-  // Line starts:             1 2 3    4      5 6   7    8    9
-  const char* source_chars = "\n\nxyz\nabc\r\n\n\r\ndef\rghi\r";
-  const String& url = String::Handle(zone, String::New(url_chars));
-  const String& source = String::Handle(zone, String::New(source_chars));
-  const Script& script = Script::Handle(zone, Script::New(url, source));
-  EXPECT(!script.IsNull());
-  EXPECT(script.IsScript());
-  script.SetLocationOffset(offset, 10);
-  auto& str = String::Handle(zone);
-  str = script.GetLine(offset + 1);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 2);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 3);
-  EXPECT_STREQ("xyz", str.ToCString());
-  str = script.GetLine(offset + 4);
-  EXPECT_STREQ("abc", str.ToCString());
-  str = script.GetLine(offset + 5);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 6);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 7);
-  EXPECT_STREQ("def", str.ToCString());
-  str = script.GetLine(offset + 8);
-  EXPECT_STREQ("ghi", str.ToCString());
-  str = script.GetLine(offset + 9);
-  EXPECT_STREQ("", str.ToCString());
-  // Using "column" of \r at end of line for to_column.
-  str = script.GetSnippet(offset + 3, 1, offset + 7, 4);
-  EXPECT_STREQ("xyz\nabc\r\n\n\r\ndef", str.ToCString());
-  // Lines not in the range of (1-based) line indices in the source should
-  // return the empty string.
-  str = script.GetLine(-500);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(0);
-  EXPECT_STREQ("", str.ToCString());
-  if (offset > 0) {
-    str = script.GetLine(1);  // Absolute, not relative to offset.
-    EXPECT_STREQ("", str.ToCString());
-  }
-  if (offset > 2) {
-    str = script.GetLine(3);  // Absolute, not relative to offset.
-    EXPECT_STREQ("", str.ToCString());
-  }
-  str = script.GetLine(offset - 500);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 10);
-  EXPECT_STREQ("", str.ToCString());
-  str = script.GetLine(offset + 10000);
-  EXPECT_STREQ("", str.ToCString());
-  // Snippets not contained within the source should be the null string.
-  str = script.GetSnippet(-1, 1, 2, 2);
-  EXPECT(str.IsNull());
-  str = script.GetSnippet(offset - 1, 1, offset + 2, 2);
-  EXPECT(str.IsNull());
-  str = script.GetSnippet(offset + 5, 15, offset + 6, 2);
-  EXPECT(str.IsNull());
-  str = script.GetSnippet(offset + 20, 1, offset + 30, 1);
-  EXPECT(str.IsNull());
-}
-
 ISOLATE_UNIT_TEST_CASE(Script) {
   {
     const char* url_chars = "builtin:test-case";
@@ -2458,10 +2389,6 @@
     EXPECT_EQ('.', str.CharAt(21));
   }
 
-  CheckLinesWithOffset(Z, 0);
-  CheckLinesWithOffset(Z, 500);
-  CheckLinesWithOffset(Z, 10000);
-
   {
     const char* url_chars = "";
     // Single line, no terminators.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f567ae7..c3c1017 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1575,8 +1575,6 @@
     return NULL;
   }
 
-  int32_t line_offset_;
-  int32_t col_offset_;
 #if !defined(DART_PRECOMPILED_RUNTIME)
   int32_t flags_and_max_position_;
 
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 7584d90..60248f2 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -627,16 +627,19 @@
   UNREACHABLE();
 }
 
-// Allocate a new closure and initializes its function field with the argument
-// and all other fields to null.
+// Allocate a new closure and initializes its function and context fields with
+// the arguments and all other fields to null.
+// Arg0: function.
+// Arg1: context.
 // Return value: newly allocated closure.
-DEFINE_RUNTIME_ENTRY(AllocateClosure, 1) {
+DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) {
   const auto& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
+  const auto& context = Context::CheckedHandle(zone, arguments.ArgAt(1));
   const Closure& closure = Closure::Handle(
-      zone, Closure::New(
-                Object::null_type_arguments(), Object::null_type_arguments(),
-                Object::null_type_arguments(), function,
-                Context::Handle(Context::null()), SpaceForRuntimeAllocation()));
+      zone,
+      Closure::New(Object::null_type_arguments(), Object::null_type_arguments(),
+                   Object::null_type_arguments(), function, context,
+                   SpaceForRuntimeAllocation()));
   arguments.SetReturn(closure);
 }
 
diff --git a/tests/language/vm/allocate_overflow_bytearray_test.dart b/tests/language/vm/allocate_overflow_bytearray_test.dart
index 9242494..905203f 100644
--- a/tests/language/vm/allocate_overflow_bytearray_test.dart
+++ b/tests/language/vm/allocate_overflow_bytearray_test.dart
@@ -19,26 +19,31 @@
 
 main() {
   for (int interestingLength in interestingLengths) {
+    bool exceptionCheck(e) {
+      // Allow RangeError as the range check may happen before the allocation.
+      return e is RangeError || e is OutOfMemoryError;
+    }
+
     print(interestingLength);
 
     Expect.throws(() {
       var bytearray = new Uint8List(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new Uint8ClampedList(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new Int8List(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new ByteData(interestingLength);
       print(bytearray.getUint8(0));
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
   }
 }
diff --git a/tests/language_2/vm/allocate_overflow_bytearray_test.dart b/tests/language_2/vm/allocate_overflow_bytearray_test.dart
index d98f921..d9aa360 100644
--- a/tests/language_2/vm/allocate_overflow_bytearray_test.dart
+++ b/tests/language_2/vm/allocate_overflow_bytearray_test.dart
@@ -21,26 +21,31 @@
 
 main() {
   for (int interestingLength in interestingLengths) {
+    bool exceptionCheck(e) {
+      // Allow RangeError as the range check may happen before the allocation.
+      return e is RangeError || e is OutOfMemoryError;
+    }
+
     print(interestingLength);
 
     Expect.throws(() {
       var bytearray = new Uint8List(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new Uint8ClampedList(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new Int8List(interestingLength);
       print(bytearray.first);
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
 
     Expect.throws(() {
       var bytearray = new ByteData(interestingLength);
       print(bytearray.getUint8(0));
-    }, (e) => e is OutOfMemoryError);
+    }, exceptionCheck);
   }
 }
diff --git a/tools/VERSION b/tools/VERSION
index 931f10d..f6490ca 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 175
+PRERELEASE 176
 PRERELEASE_PATCH 0
\ No newline at end of file