Version 2.14.0-335.0.dev

Merge commit '325e7b277c1d52ef750216ca49378ae2f131f010' into 'dev'
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index a2d2707..3ee89a3 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.7.0
+
+- Support verison `2.x` of the `analyzer` package
+
 ## 0.6.0
 - Bug fixes to the protocol.
 
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 2b5441c..b5304b9 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -7,7 +7,7 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  analyzer: ^1.5.0
+  analyzer: ^2.0.0
   collection: ^1.15.0
   dart_style: ^2.0.0
   pub_semver: ^2.0.0
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 6c90fb2..0aa7a6e 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -2314,7 +2314,7 @@
 
   @override
   TypeInformation visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    return builder.createStaticGetTypeInformation(node, node.procedure);
+    return builder.createStaticGetTypeInformation(node, node.target);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 33640a7..8339c43 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -749,19 +749,14 @@
 
   @override
   void visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    ir.Member member = node.procedure;
-    if (member is ir.Procedure) {
-      registry.registerStaticTearOff(member, import);
-    } else {
-      throw new UnsupportedError("Unexpected member (${member.runtimeType}).");
-    }
+    registry.registerStaticTearOff(node.target, import);
   }
 
   @override
   void visitInstantiationConstant(ir.InstantiationConstant node) {
     registry.registerGenericInstantiation(
         node.tearOffConstant.function.computeFunctionType(
-            node.tearOffConstant.member.enclosingLibrary.nonNullable),
+            node.tearOffConstant.target.enclosingLibrary.nonNullable),
         node.types);
     visitConstant(node.tearOffConstant);
   }
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 0335a73..cbcfda9 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -213,15 +213,10 @@
 
   @override
   ConstantValue visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
-    ir.Member member = node.procedure;
-    if (member is ir.Procedure) {
-      FunctionEntity function = elementMap.getMethod(member);
-      DartType type = elementMap.getFunctionType(member.function);
-      return new FunctionConstantValue(function, type);
-    } else {
-      throw new UnsupportedError(
-          "Unexpected torn off member kind (${member.runtimeType}).");
-    }
+    ir.Procedure member = node.target;
+    FunctionEntity function = elementMap.getMethod(member);
+    DartType type = elementMap.getFunctionType(member.function);
+    return new FunctionConstantValue(function, type);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index e0c56a2..782e2fc 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -313,6 +313,10 @@
   void visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) {}
 
   @override
+  void visitRedirectingFactoryTearOffConstant(
+      ir.RedirectingFactoryTearOffConstant node) {}
+
+  @override
   void visitInstantiationConstant(ir.InstantiationConstant node) {
     node.tearOffConstant.accept(this);
   }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 765039b..ad0375f 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4491,8 +4491,8 @@
     } else if (closure is ir.ConstantExpression &&
         closure.constant is ir.StaticTearOffConstant) {
       ir.StaticTearOffConstant tearOff = closure.constant;
-      ir.Member member = tearOff.procedure;
-      if (member is ir.Procedure && handleTarget(member)) {
+      ir.Procedure member = tearOff.target;
+      if (handleTarget(member)) {
         return;
       }
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index c0e4c51..d6d428c 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -729,7 +729,8 @@
       : null;
 
   var debugSymbols = emitDebugSymbols
-      ? _emitSymbols(compiler, nameListener.identifierNames, component)
+      ? _emitSymbols(
+          compiler, moduleTree.name, nameListener.identifierNames, component)
       : null;
 
   return JSCode(text, builtMap, symbols: debugSymbols, metadata: debugMetadata);
@@ -741,7 +742,7 @@
 /// Uses information from the [compiler] used to compile the JS module combined
 /// with [identifierNames] that maps JavaScript identifier nodes to their actual
 /// names used when outputting the JavaScript.
-ModuleSymbols _emitSymbols(ProgramCompiler compiler,
+ModuleSymbols _emitSymbols(ProgramCompiler compiler, String moduleName,
     Map<js_ast.Identifier, String> identifierNames, Component component) {
   var classJsNames = <Class, String>{
     for (var e in compiler.classIdentifiers.entries)
@@ -753,7 +754,7 @@
   };
 
   return ModuleSymbolsCollector(
-          classJsNames, compiler.memberNames, variableJsNames)
+          moduleName, classJsNames, compiler.memberNames, variableJsNames)
       .collectSymbolInfo(component);
 }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index c11ced8..2c37a60 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5853,6 +5853,12 @@
   }
 
   @override
+  js_ast.Expression visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node) {
+    throw UnsupportedError('RedirectingFactory tear off');
+  }
+
+  @override
   js_ast.Expression visitTypedefTearOff(TypedefTearOff node) {
     throw UnsupportedError('Typedef instantiation');
   }
@@ -6241,13 +6247,13 @@
   js_ast.Expression visitConstant(Constant node) {
     if (node is StaticTearOffConstant) {
       // JS() or external JS consts should not be lazily loaded.
-      var isSdk = node.procedure.enclosingLibrary.importUri.scheme == 'dart';
+      var isSdk = node.target.enclosingLibrary.importUri.scheme == 'dart';
       if (_isInForeignJS) {
-        return _emitStaticTarget(node.procedure);
+        return _emitStaticTarget(node.target);
       }
-      if (node.procedure.isExternal && !isSdk) {
+      if (node.target.isExternal && !isSdk) {
         return runtimeCall(
-            'tearoffInterop(#)', [_emitStaticTarget(node.procedure)]);
+            'tearoffInterop(#)', [_emitStaticTarget(node.target)]);
       }
     }
     if (node is TypeLiteralConstant) {
@@ -6426,8 +6432,8 @@
 
   @override
   js_ast.Expression visitStaticTearOffConstant(StaticTearOffConstant node) {
-    _declareBeforeUse(node.procedure.enclosingClass);
-    return _emitStaticGet(node.procedure);
+    _declareBeforeUse(node.target.enclosingClass);
+    return _emitStaticGet(node.target);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 7ac69c9..23cc5bb 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -28,7 +28,7 @@
         Member,
         Node,
         Procedure,
-        RedirectingFactoryConstructor,
+        RedirectingFactory,
         TreeNode,
         TypeParameter,
         VariableDeclaration,
@@ -253,7 +253,7 @@
     if (node is Constructor) return node.fileEndOffset;
     if (node is Procedure) return node.fileEndOffset;
     if (node is Field) return node.fileEndOffset;
-    if (node is RedirectingFactoryConstructor) return node.fileEndOffset;
+    if (node is RedirectingFactory) return node.fileEndOffset;
     if (node is FunctionNode) return node.fileEndOffset;
     return noOffset;
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
index 253facf..2f16592 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
@@ -14,24 +14,23 @@
   /// The first scope added to the stack should always be the library scope. The
   /// last element in the list represents the current scope.
   final _scopes = <ScopeSymbol>[];
-
-  final _moduleSymbols = ModuleSymbols(
-      // TODO(nshahan) version
-      // TODO(nshahan) moduleName
-      libraries: <LibrarySymbol>[],
-      scripts: <Script>[],
-      classes: <ClassSymbol>[],
-      // TODO(nshahan) functionTypes
-      // TODO(nshahan) functions
-      // TODO(nshahan) scopes
-      variables: <VariableSymbol>[]);
-
+  final ModuleSymbols _moduleSymbols;
   final Map<Class, String> _classJsNames;
   final Map<Member, String> _memberJsNames;
   final Map<VariableDeclaration, String> _variableJsNames;
 
-  ModuleSymbolsCollector(
-      this._classJsNames, this._memberJsNames, this._variableJsNames);
+  ModuleSymbolsCollector(String moduleName, this._classJsNames,
+      this._memberJsNames, this._variableJsNames)
+      : _moduleSymbols = ModuleSymbols(
+            version: ModuleSymbols.current.version,
+            moduleName: moduleName,
+            libraries: <LibrarySymbol>[],
+            scripts: <Script>[],
+            classes: <ClassSymbol>[],
+            // TODO(nshahan) functionTypes
+            // TODO(nshahan) functions
+            // TODO(nshahan) scopes
+            variables: <VariableSymbol>[]);
 
   ModuleSymbols collectSymbolInfo(Component node) {
     node.accept(this);
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index d29d1ea..ee007f5 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -240,7 +240,7 @@
 
 /// Desugar API to determine whether [member] is a redirecting factory
 /// constructor.
-// TODO(sigmund): Delete this API once `member.isRedirectingFactoryConstructor`
+// TODO(sigmund): Delete this API once `member.isRedirectingFactory`
 // is implemented correctly for patch files (Issue #33495).
 bool isRedirectingFactory(ir.Procedure member) {
   if (member.kind == ir.ProcedureKind.Factory) {
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
index ddf666e..ae02cb6 100644
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -203,8 +203,8 @@
     origin._procedure.isExternal = _procedureInternal.isExternal;
     origin._procedure.function = _procedureInternal.function;
     origin._procedure.function.parent = origin._procedure;
-    origin._procedure.isRedirectingFactoryConstructor =
-        _procedureInternal.isRedirectingFactoryConstructor;
+    origin._procedure.isRedirectingFactory =
+        _procedureInternal.isRedirectingFactory;
     return 1;
   }
 }
@@ -264,7 +264,7 @@
     bodyInternal = new RedirectingFactoryBody(target, typeArguments);
     function.body = bodyInternal;
     bodyInternal?.parent = function;
-    _procedure.isRedirectingFactoryConstructor = true;
+    _procedure.isRedirectingFactory = true;
     if (isPatch) {
       // ignore: unnecessary_null_comparison
       if (function.typeParameters != null) {
@@ -299,7 +299,7 @@
     _procedureInternal.isExternal = isExternal;
     _procedureInternal.isConst = isConst;
     _procedureInternal.isStatic = isStatic;
-    _procedureInternal.isRedirectingFactoryConstructor = true;
+    _procedureInternal.isRedirectingFactory = true;
     if (redirectionTarget.typeArguments != null) {
       typeArguments = new List<DartType>.generate(
           redirectionTarget.typeArguments!.length,
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 1fa324b..8950e51 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -537,8 +537,7 @@
     origin.procedure.isExternal = _procedure.isExternal;
     origin.procedure.function = _procedure.function;
     origin.procedure.function.parent = origin.procedure;
-    origin.procedure.isRedirectingFactoryConstructor =
-        _procedure.isRedirectingFactoryConstructor;
+    origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
     return 1;
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 382ee2b..04bbb31 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -453,8 +453,7 @@
       transformTypeParameterList(node.typeParameters, node);
       transformConstructorList(node.constructors, node);
       transformProcedureList(node.procedures, node);
-      transformRedirectingFactoryConstructorList(
-          node.redirectingFactoryConstructors, node);
+      transformRedirectingFactoryList(node.redirectingFactories, node);
     });
     _staticTypeContext = oldStaticTypeContext;
     return node;
@@ -511,17 +510,15 @@
   }
 
   @override
-  RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, TreeNode? removalSentinel) {
+  RedirectingFactory visitRedirectingFactory(
+      RedirectingFactory node, TreeNode? removalSentinel) {
     // Currently unreachable as the compiler doesn't produce
     // RedirectingFactoryConstructor.
     StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
     _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
     constantEvaluator.withNewEnvironment(() {
       transformAnnotations(node.annotations, node);
-      transformTypeParameterList(node.typeParameters, node);
-      transformVariableDeclarationList(node.positionalParameters, node);
-      transformVariableDeclarationList(node.namedParameters, node);
+      node.function = transform(node.function)..parent = node;
     });
     _staticTypeContext = oldStaticTypeContext;
     return node;
@@ -3397,7 +3394,7 @@
               node.typeArguments.map((t) => env.substituteType(t)).toList()));
     }
     if (constant is StaticTearOffConstant) {
-      Member constantMember = constant.procedure;
+      Procedure constantMember = constant.target;
       if (constantMember is Procedure) {
         if (node.typeArguments.length ==
             constantMember.function.typeParameters.length) {
@@ -3422,9 +3419,6 @@
               'instantiation does not match the number of type arguments '
               'of the $constant.');
         }
-      } else if (constantMember is Constructor) {
-        // TODO(dmitryas): Add support for instantiated constructor tear-offs.
-        return defaultExpression(node);
       } else {
         // Probably unreachable.
         return createInvalidExpressionConstant(
@@ -3442,6 +3436,12 @@
 
   @override
   Constant visitConstructorTearOff(ConstructorTearOff node) {
+    // TODO(dmitryas): Add support for instantiated constructor tear-offs.
+    return defaultExpression(node);
+  }
+
+  @override
+  Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
     return defaultExpression(node);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 7fc34a9..0c85ec0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -217,12 +217,18 @@
   @override
   ExpressionInferenceResult visitConstructorTearOff(
       ConstructorTearOff node, DartType typeContext) {
-    DartType type = node.constructor.function
-        .computeFunctionType(inferrer.library.nonNullable);
+    DartType type =
+        node.target.function!.computeFunctionType(inferrer.library.nonNullable);
     return inferrer.instantiateTearOff(type, typeContext, node);
   }
 
   @override
+  ExpressionInferenceResult visitRedirectingFactoryTearOff(
+      RedirectingFactoryTearOff node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
   ExpressionInferenceResult visitTypedefTearOff(
       TypedefTearOff node, DartType typeContext) {
     ExpressionInferenceResult expressionResult = inferrer.inferExpression(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index ef5652b..c3a5e4e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -598,7 +598,7 @@
     assert(!builder.isExtension);
     // TODO(askesc): Make this check light-weight in the absence of patches.
     if (builder.cls.constructors.isNotEmpty) return;
-    if (builder.cls.redirectingFactoryConstructors.isNotEmpty) return;
+    if (builder.cls.redirectingFactories.isNotEmpty) return;
     for (Procedure proc in builder.cls.procedures) {
       if (proc.isFactory) return;
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index aeb1696..8a23b53 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -361,7 +361,7 @@
   }
 
   void visitStaticTearOffConstant(StaticTearOffConstant node) {
-    Procedure procedure = node.procedure;
+    Procedure procedure = node.target;
     Class? classNode = procedure.enclosingClass;
     if (classNode != null) {
       result.add(nameForEntity(
@@ -375,8 +375,21 @@
   }
 
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
-    Constructor constructor = node.constructor;
-    Class? classNode = constructor.enclosingClass;
+    Member constructor = node.target;
+    Class classNode = constructor.enclosingClass!;
+    result.add(nameForEntity(
+        classNode,
+        classNode.name,
+        classNode.enclosingLibrary.importUri,
+        classNode.enclosingLibrary.fileUri));
+    result.add(".");
+    result.add(constructor.name.text);
+  }
+
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    Member constructor = node.target;
+    Class classNode = constructor.enclosingClass!;
     result.add(nameForEntity(
         classNode,
         classNode.name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 363f618..4ac0b50 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -283,7 +283,7 @@
     // the shape, but aren't of the RedirectingFactoryBody type.
     bool hasBody = isRedirectingFactory(node) ||
         RedirectingFactoryBody.hasRedirectingFactoryBodyShape(node);
-    bool hasFlag = node.isRedirectingFactoryConstructor;
+    bool hasFlag = node.isRedirectingFactory;
     if (hasBody != hasFlag) {
       String hasBodyString = hasBody ? "has" : "doesn't have";
       String hasFlagString = hasFlag ? "has" : "doesn't have";
@@ -291,7 +291,7 @@
           node,
           "Procedure '${node.name}' ${hasBodyString} a body "
           "of a redirecting factory, but ${hasFlagString} the "
-          "'isRedirectingFactoryConstructor' bit set.");
+          "'isRedirectingFactory' bit set.");
     }
 
     super.visitProcedure(node);
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 0a88d80..d81529e 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -161,8 +161,8 @@
                 cls.addField(member);
               } else if (member is Constructor) {
                 cls.addConstructor(member);
-              } else if (member is RedirectingFactoryConstructor) {
-                cls.addRedirectingFactoryConstructor(member);
+              } else if (member is RedirectingFactory) {
+                cls.addRedirectingFactory(member);
               } else {
                 unhandled("${member.runtimeType}", "getMember",
                     member.fileOffset, member.fileUri);
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index fafad3a..59a5c83 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -415,7 +415,7 @@
 
   void visitInstantiationConstant(InstantiationConstant node) {
     sb.write('Instantiation(');
-    sb.write(getMemberName(node.tearOffConstant.member));
+    sb.write(getMemberName(node.tearOffConstant.target));
     sb.write('<');
     typeToText.visitList(node.types);
     sb.write('>)');
@@ -423,7 +423,7 @@
 
   void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
     sb.write('TypedefTearOff(');
-    sb.write(getMemberName(node.tearOffConstant.member));
+    sb.write(getMemberName(node.tearOffConstant.target));
     if (node.parameters.isNotEmpty) {
       sb.write('<');
       for (int i = 0; i < node.parameters.length; i++) {
@@ -451,13 +451,20 @@
 
   void visitStaticTearOffConstant(StaticTearOffConstant node) {
     sb.write('Function(');
-    sb.write(getMemberName(node.procedure));
+    sb.write(getMemberName(node.target));
     sb.write(')');
   }
 
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
     sb.write('Constructor(');
-    sb.write(getMemberName(node.constructor));
+    sb.write(getMemberName(node.target));
+    sb.write(')');
+  }
+
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    sb.write('RedirectingFactory(');
+    sb.write(getMemberName(node.target));
     sb.write(')');
   }
 
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index 7aa716d..f8078d1 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -67,7 +67,7 @@
   Expect.isTrue(
       member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
   Expect.isTrue(api.isRedirectingFactory(member));
-  Expect.isTrue(member.isRedirectingFactoryConstructor);
+  Expect.isTrue(member.isRedirectingFactory);
 }
 
 const aSource = '''
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
index d304ccb..922866f 100644
--- a/pkg/front_end/test/incremental_compiler_leak_test.dart
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -243,7 +243,7 @@
     "Field",
     "Library",
     "Procedure",
-    "RedirectingFactoryConstructor",
+    "RedirectingFactory",
     "Typedef",
   };
 
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 4dd9aa7..a2f3687 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 67;
+  UInt32 formatVersion = 68;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -328,7 +328,7 @@
   List<Field> fields;
   List<Constructor> constructors;
   List<Procedure> procedures;
-  List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
+  List<RedirectingFactory> redirectingFactories;
 
   // Class index. Offsets are used to get start (inclusive) and end (exclusive) byte positions for
   // a specific procedure. Note the "+1" to account for needing the end of the last entry.
@@ -424,7 +424,7 @@
   Byte kind; // Index into the ProcedureKind enum above.
   Byte stubKind; // Index into the ProcedureStubKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst,
-              isRedirectingFactoryConstructor, isExtensionMember,
+              isRedirectingFactory, isExtensionMember,
               isNonNullableByDefault);
   Name name;
   List<Expression> annotations;
@@ -432,7 +432,7 @@
   FunctionNode function;
 }
 
-type RedirectingFactoryConstructor extends Member {
+type RedirectingFactory extends Member {
   Byte tag = 108;
   CanonicalNameReference canonicalName;
   UriReference fileUri;
@@ -703,8 +703,13 @@
 type ConstructorTearOff extends Expression {
   Byte tag = 60;
   FileOffset fileOffset;
-  ConstructorReference constructor;
-  Option<List<DartType>> typeArguments;
+  MemberReference target;
+}
+
+type RedirectingFactoryTearOff extends Expression {
+  Byte tag = 84;
+  FileOffset fileOffset;
+  MemberReference target;
 }
 
 type TypedefTearOff extends Expression {
@@ -1219,6 +1224,11 @@
   CanonicalNameReference constructorReference;
 }
 
+type RedirectingFactoryTearOffConstant extends Constant {
+  Byte tag = 16;
+  CanonicalNameReference constructorReference;
+}
+
 abstract type Statement extends Node {}
 
 type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 69b540a..3f78529 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1190,19 +1190,18 @@
     _proceduresView = null;
   }
 
-  List<RedirectingFactoryConstructor> _redirectingFactoryConstructorsInternal;
-  DirtifyingList<RedirectingFactoryConstructor>?
-      _redirectingFactoryConstructorsView;
+  List<RedirectingFactory> _redirectingFactoriesInternal;
+  DirtifyingList<RedirectingFactory>? _redirectingFactoryConstructorsView;
 
   /// Redirecting factory constructors declared in the class.
   ///
   /// For mixin applications this should be empty.
-  List<RedirectingFactoryConstructor> get redirectingFactoryConstructors {
+  List<RedirectingFactory> get redirectingFactories {
     ensureLoaded();
     // If already dirty the caller just might as well add stuff directly too.
-    if (dirty) return _redirectingFactoryConstructorsInternal;
+    if (dirty) return _redirectingFactoriesInternal;
     return _redirectingFactoryConstructorsView ??=
-        new DirtifyingList(this, _redirectingFactoryConstructorsInternal);
+        new DirtifyingList(this, _redirectingFactoriesInternal);
   }
 
   /// Internal. Should *ONLY* be used from within kernel.
@@ -1210,8 +1209,8 @@
   /// Used for adding redirecting factory constructor when reading the dill
   /// file.
   void set redirectingFactoryConstructorsInternal(
-      List<RedirectingFactoryConstructor> redirectingFactoryConstructors) {
-    _redirectingFactoryConstructorsInternal = redirectingFactoryConstructors;
+      List<RedirectingFactory> redirectingFactoryConstructors) {
+    _redirectingFactoriesInternal = redirectingFactoryConstructors;
     _redirectingFactoryConstructorsView = null;
   }
 
@@ -1226,7 +1225,7 @@
       List<Constructor>? constructors,
       List<Procedure>? procedures,
       List<Field>? fields,
-      List<RedirectingFactoryConstructor>? redirectingFactoryConstructors,
+      List<RedirectingFactory>? redirectingFactoryConstructors,
       required this.fileUri,
       Reference? reference})
       // ignore: unnecessary_null_comparison
@@ -1238,14 +1237,14 @@
         this._fieldsInternal = fields ?? <Field>[],
         this._constructorsInternal = constructors ?? <Constructor>[],
         this._proceduresInternal = procedures ?? <Procedure>[],
-        this._redirectingFactoryConstructorsInternal =
-            redirectingFactoryConstructors ?? <RedirectingFactoryConstructor>[],
+        this._redirectingFactoriesInternal =
+            redirectingFactoryConstructors ?? <RedirectingFactory>[],
         super(reference) {
     setParents(this.typeParameters, this);
     setParents(this._constructorsInternal, this);
     setParents(this._proceduresInternal, this);
     setParents(this._fieldsInternal, this);
-    setParents(this._redirectingFactoryConstructorsInternal, this);
+    setParents(this._redirectingFactoriesInternal, this);
     this.isAbstract = isAbstract;
     this.isAnonymousMixin = isAnonymousMixin;
   }
@@ -1270,10 +1269,10 @@
       Constructor member = constructors[i];
       canonicalName.getChildFromConstructor(member).bindTo(member.reference);
     }
-    for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
-      RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+    for (int i = 0; i < redirectingFactories.length; ++i) {
+      RedirectingFactory member = redirectingFactories[i];
       canonicalName
-          .getChildFromRedirectingFactoryConstructor(member)
+          .getChildFromRedirectingFactory(member)
           .bindTo(member.reference);
     }
     dirty = false;
@@ -1300,8 +1299,8 @@
       Constructor member = constructors[i];
       member._relinkNode();
     }
-    for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
-      RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+    for (int i = 0; i < redirectingFactories.length; ++i) {
+      RedirectingFactory member = redirectingFactories[i];
       member._relinkNode();
     }
     dirty = false;
@@ -1345,7 +1344,7 @@
         fields,
         constructors,
         procedures,
-        redirectingFactoryConstructors
+        redirectingFactories
       ].expand((x) => x);
 
   /// The immediately extended, mixed-in, and implemented types.
@@ -1389,11 +1388,10 @@
   }
 
   /// Adds a field to this class.
-  void addRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor redirectingFactoryConstructor) {
+  void addRedirectingFactory(RedirectingFactory redirectingFactory) {
     dirty = true;
-    redirectingFactoryConstructor.parent = this;
-    _redirectingFactoryConstructorsInternal.add(redirectingFactoryConstructor);
+    redirectingFactory.parent = this;
+    _redirectingFactoriesInternal.add(redirectingFactory);
   }
 
   @override
@@ -1446,7 +1444,7 @@
     visitList(constructors, v);
     visitList(procedures, v);
     visitList(fields, v);
-    visitList(redirectingFactoryConstructors, v);
+    visitList(redirectingFactories, v);
   }
 
   @override
@@ -1463,7 +1461,7 @@
     v.transformList(constructors, this);
     v.transformList(procedures, this);
     v.transformList(fields, this);
-    v.transformList(redirectingFactoryConstructors, this);
+    v.transformList(redirectingFactories, this);
   }
 
   @override
@@ -1490,8 +1488,7 @@
     v.transformConstructorList(constructors, this);
     v.transformProcedureList(procedures, this);
     v.transformFieldList(fields, this);
-    v.transformRedirectingFactoryConstructorList(
-        redirectingFactoryConstructors, this);
+    v.transformRedirectingFactoryList(redirectingFactories, this);
   }
 
   @override
@@ -2237,64 +2234,45 @@
 /// be removed from the class.  However, it is needed during the linking phase,
 /// because other modules can refer to that constructor.
 ///
-/// [RedirectingFactoryConstructor]s contain the necessary information for
+/// [RedirectingFactory]s contain the necessary information for
 /// linking and are treated as non-runnable members of classes that merely serve
 /// as containers for that information.
 ///
 /// Redirecting factory constructors can be unnamed.  In this case, the name is
 /// an empty string (in a [Name]).
-class RedirectingFactoryConstructor extends Member {
+class RedirectingFactory extends Member {
   int flags = 0;
 
-  /// [RedirectingFactoryConstructor]s may redirect to constructors or factories
+  /// [RedirectingFactory]s may redirect to constructors or factories
   /// of instantiated generic types, that is, generic types with supplied type
   /// arguments.  The supplied type arguments are stored in this field.
   final List<DartType> typeArguments;
 
   /// Reference to the constructor or the factory that this
-  /// [RedirectingFactoryConstructor] redirects to.
+  /// [RedirectingFactory] redirects to.
   // TODO(johnniwinther): Make this non-nullable.
   Reference? targetReference;
 
-  /// [typeParameters] are duplicates of the type parameters of the enclosing
-  /// class.  Because [RedirectingFactoryConstructor]s aren't instance members,
-  /// references to the type parameters of the enclosing class in the
-  /// redirection target description are encoded with references to the elements
-  /// of [typeParameters].
-  List<TypeParameter> typeParameters;
+  /// [FunctionNode] that holds the type parameters, copied from the enclosing
+  /// class, and the parameters defined on the redirecting factory.
+  ///
+  /// The `FunctionNode.body` is `null` or a synthesized [ConstructorInvocation]
+  /// of the [targetReference] constructor using the [typeArguments] and
+  /// [VariableGet] of the parameters.
+  FunctionNode function;
 
-  /// Positional parameters of [RedirectingFactoryConstructor]s should be
-  /// compatible with that of the target constructor.
-  List<VariableDeclaration> positionalParameters;
-  int requiredParameterCount;
-
-  /// Named parameters of [RedirectingFactoryConstructor]s should be compatible
-  /// with that of the target constructor.
-  List<VariableDeclaration> namedParameters;
-
-  RedirectingFactoryConstructor(this.targetReference,
+  RedirectingFactory(this.targetReference,
       {required Name name,
       bool isConst: false,
       bool isExternal: false,
       int transformerFlags: 0,
       List<DartType>? typeArguments,
-      List<TypeParameter>? typeParameters,
-      List<VariableDeclaration>? positionalParameters,
-      List<VariableDeclaration>? namedParameters,
-      int? requiredParameterCount,
+      required this.function,
       required Uri fileUri,
       Reference? reference})
       : this.typeArguments = typeArguments ?? <DartType>[],
-        this.typeParameters = typeParameters ?? <TypeParameter>[],
-        this.positionalParameters =
-            positionalParameters ?? <VariableDeclaration>[],
-        this.namedParameters = namedParameters ?? <VariableDeclaration>[],
-        this.requiredParameterCount =
-            requiredParameterCount ?? positionalParameters?.length ?? 0,
         super(name, fileUri, reference) {
-    setParents(this.typeParameters, this);
-    setParents(this.positionalParameters, this);
-    setParents(this.namedParameters, this);
+    function.parent = this;
     this.isConst = isConst;
     this.isExternal = isExternal;
     this.transformerFlags = transformerFlags;
@@ -2355,15 +2333,15 @@
   }
 
   @override
-  R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactoryConstructor(this);
+  R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactory(this);
 
   @override
   R accept1<R, A>(MemberVisitor1<R, A> v, A arg) =>
-      v.visitRedirectingFactoryConstructor(this, arg);
+      v.visitRedirectingFactory(this, arg);
 
   @override
   R acceptReference<R>(MemberReferenceVisitor<R> v) =>
-      v.visitRedirectingFactoryConstructorReference(this);
+      v.visitRedirectingFactoryReference(this);
 
   @override
   void visitChildren(Visitor v) {
@@ -2371,18 +2349,21 @@
     target?.acceptReference(v);
     visitList(typeArguments, v);
     name.accept(v);
+    function.accept(v);
   }
 
   @override
   void transformChildren(Transformer v) {
     v.transformList(annotations, this);
     v.transformDartTypeList(typeArguments);
+    function = v.transform(function)..parent = this;
   }
 
   @override
   void transformOrRemoveChildren(RemovingTransformer v) {
     v.transformExpressionList(annotations, this);
     v.transformDartTypeList(typeArguments);
+    function = v.transform(function)..parent = this;
   }
 
   @override
@@ -2705,7 +2686,7 @@
   static const int FlagExternal = 1 << 2;
   static const int FlagConst = 1 << 3; // Only for external const factories.
   // TODO(29841): Remove this flag after the issue is resolved.
-  static const int FlagRedirectingFactoryConstructor = 1 << 4;
+  static const int FlagRedirectingFactory = 1 << 4;
   static const int FlagExtensionMember = 1 << 5;
   static const int FlagNonNullableByDefault = 1 << 6;
   static const int FlagSynthetic = 1 << 7;
@@ -2750,8 +2731,8 @@
 
   // Indicates if this [Procedure] represents a redirecting factory constructor
   // and doesn't have a runnable body.
-  bool get isRedirectingFactoryConstructor {
-    return flags & FlagRedirectingFactoryConstructor != 0;
+  bool get isRedirectingFactory {
+    return flags & FlagRedirectingFactory != 0;
   }
 
   /// If set, this flag indicates that this function was not present in the
@@ -2783,10 +2764,10 @@
     flags = value ? (flags | FlagConst) : (flags & ~FlagConst);
   }
 
-  void set isRedirectingFactoryConstructor(bool value) {
+  void set isRedirectingFactory(bool value) {
     flags = value
-        ? (flags | FlagRedirectingFactoryConstructor)
-        : (flags & ~FlagRedirectingFactoryConstructor);
+        ? (flags | FlagRedirectingFactory)
+        : (flags & ~FlagRedirectingFactory);
   }
 
   void set isExtensionMember(bool value) {
@@ -8611,23 +8592,28 @@
 /// Tearing off a constructor of a class.
 class ConstructorTearOff extends Expression {
   /// The reference to the constructor being torn off.
-  Reference constructorReference;
+  Reference targetReference;
 
-  ConstructorTearOff(Constructor constructor)
-      : this.byReference(getNonNullableMemberReferenceGetter(constructor));
+  ConstructorTearOff(Member target)
+      : assert(target is Constructor ||
+            (target is Procedure && target.kind == ProcedureKind.Factory)),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
 
-  ConstructorTearOff.byReference(this.constructorReference);
+  ConstructorTearOff.byReference(this.targetReference);
 
-  Constructor get constructor => constructorReference.asConstructor;
+  Member get target => targetReference.asMember;
 
-  void set constructor(Constructor constructor) {
-    constructorReference = getNonNullableMemberReferenceGetter(constructor);
+  FunctionNode get function => target.function!;
+
+  void set target(Member member) {
+    assert(member is Constructor ||
+        (member is Procedure && member.kind == ProcedureKind.Factory));
+    targetReference = getNonNullableMemberReferenceGetter(member);
   }
 
   @override
   DartType getStaticTypeInternal(StaticTypeContext context) {
-    return constructorReference.asConstructor.function
-        .computeFunctionType(Nullability.nonNullable);
+    return target.function!.computeFunctionType(Nullability.nonNullable);
   }
 
   @override
@@ -8639,7 +8625,7 @@
 
   @override
   void visitChildren(Visitor v) {
-    constructor.acceptReference(v);
+    target.acceptReference(v);
   }
 
   @override
@@ -8655,7 +8641,60 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(constructorReference);
+    printer.writeMemberName(targetReference);
+  }
+}
+
+/// Tearing off a redirecting factory constructor of a class.
+class RedirectingFactoryTearOff extends Expression {
+  /// The reference to the redirecting factory constructor being torn off.
+  Reference targetReference;
+
+  RedirectingFactoryTearOff(Procedure target)
+      : assert(target.isRedirectingFactory),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+  RedirectingFactoryTearOff.byReference(this.targetReference);
+
+  Procedure get target => targetReference.asProcedure;
+
+  void set target(Procedure target) {
+    targetReference = getNonNullableMemberReferenceGetter(target);
+  }
+
+  FunctionNode get function => target.function;
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) {
+    return target.function.computeFunctionType(Nullability.nonNullable);
+  }
+
+  @override
+  R accept<R>(ExpressionVisitor<R> v) => v.visitRedirectingFactoryTearOff(this);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitRedirectingFactoryTearOff(this, arg);
+
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {}
+
+  @override
+  void transformOrRemoveChildren(RemovingTransformer v) {}
+
+  @override
+  String toString() {
+    return "RedirectingFactoryTearOff(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeMemberName(targetReference);
   }
 }
 
@@ -12899,32 +12938,30 @@
 }
 
 abstract class TearOffConstant implements Constant {
-  Reference get memberReference;
-  Member get member;
+  Reference get targetReference;
+  Member get target;
   FunctionNode get function;
 }
 
 class StaticTearOffConstant extends Constant implements TearOffConstant {
   @override
-  final Reference memberReference;
+  final Reference targetReference;
 
   StaticTearOffConstant(Procedure procedure)
-      : memberReference = procedure.reference {
+      : targetReference = procedure.reference {
     assert(procedure.isStatic);
   }
 
-  StaticTearOffConstant.byReference(this.memberReference);
+  StaticTearOffConstant.byReference(this.targetReference);
 
   @override
-  Member get member => memberReference.asMember;
+  Procedure get target => targetReference.asProcedure;
 
   @override
-  FunctionNode get function => procedure.function;
-
-  Procedure get procedure => memberReference.asProcedure;
+  FunctionNode get function => target.function;
 
   visitChildren(Visitor v) {
-    memberReference.asProcedure.acceptReference(v);
+    target.acceptReference(v);
   }
 
   R accept<R>(ConstantVisitor<R> v) => v.visitStaticTearOffConstant(this);
@@ -12933,66 +12970,121 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(memberReference);
+    printer.writeMemberName(targetReference);
   }
 
   @override
   String toString() => 'StaticTearOffConstant(${toStringInternal()})';
 
-  int get hashCode => memberReference.hashCode;
+  int get hashCode => targetReference.hashCode;
 
   bool operator ==(Object other) {
     return other is StaticTearOffConstant &&
-        other.memberReference == memberReference;
+        other.targetReference == targetReference;
   }
 
   FunctionType getType(StaticTypeContext context) {
-    return procedure.function.computeFunctionType(context.nonNullable);
+    return target.function.computeFunctionType(context.nonNullable);
   }
 }
 
 class ConstructorTearOffConstant extends Constant implements TearOffConstant {
   @override
-  final Reference memberReference;
+  final Reference targetReference;
 
-  ConstructorTearOffConstant(Constructor constructor)
-      : memberReference = constructor.reference;
+  ConstructorTearOffConstant(Member target)
+      : assert(target is Constructor ||
+            (target is Procedure && target.kind == ProcedureKind.Factory)),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
 
-  ConstructorTearOffConstant.byReference(this.memberReference);
+  ConstructorTearOffConstant.byReference(this.targetReference);
 
   @override
-  Member get member => memberReference.asMember;
+  Member get target => targetReference.asMember;
 
   @override
-  FunctionNode get function => constructor.function;
+  FunctionNode get function => target.function!;
 
-  Constructor get constructor => memberReference.asConstructor;
-
-  visitChildren(Visitor v) {
-    memberReference.asProcedure.acceptReference(v);
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
   }
 
+  @override
   R accept<R>(ConstantVisitor<R> v) => v.visitConstructorTearOffConstant(this);
+
+  @override
   R acceptReference<R>(Visitor<R> v) =>
       v.visitConstructorTearOffConstantReference(this);
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeMemberName(memberReference);
+    printer.writeMemberName(targetReference);
   }
 
   @override
   String toString() => 'ConstructorTearOffConstant(${toStringInternal()})';
 
-  int get hashCode => memberReference.hashCode;
+  int get hashCode => targetReference.hashCode;
 
   bool operator ==(Object other) {
     return other is StaticTearOffConstant &&
-        other.memberReference == memberReference;
+        other.targetReference == targetReference;
   }
 
   FunctionType getType(StaticTypeContext context) {
-    return constructor.function.computeFunctionType(context.nonNullable);
+    return function.computeFunctionType(context.nonNullable);
+  }
+}
+
+class RedirectingFactoryTearOffConstant extends Constant
+    implements TearOffConstant {
+  @override
+  final Reference targetReference;
+
+  RedirectingFactoryTearOffConstant(Procedure target)
+      : assert(target.isRedirectingFactory),
+        this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+  RedirectingFactoryTearOffConstant.byReference(this.targetReference);
+
+  @override
+  Procedure get target => targetReference.asProcedure;
+
+  @override
+  FunctionNode get function => target.function;
+
+  @override
+  void visitChildren(Visitor v) {
+    target.acceptReference(v);
+  }
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) =>
+      v.visitRedirectingFactoryTearOffConstant(this);
+
+  @override
+  R acceptReference<R>(Visitor<R> v) =>
+      v.visitRedirectingFactoryTearOffConstantReference(this);
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeMemberName(targetReference);
+  }
+
+  @override
+  String toString() =>
+      'RedirectingFactoryTearOffConstant(${toStringInternal()})';
+
+  int get hashCode => targetReference.hashCode;
+
+  bool operator ==(Object other) {
+    return other is StaticTearOffConstant &&
+        other.targetReference == targetReference;
+  }
+
+  FunctionType getType(StaticTypeContext context) {
+    return function.computeFunctionType(context.nonNullable);
   }
 }
 
@@ -14039,12 +14131,11 @@
 final List<Constructor> emptyListOfConstructor =
     List.filled(0, dummyConstructor, growable: false);
 
-/// Almost const <RedirectingFactoryConstructor>[], but not const in an attempt
-/// to avoid polymorphism. See
+/// Almost const <RedirectingFactory>[], but not const in an attempt to avoid
+/// polymorphism. See
 /// https://dart-review.googlesource.com/c/sdk/+/185828.
-final List<RedirectingFactoryConstructor>
-    emptyListOfRedirectingFactoryConstructor =
-    List.filled(0, dummyRedirectingFactoryConstructor, growable: false);
+final List<RedirectingFactory> emptyListOfRedirectingFactory =
+    List.filled(0, dummyRedirectingFactory, growable: false);
 
 /// Almost const <Initializer>[], but not const in an attempt to avoid
 /// polymorphism. See https://dart-review.googlesource.com/c/sdk/+/185828.
@@ -14172,13 +14263,13 @@
 /// constructor.
 final Field dummyField = new Field.mutable(dummyName, fileUri: dummyUri);
 
-/// Non-nullable [RedirectingFactoryConstructor] dummy value.
+/// Non-nullable [RedirectingFactory] dummy value.
 ///
 /// This is used as the removal sentinel in [RemovingTransformer] and can be
 /// used for instance as a dummy initial value for the `List.filled`
 /// constructor.
-final RedirectingFactoryConstructor dummyRedirectingFactoryConstructor =
-    new RedirectingFactoryConstructor(null, name: dummyName, fileUri: dummyUri);
+final RedirectingFactory dummyRedirectingFactory = new RedirectingFactory(null,
+    name: dummyName, fileUri: dummyUri, function: dummyFunctionNode);
 
 /// Non-nullable [Typedef] dummy value.
 ///
@@ -14309,7 +14400,7 @@
   dummyMember,
   dummyProcedure,
   dummyField,
-  dummyRedirectingFactoryConstructor,
+  dummyRedirectingFactory,
   dummyTypedef,
   dummyInitializer,
   dummyFunctionNode,
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index a257708..7f610ca 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1478,7 +1478,7 @@
     node.fieldsInternal = _readFieldList(node);
     _readConstructorList(node);
     node.proceduresInternal = _readProcedureList(node, procedureOffsets);
-    _readRedirectingFactoryConstructorList(node);
+    _readRedirectingFactoryList(node);
   }
 
   void _readConstructorList(Class node) {
@@ -1494,17 +1494,17 @@
     }
   }
 
-  void _readRedirectingFactoryConstructorList(Class node) {
+  void _readRedirectingFactoryList(Class node) {
     int length = readUInt30();
     if (!useGrowableLists && length == 0) {
       // When lists don't have to be growable anyway, we might as well use a
       // constant one for the empty list.
       node.redirectingFactoryConstructorsInternal =
-          emptyListOfRedirectingFactoryConstructor;
+          emptyListOfRedirectingFactory;
     } else {
       node.redirectingFactoryConstructorsInternal =
-          new List<RedirectingFactoryConstructor>.generate(length,
-              (int index) => readRedirectingFactoryConstructor()..parent = node,
+          new List<RedirectingFactory>.generate(
+              length, (int index) => readRedirectingFactory()..parent = node,
               growable: useGrowableLists);
     }
   }
@@ -1690,13 +1690,12 @@
     return node;
   }
 
-  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+  RedirectingFactory readRedirectingFactory() {
     int tag = readByte();
-    assert(tag == Tag.RedirectingFactoryConstructor);
+    assert(tag == Tag.RedirectingFactory);
     CanonicalName canonicalName = readNonNullCanonicalNameReference();
     Reference reference = canonicalName.reference;
-    RedirectingFactoryConstructor? node =
-        reference.node as RedirectingFactoryConstructor?;
+    RedirectingFactory? node = reference.node as RedirectingFactory?;
     if (alwaysCreateNewNamedNodes) {
       node = null;
     }
@@ -1705,39 +1704,34 @@
     int fileEndOffset = readOffset();
     int flags = readByte();
     Name name = readName();
-    if (node == null) {
-      node = new RedirectingFactoryConstructor(null,
-          reference: reference, name: name, fileUri: fileUri);
-    }
-    List<Expression> annotations = readAnnotationList(node);
     assert(() {
       debugPath.add(name.text);
       return true;
     }());
+    List<Expression> annotations = readAnnotationList();
     Reference targetReference = readNonNullMemberReference();
     List<DartType> typeArguments = readDartTypeList();
-    int typeParameterStackHeight = typeParameterStack.length;
-    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
-    readUInt30(); // Total parameter count.
-    int requiredParameterCount = readUInt30();
-    int variableStackHeight = variableStack.length;
-    List<VariableDeclaration> positional = readAndPushVariableDeclarationList();
-    List<VariableDeclaration> named = readAndPushVariableDeclarationList();
-    variableStack.length = variableStackHeight;
-    typeParameterStack.length = typeParameterStackHeight;
-    debugPath.removeLast();
+    FunctionNode function = readFunctionNode(outerEndOffset: fileEndOffset);
+    if (node == null) {
+      node = new RedirectingFactory(targetReference,
+          reference: reference,
+          name: name,
+          fileUri: fileUri,
+          function: function,
+          typeArguments: typeArguments);
+    } else {
+      node.name = name;
+      node.fileUri = fileUri;
+      node.targetReference = targetReference;
+      node.typeArguments.addAll(typeArguments);
+      node.function = function..parent = node;
+    }
     node.fileOffset = fileOffset;
     node.fileEndOffset = fileEndOffset;
     node.flags = flags;
-    node.name = name;
-    node.fileUri = fileUri;
     node.annotations = annotations;
-    node.targetReference = targetReference;
-    node.typeArguments.addAll(typeArguments);
-    node.typeParameters = typeParameters;
-    node.requiredParameterCount = requiredParameterCount;
-    node.positionalParameters = positional;
-    node.namedParameters = named;
+    setParents(annotations, node);
+    debugPath.removeLast();
     return node;
   }
 
@@ -3372,10 +3366,9 @@
   }
 
   @override
-  RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+  RedirectingFactory readRedirectingFactory() {
     final int nodeOffset = _byteOffset;
-    final RedirectingFactoryConstructor result =
-        super.readRedirectingFactoryConstructor();
+    final RedirectingFactory result = super.readRedirectingFactory();
     return _associateMetadata(result, nodeOffset);
   }
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 9018db9..d0d0343 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -264,11 +264,15 @@
     } else if (constant is StaticTearOffConstant) {
       writeByte(ConstantTag.StaticTearOffConstant);
       writeNonNullCanonicalNameReference(
-          constant.procedure.reference.canonicalName!);
+          constant.targetReference.canonicalName!);
     } else if (constant is ConstructorTearOffConstant) {
       writeByte(ConstantTag.ConstructorTearOffConstant);
       writeNonNullCanonicalNameReference(
-          constant.constructor.reference.canonicalName!);
+          constant.targetReference.canonicalName!);
+    } else if (constant is RedirectingFactoryTearOffConstant) {
+      writeByte(ConstantTag.RedirectingFactoryTearOffConstant);
+      writeNonNullCanonicalNameReference(
+          constant.targetReference.canonicalName!);
     } else if (constant is TypeLiteralConstant) {
       writeByte(ConstantTag.TypeLiteralConstant);
       writeDartType(constant.type);
@@ -373,13 +377,12 @@
     }
   }
 
-  void writeRedirectingFactoryConstructorNodeList(
-      List<RedirectingFactoryConstructor> nodes) {
+  void writeRedirectingFactoryNodeList(List<RedirectingFactory> nodes) {
     final int len = nodes.length;
     writeUInt30(len);
     for (int i = 0; i < len; i++) {
-      final RedirectingFactoryConstructor node = nodes[i];
-      writeRedirectingFactoryConstructorNode(node);
+      final RedirectingFactory node = nodes[i];
+      writeRedirectingFactoryNode(node);
     }
   }
 
@@ -473,8 +476,7 @@
     node.accept(this);
   }
 
-  void writeRedirectingFactoryConstructorNode(
-      RedirectingFactoryConstructor node) {
+  void writeRedirectingFactoryNode(RedirectingFactory node) {
     if (_metadataSubsections != null) {
       _writeNodeMetadata(node);
     }
@@ -1205,8 +1207,7 @@
     procedureOffsets = <int>[];
     writeProcedureNodeList(node.procedures);
     procedureOffsets.add(getBufferOffset());
-    writeRedirectingFactoryConstructorNodeList(
-        node.redirectingFactoryConstructors);
+    writeRedirectingFactoryNodeList(node.redirectingFactories);
     leaveScope(typeParameters: node.typeParameters);
 
     assert(procedureOffsets.length > 0);
@@ -1366,35 +1367,21 @@
   }
 
   @override
-  void visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  void visitRedirectingFactory(RedirectingFactory node) {
     if (node.reference.canonicalName == null) {
       throw new ArgumentError('Missing canonical name for $node');
     }
-    writeByte(Tag.RedirectingFactoryConstructor);
-    enterScope(
-        typeParameters: node.typeParameters,
-        memberScope: true,
-        variableScope: true);
+    writeByte(Tag.RedirectingFactory);
     writeNonNullCanonicalNameReference(getCanonicalNameOfMemberGetter(node));
     writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
     writeByte(node.flags);
     writeName(node.name);
-
     writeAnnotationList(node.annotations);
     writeNonNullReference(node.targetReference!);
     writeNodeList(node.typeArguments);
-    writeNodeList(node.typeParameters);
-    writeUInt30(node.positionalParameters.length + node.namedParameters.length);
-    writeUInt30(node.requiredParameterCount);
-    writeVariableDeclarationList(node.positionalParameters);
-    writeVariableDeclarationList(node.namedParameters);
-
-    leaveScope(
-        typeParameters: node.typeParameters,
-        memberScope: true,
-        variableScope: true);
+    writeFunctionNode(node.function);
   }
 
   @override
@@ -1609,7 +1596,14 @@
   void visitConstructorTearOff(ConstructorTearOff node) {
     writeByte(Tag.ConstructorTearOff);
     writeOffset(node.fileOffset);
-    writeNonNullReference(node.constructorReference);
+    writeNonNullReference(node.targetReference);
+  }
+
+  @override
+  void visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    writeByte(Tag.RedirectingFactoryTearOff);
+    writeOffset(node.fileOffset);
+    writeNonNullReference(node.targetReference);
   }
 
   @override
@@ -2687,10 +2681,9 @@
   }
 
   @override
-  void visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  void visitRedirectingFactoryReference(RedirectingFactory node) {
     throw new UnsupportedError(
-        'serialization of RedirectingFactoryConstructor references');
+        'serialization of RedirectingFactory references');
   }
 
   @override
@@ -2740,6 +2733,13 @@
   }
 
   @override
+  void visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node) {
+    throw new UnsupportedError(
+        'serialization of RedirectingFactoryTearOffConstants ');
+  }
+
+  @override
   void visitStaticTearOffConstantReference(StaticTearOffConstant node) {
     throw new UnsupportedError(
         'serialization of StaticTearOffConstant references');
@@ -2753,6 +2753,13 @@
   }
 
   @override
+  void visitRedirectingFactoryTearOffConstantReference(
+      RedirectingFactoryTearOffConstant node) {
+    throw new UnsupportedError(
+        'serialization of RedirectingFactoryTearOffConstant references');
+  }
+
+  @override
   void visitTypeLiteralConstant(TypeLiteralConstant node) {
     throw new UnsupportedError('serialization of TypeLiteralConstants');
   }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index e5291c5..138be00 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -17,7 +17,7 @@
   static const int Field = 4;
   static const int Constructor = 5;
   static const int Procedure = 6;
-  static const int RedirectingFactoryConstructor = 108;
+  static const int RedirectingFactory = 108;
 
   // Initializers
   static const int InvalidInitializer = 7;
@@ -78,6 +78,7 @@
   static const int ConstMapLiteral = 59;
   static const int ConstructorTearOff = 60;
   static const int TypedefTearOff = 83;
+  static const int RedirectingFactoryTearOff = 84;
 
   static const int SetLiteral = 109;
   static const int ConstSetLiteral = 110;
@@ -125,6 +126,7 @@
   static const int AssertBlock = 81;
   // 82 is occupied by [BlockExpression] (expression).
   // 83 is occupied by [TypedefTearOff] (expression).
+  // 84 is occupied by [RedirectingFactoryTearOff] (expression).
 
   // Types
   static const int TypedefType = 87;
@@ -141,7 +143,7 @@
 
   static const int ConstantExpression = 106;
 
-  /// 108 is occupied by [RedirectingFactoryConstructor] (member).
+  /// 108 is occupied by [RedirectingFactory] (member).
   /// 109 is occupied by [SetLiteral] (expression).
   /// 110 is occupied by [ConstSetLiteral] (expression).
   /// 111 is occupied by [ListConcatenation] (expression).
@@ -177,7 +179,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 67;
+  static const int BinaryFormatVersion = 68;
 }
 
 abstract class ConstantTag {
@@ -198,6 +200,7 @@
   // 13 is occupied by [SetConstant]
   static const int TypedefTearOffConstant = 14;
   static const int ConstructorTearOffConstant = 15;
+  static const int RedirectingFactoryTearOffConstant = 16;
 }
 
 const int sdkHashLength = 10; // Bytes, a Git "short hash".
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 21eb6b3..666a24f 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -149,8 +149,8 @@
         .getChildFromQualifiedName(constructor.name);
   }
 
-  CanonicalName getChildFromRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor redirectingFactoryConstructor) {
+  CanonicalName getChildFromRedirectingFactory(
+      RedirectingFactory redirectingFactoryConstructor) {
     return getChild('@factories')
         .getChildFromQualifiedName(redirectingFactoryConstructor.name);
   }
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 86e78d6..a5bde19 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -81,8 +81,7 @@
     throw 'Cloning of fields is not implemented here';
   }
 
-  TreeNode visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node) {
+  TreeNode visitRedirectingFactory(RedirectingFactory node) {
     throw 'Cloning of redirecting factory constructors is not implemented here';
   }
 
@@ -738,7 +737,12 @@
 
   @override
   TreeNode visitConstructorTearOff(ConstructorTearOff node) {
-    return new ConstructorTearOff.byReference(node.constructorReference);
+    return new ConstructorTearOff.byReference(node.targetReference);
+  }
+
+  @override
+  TreeNode visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    return new RedirectingFactoryTearOff.byReference(node.targetReference);
   }
 
   @override
@@ -856,24 +860,18 @@
     return result;
   }
 
-  RedirectingFactoryConstructor cloneRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, Reference? reference) {
+  RedirectingFactory cloneRedirectingFactory(
+      RedirectingFactory node, Reference? reference) {
     final Uri? activeFileUriSaved = _activeFileUri;
     _activeFileUri = node.fileUri;
 
-    prepareTypeParameters(node.typeParameters);
-    RedirectingFactoryConstructor result = new RedirectingFactoryConstructor(
-        node.targetReference,
+    RedirectingFactory result = new RedirectingFactory(node.targetReference,
         name: node.name,
         isConst: node.isConst,
         isExternal: node.isExternal,
         transformerFlags: node.transformerFlags,
         typeArguments: node.typeArguments.map(visitType).toList(),
-        typeParameters: node.typeParameters.map(super.clone).toList(),
-        positionalParameters:
-            node.positionalParameters.map(super.clone).toList(),
-        namedParameters: node.namedParameters.map(super.clone).toList(),
-        requiredParameterCount: node.requiredParameterCount,
+        function: super.clone(node.function),
         fileUri: node.fileUri,
         reference: reference)
       ..annotations = cloneAnnotations && !node.annotations.isEmpty
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 53fbe25..7690d8c 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1243,20 +1243,13 @@
         name: node.name, initializers: node.initializers);
   }
 
-  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  visitRedirectingFactory(RedirectingFactory node) {
     writeAnnotationList(node.annotations);
     writeIndentation();
     writeModifier(node.isExternal, 'external');
     writeModifier(node.isConst, 'const');
     writeWord('redirecting_factory');
-
-    // ignore: unnecessary_null_comparison
-    if (node.name != null) {
-      writeName(node.name);
-    }
-    writeTypeParameterList(node.typeParameters);
-    writeParameterList(node.positionalParameters, node.namedParameters,
-        node.requiredParameterCount);
+    writeFunction(node.function, name: node.name);
     writeSpaced('=');
     writeMemberReferenceFromReference(node.targetReference!);
     if (node.typeArguments.isNotEmpty) {
@@ -1327,7 +1320,7 @@
     node.fields.forEach(writeNode);
     node.constructors.forEach(writeNode);
     node.procedures.forEach(writeNode);
-    node.redirectingFactoryConstructors.forEach(writeNode);
+    node.redirectingFactories.forEach(writeNode);
     --indentation;
     writeIndentation();
     endLine('}');
@@ -2052,7 +2045,7 @@
   }
 
   visitConstructorTearOff(ConstructorTearOff node) {
-    writeMemberReferenceFromReference(node.constructorReference);
+    writeMemberReferenceFromReference(node.targetReference);
   }
 
   visitTypedefTearOff(TypedefTearOff node) {
@@ -2683,7 +2676,7 @@
     writeSpaced('=');
     writeWord('partial-instantiation');
     writeSpace();
-    writeMemberReferenceFromReference(node.tearOffConstant.memberReference);
+    writeMemberReferenceFromReference(node.tearOffConstant.targetReference);
     writeSpace();
     writeSymbol('<');
     writeList(node.types, writeType);
@@ -2704,7 +2697,7 @@
     writeSpaced('=');
     writeWord('tearoff');
     writeSpace();
-    writeMemberReferenceFromReference(node.memberReference);
+    writeMemberReferenceFromReference(node.targetReference);
     endLine();
   }
 
@@ -2924,6 +2917,9 @@
   int visitConstructorTearOff(ConstructorTearOff node) => PRIMARY;
 
   @override
+  int visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) => PRIMARY;
+
+  @override
   int visitTypedefTearOff(TypedefTearOff node) => EXPRESSION;
 
   @override
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 0c4f26e..7b2c1ef 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -1836,8 +1836,7 @@
   Procedure.FlagAbstract: "abstract",
   Procedure.FlagExternal: "external",
   Procedure.FlagConst: "const",
-  Procedure.FlagRedirectingFactoryConstructor:
-      "redirecting-factory-constructor",
+  Procedure.FlagRedirectingFactory: "redirecting-factory-constructor",
   Procedure.FlagExtensionMember: "extension-member",
   Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
   Procedure.FlagSynthetic: "synthetic",
@@ -1906,20 +1905,18 @@
     ListSerializer(
         Case(ConstructorFlagTagger(), convertFlagsMap(constructorFlagToName))));
 
-const Map<int, String> redirectingFactoryConstructorFlagToName = const {
-  RedirectingFactoryConstructor.FlagConst: "const",
-  RedirectingFactoryConstructor.FlagExternal: "external",
-  RedirectingFactoryConstructor.FlagNonNullableByDefault:
-      "non-nullable-by-default",
+const Map<int, String> redirectingFactoryFlagToName = const {
+  RedirectingFactory.FlagConst: "const",
+  RedirectingFactory.FlagExternal: "external",
+  RedirectingFactory.FlagNonNullableByDefault: "non-nullable-by-default",
 };
 
-class RedirectingFactoryConstructorFlagTagger implements Tagger<int> {
-  const RedirectingFactoryConstructorFlagTagger();
+class RedirectingFactoryFlagTagger implements Tagger<int> {
+  const RedirectingFactoryFlagTagger();
 
   String tag(int flag) {
-    return redirectingFactoryConstructorFlagToName[flag] ??
-        (throw StateError(
-            "Unknown RedirectingFactoryConstructor flag value: ${flag}."));
+    return redirectingFactoryFlagToName[flag] ??
+        (throw StateError("Unknown RedirectingFactory flag value: ${flag}."));
   }
 }
 
@@ -1929,8 +1926,8 @@
             .where((f) => f != 0)
             .toList(),
         (u) => u.fold(0, (fs, f) => fs |= f),
-        ListSerializer(Case(RedirectingFactoryConstructorFlagTagger(),
-            convertFlagsMap(redirectingFactoryConstructorFlagToName))));
+        ListSerializer(Case(RedirectingFactoryFlagTagger(),
+            convertFlagsMap(redirectingFactoryFlagToName))));
 
 class MemberTagger implements Tagger<Member> {
   const MemberTagger();
@@ -1940,7 +1937,7 @@
       return node.hasSetter ? "mutable-field" : "immutable-field";
     } else if (node is Constructor) {
       return "constructor";
-    } else if (node is RedirectingFactoryConstructor) {
+    } else if (node is RedirectingFactory) {
       return "redirecting-factory-constructor";
     } else if (node is Procedure) {
       switch (node.kind) {
@@ -2036,57 +2033,25 @@
     Tuple4Serializer(nameSerializer, constructorFlagsSerializer,
         functionNodeWithInitializersSerializer, UriSerializer()));
 
-TextSerializer<RedirectingFactoryConstructor>
-    redirectingFactoryConstructorSerializer
+TextSerializer<RedirectingFactory> redirectingFactoryConstructorSerializer
     // Comment added to direct formatter.
     = Wrapped<
-            Tuple5<
-                Name,
-                int,
-                CanonicalName,
-                Tuple2<
-                    List<TypeParameter>,
-                    Tuple4<List<VariableDeclaration>, List<VariableDeclaration>,
-                        List<VariableDeclaration>, List<DartType>>>,
-                Uri>,
-            RedirectingFactoryConstructor>(
-        (w) => Tuple5(
-            w.name,
-            w.flags,
-            w.targetReference!.canonicalName!,
-            Tuple2(
-                w.typeParameters,
-                Tuple4(
-                    w.positionalParameters
-                        .take(w.requiredParameterCount)
-                        .toList(),
-                    w.positionalParameters
-                        .skip(w.requiredParameterCount)
-                        .toList(),
-                    w.namedParameters,
-                    w.typeArguments)),
-            w.fileUri),
-        (u) => RedirectingFactoryConstructor(u.third.reference,
+            Tuple6<Name, int, FunctionNode, CanonicalName, List<DartType>, Uri>,
+            RedirectingFactory>(
+        (w) => Tuple6(w.name, w.flags, w.function,
+            w.targetReference!.canonicalName!, w.typeArguments, w.fileUri),
+        (u) => RedirectingFactory(u.fourth.reference,
             name: u.first,
-            typeParameters: u.fourth.first,
-            positionalParameters:
-                u.fourth.second.first + u.fourth.second.second,
-            requiredParameterCount: u.fourth.second.first.length,
-            namedParameters: u.fourth.second.third,
-            typeArguments: u.fourth.second.fourth,
-            fileUri: u.fifth)
+            function: u.third,
+            typeArguments: u.fifth,
+            fileUri: u.sixth)
           ..flags = u.second,
-        Tuple5Serializer(
+        Tuple6Serializer(
             nameSerializer,
             redirectingFactoryConstructorFlagsSerializer,
+            functionNodeSerializer,
             CanonicalNameSerializer(),
-            Bind(
-                typeParametersSerializer,
-                Tuple4Serializer(
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(variableDeclarationSerializer),
-                    ListSerializer(dartTypeSerializer))),
+            ListSerializer(dartTypeSerializer),
             UriSerializer()));
 
 Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
@@ -2281,7 +2246,7 @@
 
 TextSerializer<StaticTearOffConstant> tearOffConstantSerializer =
     Wrapped<CanonicalName, StaticTearOffConstant>(
-        (w) => w.memberReference.canonicalName!,
+        (w) => w.targetReference.canonicalName!,
         (u) => StaticTearOffConstant.byReference(u.reference),
         CanonicalNameSerializer());
 
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index af4d5e3..68d7596 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -208,7 +208,7 @@
     handleFunctionNode(node.function);
   }
 
-  visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  visitRedirectingFactory(RedirectingFactory node) {
     currentReturnType = null;
     currentYieldType = null;
   }
@@ -521,8 +521,12 @@
 
   @override
   DartType visitConstructorTearOff(ConstructorTearOff node) {
-    return node.constructorReference.asConstructor.function
-        .computeFunctionType(Nullability.nonNullable);
+    return node.function.computeFunctionType(Nullability.nonNullable);
+  }
+
+  @override
+  DartType visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+    return node.function.computeFunctionType(Nullability.nonNullable);
   }
 
   @override
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 1f71e2c..ebbb991 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -82,6 +82,8 @@
   R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
       defaultExpression(node);
   R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+      defaultExpression(node);
   R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
 }
 
@@ -124,7 +126,7 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
-  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  R visitRedirectingFactory(RedirectingFactory node) {
     return defaultMember(node);
   }
 }
@@ -137,8 +139,7 @@
   R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
   R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
   R visitField(Field node, A arg) => defaultMember(node, arg);
-  R visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, A arg) {
+  R visitRedirectingFactory(RedirectingFactory node, A arg) {
     return defaultMember(node, arg);
   }
 }
@@ -258,6 +259,8 @@
   R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
       defaultExpression(node);
   R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+      defaultExpression(node);
   R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
 
   // Statements
@@ -292,7 +295,7 @@
   R visitConstructor(Constructor node) => defaultMember(node);
   R visitProcedure(Procedure node) => defaultMember(node);
   R visitField(Field node) => defaultMember(node);
-  R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+  R visitRedirectingFactory(RedirectingFactory node) {
     return defaultMember(node);
   }
 
@@ -436,6 +439,8 @@
       defaultExpression(node, arg);
   R visitConstructorTearOff(ConstructorTearOff node, A arg) =>
       defaultExpression(node, arg);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, A arg) =>
+      defaultExpression(node, arg);
   R visitTypedefTearOff(TypedefTearOff node, A arg) =>
       defaultExpression(node, arg);
 
@@ -480,8 +485,7 @@
   R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
   R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
   R visitField(Field node, A arg) => defaultMember(node, arg);
-  R visitRedirectingFactoryConstructor(
-      RedirectingFactoryConstructor node, A arg) {
+  R visitRedirectingFactory(RedirectingFactory node, A arg) {
     return defaultMember(node, arg);
   }
 
@@ -589,6 +593,9 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 }
@@ -610,6 +617,8 @@
   R visitTypedefTearOffConstant(TypedefTearOffConstant node);
   R visitStaticTearOffConstant(StaticTearOffConstant node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node);
+  R visitRedirectingFactoryTearOffConstant(
+      RedirectingFactoryTearOffConstant node);
   R visitTypeLiteralConstant(TypeLiteralConstant node);
   R visitUnevaluatedConstant(UnevaluatedConstant node);
 }
@@ -636,6 +645,11 @@
       _callback.visitConstructorTearOffConstant(node);
 
   @override
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      _callback.visitRedirectingFactoryTearOffConstant(node);
+
+  @override
   R visitInstantiationConstant(InstantiationConstant node) =>
       _callback.visitInstantiationConstant(node);
 
@@ -730,6 +744,9 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 }
@@ -774,6 +791,9 @@
       defaultConstant(node);
   void visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  void visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   void visitTypeLiteralConstant(TypeLiteralConstant node) =>
       defaultConstant(node);
   void visitUnevaluatedConstant(UnevaluatedConstant node) =>
@@ -788,8 +808,7 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
-  R visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  R visitRedirectingFactoryReference(RedirectingFactory node) {
     return defaultMemberReference(node);
   }
 }
@@ -839,6 +858,9 @@
       defaultConstant(node);
   R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
       defaultConstant(node);
+  R visitRedirectingFactoryTearOffConstant(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
   R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
 
@@ -878,6 +900,9 @@
       defaultConstantReference(node);
   R visitConstructorTearOffConstantReference(ConstructorTearOffConstant node) =>
       defaultConstantReference(node);
+  R visitRedirectingFactoryTearOffConstantReference(
+          RedirectingFactoryTearOffConstant node) =>
+      defaultConstantReference(node);
   R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
       defaultConstantReference(node);
   R visitUnevaluatedConstantReference(UnevaluatedConstant node) =>
@@ -889,8 +914,7 @@
   R visitFieldReference(Field node) => defaultMemberReference(node);
   R visitConstructorReference(Constructor node) => defaultMemberReference(node);
   R visitProcedureReference(Procedure node) => defaultMemberReference(node);
-  R visitRedirectingFactoryConstructorReference(
-      RedirectingFactoryConstructor node) {
+  R visitRedirectingFactoryReference(RedirectingFactory node) {
     return defaultMemberReference(node);
   }
 
@@ -1346,14 +1370,14 @@
     transformList(nodes, parent, dummyField);
   }
 
-  /// Transforms or removes [RedirectingFactoryConstructor] nodes in [nodes] as
+  /// Transforms or removes [RedirectingFactory] nodes in [nodes] as
   /// children of [parent].
   ///
   /// This is convenience method for calling [transformList] with removal
-  /// sentinel for [RedirectingFactoryConstructor] nodes.
-  void transformRedirectingFactoryConstructorList(
-      List<RedirectingFactoryConstructor> nodes, TreeNode parent) {
-    transformList(nodes, parent, dummyRedirectingFactoryConstructor);
+  /// sentinel for [RedirectingFactory] nodes.
+  void transformRedirectingFactoryList(
+      List<RedirectingFactory> nodes, TreeNode parent) {
+    transformList(nodes, parent, dummyRedirectingFactory);
   }
 
   /// Transforms or removes [Typedef] nodes in [nodes] as children of [parent].
@@ -1581,6 +1605,8 @@
       defaultExpression(node, arg);
   R visitConstructorTearOff(ConstructorTearOff node, T arg) =>
       defaultExpression(node, arg);
+  R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, T arg) =>
+      defaultExpression(node, arg);
   R visitTypedefTearOff(TypedefTearOff node, T arg) =>
       defaultExpression(node, arg);
 }
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 9803f71..8c1a8bf 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -729,8 +729,8 @@
       enclosingClass.addField(node);
     } else if (node is Constructor) {
       enclosingClass.addConstructor(node);
-    } else if (node is RedirectingFactoryConstructor) {
-      enclosingClass.addRedirectingFactoryConstructor(node);
+    } else if (node is RedirectingFactory) {
+      enclosingClass.addRedirectingFactory(node);
     } else {
       throw "Unexpected class member: ${node.runtimeType}";
     }
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index e24408b..ebecc27 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -79,13 +79,13 @@
     var type = _annotationsDefineRoot(proc.annotations);
     if (type == null) return;
 
-    if (proc.isRedirectingFactoryConstructor) {
+    if (proc.isRedirectingFactory) {
       if (type != PragmaEntryPointType.CallOnly &&
           type != PragmaEntryPointType.Default) {
         throw "Error: factory $proc doesn't have a setter or getter";
       }
       Member target = proc;
-      while (target is Procedure && target.isRedirectingFactoryConstructor) {
+      while (target is Procedure && target.isRedirectingFactory) {
         target = getRedirectingFactoryBody(target).target;
         assert(target != null);
         assert(
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 362bc5c..1527a11 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -605,7 +605,7 @@
         "${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""}";
     debugPrint("===== $summaryName =====");
     assert(!member.isAbstract);
-    assert(!(member is Procedure && member.isRedirectingFactoryConstructor));
+    assert(!(member is Procedure && member.isRedirectingFactory));
 
     _protobufHandler?.beforeSummaryCreation(member);
 
@@ -2483,7 +2483,7 @@
 
   @override
   Type visitStaticTearOffConstant(StaticTearOffConstant constant) {
-    final Member member = constant.procedure;
+    final Member member = constant.target;
     summaryCollector._entryPointsListener
         .addRawCall(new DirectSelector(member));
     if (member is Constructor) {
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 285990d..fb4dec7 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1129,8 +1129,7 @@
     transformConstructorList(node.constructors, node);
     transformProcedureList(node.procedures, node);
     transformFieldList(node.fields, node);
-    transformRedirectingFactoryConstructorList(
-        node.redirectingFactoryConstructors, node);
+    transformRedirectingFactoryList(node.redirectingFactories, node);
     return node;
   }
 
@@ -1811,7 +1810,7 @@
 
   @override
   visitStaticTearOffConstant(StaticTearOffConstant constant) {
-    shaker.addUsedMember(constant.procedure);
+    shaker.addUsedMember(constant.target);
   }
 
   @override
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7a07552..68734d6 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -230,7 +230,7 @@
     bool has_field_initializers = false;
     for (intptr_t i = 0; i < list_length; ++i) {
       if (PeekTag() == kRedirectingInitializer ||
-          PeekTag() == kRedirectingFactoryConstructor) {
+          PeekTag() == kRedirectingFactory) {
         is_redirecting_constructor = true;
       } else if (PeekTag() == kFieldInitializer) {
         has_field_initializers = true;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index c8e3ca3..e9a4807 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -554,7 +554,7 @@
     kConst = 1 << 3,  // Only for external const factories.
 
     // TODO(29841): Remove this line after the issue is resolved.
-    kRedirectingFactoryConstructor = 1 << 4,
+    kRedirectingFactory = 1 << 4,
     kExtensionMember = 1 << 5,
     kSyntheticProcedure = 1 << 7,
   };
@@ -579,8 +579,8 @@
     return stub_kind_ == kAbstractForwardingStubKind ||
            stub_kind_ == kConcreteForwardingStubKind;
   }
-  bool IsRedirectingFactoryConstructor() const {
-    return (flags_ & kRedirectingFactoryConstructor) != 0;
+  bool IsRedirectingFactory() const {
+    return (flags_ & kRedirectingFactory) != 0;
   }
   bool IsNoSuchMethodForwarder() const {
     return stub_kind_ == kNoSuchMethodForwarderStubKind;
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index b2a6031..34249a3 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -604,13 +604,11 @@
     LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
     ASSERT(future != nullptr);
     future->set_is_chained_future();
-    future->set_expected_context_index(Context::kFutureTimeoutFutureIndex);
   } else if (function.recognized_kind() == MethodRecognizer::kFutureWait &&
              depth_.function_ == 1) {
     LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
     ASSERT(future != nullptr);
     future->set_is_chained_future();
-    future->set_expected_context_index(Context::kFutureWaitFutureIndex);
   }
 }
 
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 57b229a..c30f759 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
 
 // Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 67;
-static const uint32_t kMaxSupportedKernelFormatVersion = 67;
+static const uint32_t kMinSupportedKernelFormatVersion = 68;
+static const uint32_t kMaxSupportedKernelFormatVersion = 68;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -33,7 +33,7 @@
   V(Field, 4)                                                                  \
   V(Constructor, 5)                                                            \
   V(Procedure, 6)                                                              \
-  V(RedirectingFactoryConstructor, 108)                                        \
+  V(RedirectingFactory, 108)                                                   \
   V(InvalidInitializer, 7)                                                     \
   V(FieldInitializer, 8)                                                       \
   V(SuperInitializer, 9)                                                       \
@@ -98,6 +98,7 @@
   V(ConstMapLiteral, 59)                                                       \
   V(ConstructorTearOff, 60)                                                    \
   V(TypedefTearOff, 83)                                                        \
+  V(RedirectingFactoryTearOff, 84)                                             \
   V(ExpressionStatement, 61)                                                   \
   V(Block, 62)                                                                 \
   V(EmptyStatement, 63)                                                        \
@@ -175,6 +176,7 @@
   kUnevaluatedConstant = 12,
   kTypedefTearOffConstant = 14,
   kConstructorTearOffConstant = 15,
+  kRedirectingFactoryTearOffConstant = 16,
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index d6cbc64..a45e80c 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1946,7 +1946,7 @@
   // additional functions can cause strain on the VM. They are therefore skipped
   // in jit mode and their associated origin function is used instead as
   // interface call target.
-  if (procedure_helper.IsRedirectingFactoryConstructor() ||
+  if (procedure_helper.IsRedirectingFactory() ||
       (!FLAG_precompiled_mode && procedure_helper.IsMemberSignature())) {
     helper_.SetOffset(procedure_end);
     return;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 3046b1a..3b80f79 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -6747,8 +6747,6 @@
   static const intptr_t kControllerIndex = 1;
   // Expected context index of chained futures in recognized async functions.
   // These are used to unwind async stacks.
-  static const intptr_t kFutureTimeoutFutureIndex = 2;
-  static const intptr_t kFutureWaitFutureIndex = 2;
   static const intptr_t kIsSyncIndex = 2;
 
   struct ArrayTraits {
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 404f142..e502c01 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -173,6 +173,8 @@
   RW(Function, complete_on_async_return)                                       \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
+  RW(Smi, future_timeout_future_index)                                         \
+  RW(Smi, future_wait_future_index)                                            \
   RW(CompressedStackMaps, canonicalized_stack_map_entries)                     \
   RW(ObjectPool, global_object_pool)                                           \
   RW(Array, unique_dynamic_targets)                                            \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 2553f7c..9c07f25 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2532,8 +2532,8 @@
   const VariableIndex first_local_index(-1);
   bool found_captured_vars = false;
   VariableIndex next_index = parent_scope->AllocateVariables(
-      first_parameter_index, num_parameters, first_local_index, NULL,
-      &found_captured_vars);
+      Function::null_function(), first_parameter_index, num_parameters,
+      first_local_index, NULL, &found_captured_vars);
   // Variables a, c and var_ta are captured, therefore are not allocated in
   // frame.
   EXPECT_EQ(0, next_index.value() -
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 866d0aa..7c6592f 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -287,7 +287,7 @@
   VariableIndex first_local_index =
       VariableIndex(parameter_index_start.value() > 0 ? 0 : -num_params);
   VariableIndex next_free_index = scope->AllocateVariables(
-      parameter_index_start, num_params, first_local_index, NULL,
+      function(), parameter_index_start, num_params, first_local_index, NULL,
       &found_captured_variables);
 
   num_stack_locals_ = -next_free_index.value();
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 3020106b..6eb0c25 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -1436,7 +1436,7 @@
   ObjectPtr* from = object_store->from();
   ObjectPtr* to = object_store->to_snapshot(Snapshot::kFullAOT);
   for (ObjectPtr* p = from; p <= to; p++) {
-    if ((*p)->IsCode()) {
+    if ((*p)->IsHeapObject() && (*p)->IsCode()) {
       code ^= *p;
       inst = code.instructions();
       thread->heap()->SetLoadingUnit(inst.ptr(), LoadingUnit::kRootId);
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c643b46..b2e773d 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -7,6 +7,7 @@
 
 #include "vm/compiler/backend/slot.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
@@ -194,7 +195,8 @@
       &Slot::GetContextVariableSlotFor(Thread::Current(), *variable));
 }
 
-VariableIndex LocalScope::AllocateVariables(VariableIndex first_parameter_index,
+VariableIndex LocalScope::AllocateVariables(const Function& function,
+                                            VariableIndex first_parameter_index,
                                             int num_parameters,
                                             VariableIndex first_local_index,
                                             LocalScope* context_owner,
@@ -252,8 +254,17 @@
   if (chained_future != nullptr) {
     AllocateContextVariable(chained_future, &context_owner);
     *found_captured_variables = true;
-    ASSERT(chained_future->index().value() ==
-           chained_future->expected_context_index());
+    // Remember context indices of _future variables in _Future.timeout and
+    // Future.wait. They are used while collecting async stack traces.
+    if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
+      IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
+          Smi::Handle(Smi::New(chained_future->index().value())));
+    } else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
+      IsolateGroup::Current()->object_store()->set_future_wait_future_index(
+          Smi::Handle(Smi::New(chained_future->index().value())));
+    } else {
+      UNREACHABLE();
+    }
   }
   if (is_sync != nullptr) {
     AllocateContextVariable(is_sync, &context_owner);
@@ -312,7 +323,7 @@
     // No parameters in children scopes.
     const int num_parameters_in_child = 0;
     VariableIndex child_next_index = child->AllocateVariables(
-        dummy_parameter_index, num_parameters_in_child, next_index,
+        function, dummy_parameter_index, num_parameters_in_child, next_index,
         context_owner, found_captured_variables);
     if (child_next_index.value() < min_index.value()) {
       min_index = child_next_index;
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 593e186..ff80167 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -94,7 +94,6 @@
         covariance_mode_(kNotCovariant),
         is_late_(false),
         is_chained_future_(false),
-        expected_context_index_(-1),
         late_init_offset_(0),
         type_check_mode_(kDoTypeCheck),
         index_() {
@@ -136,11 +135,6 @@
   bool is_chained_future() const { return is_chained_future_; }
   void set_is_chained_future() { is_chained_future_ = true; }
 
-  intptr_t expected_context_index() const { return expected_context_index_; }
-  void set_expected_context_index(int index) {
-    expected_context_index_ = index;
-  }
-
   intptr_t late_init_offset() const { return late_init_offset_; }
   void set_late_init_offset(intptr_t late_init_offset) {
     late_init_offset_ = late_init_offset;
@@ -244,7 +238,6 @@
   CovarianceMode covariance_mode_;
   bool is_late_;
   bool is_chained_future_;
-  intptr_t expected_context_index_;
   intptr_t late_init_offset_;
   TypeCheckMode type_check_mode_;
   VariableIndex index_;
@@ -476,7 +469,8 @@
   // Two locals in different sibling scopes may share the same frame slot.
   //
   // Return the index of the next available frame slot.
-  VariableIndex AllocateVariables(VariableIndex first_parameter_index,
+  VariableIndex AllocateVariables(const Function& function,
+                                  VariableIndex first_parameter_index,
                                   int num_parameters,
                                   VariableIndex first_local_index,
                                   LocalScope* context_owner,
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 74fa21a..1f29e90 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -5,6 +5,7 @@
 #include "vm/stack_trace.h"
 
 #include "vm/dart_api_impl.h"
+#include "vm/object_store.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
@@ -242,14 +243,26 @@
     parent_function_ = receiver_function_.parent_function();
     if (parent_function_.recognized_kind() ==
         MethodRecognizer::kFutureTimeout) {
-      context_entry_ = receiver_context_.At(Context::kFutureTimeoutFutureIndex);
+      ASSERT(IsolateGroup::Current()
+                 ->object_store()
+                 ->future_timeout_future_index() != Object::null());
+      const intptr_t future_index =
+          Smi::Value(IsolateGroup::Current()
+                         ->object_store()
+                         ->future_timeout_future_index());
+      context_entry_ = receiver_context_.At(future_index);
       return GetCallerInFutureImpl(context_entry_);
     }
 
     if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) {
       receiver_context_ = receiver_context_.parent();
       ASSERT(!receiver_context_.IsNull());
-      context_entry_ = receiver_context_.At(Context::kFutureWaitFutureIndex);
+      ASSERT(
+          IsolateGroup::Current()->object_store()->future_wait_future_index() !=
+          Object::null());
+      const intptr_t future_index = Smi::Value(
+          IsolateGroup::Current()->object_store()->future_wait_future_index());
+      context_entry_ = receiver_context_.At(future_index);
       return GetCallerInFutureImpl(context_entry_);
     }
   }
diff --git a/tools/VERSION b/tools/VERSION
index d81caa4..21e7eeb 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 334
+PRERELEASE 335
 PRERELEASE_PATCH 0
\ No newline at end of file