[dart2js] Use correct futureValueType.

Fixes: #54317
Change-Id: Id94b486df6a66ef6c77f2c578ab8d11a73189ff9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341328
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Mayank Patke <fishythefish@google.com>
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index 34dbf15..8468322 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -1496,10 +1496,10 @@
   /// argument is passed.
   DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable);
 
-  /// Returns the 'element' type of a function with the async, async* or sync*
-  /// marker [marker]. [returnType] is the return type marked function.
+  /// Returns the 'element' type of a [function] with the async, async* or sync*
+  /// marker. [returnType] is the return type of the marked function.
   DartType getAsyncOrSyncStarElementType(
-      AsyncMarker marker, DartType returnType);
+      FunctionEntity function, DartType returnType);
 
   /// Returns the 'element' type of a function with an async, async* or sync*
   /// marker. The return type of the method is inspected to determine the type
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 4019f5c..0c4f6f7 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -235,12 +235,18 @@
     case MemberKind.constructorBody:
       ir.Member node = definition.node as ir.Member;
       return node.function;
+    case MemberKind.generatorBody:
+      final node = definition.node;
+      if (node is ir.LocalFunction) return node.function;
+      return (node as ir.Member).function;
     case MemberKind.closureCall:
       ir.LocalFunction node = definition.node as ir.LocalFunction;
       return node.function;
-    default:
+    case MemberKind.closureField:
+    case MemberKind.signature:
+    case MemberKind.recordGetter:
+      return null;
   }
-  return null;
 }
 
 /// Returns the initializer for [field].
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 5ea8aaa..bf0a945 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -2221,13 +2221,14 @@
   DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
     // TODO(sra): Should be getting the DartType from the node.
     DartType returnType = getFunctionType(function).returnType;
-    return getAsyncOrSyncStarElementType(function.asyncMarker, returnType);
+    return getAsyncOrSyncStarElementType(function, returnType);
   }
 
   @override
   DartType getAsyncOrSyncStarElementType(
-      AsyncMarker asyncMarker, DartType returnType) {
-    var returnTypeWithoutNullability = returnType.withoutNullability;
+      FunctionEntity function, DartType returnType) {
+    final asyncMarker = function.asyncMarker;
+    final returnTypeWithoutNullability = returnType.withoutNullability;
     switch (asyncMarker) {
       case AsyncMarker.SYNC:
         return returnType;
@@ -2240,16 +2241,8 @@
         }
         return dynamicType;
       case AsyncMarker.ASYNC:
-        if (returnTypeWithoutNullability is FutureOrType) {
-          return returnTypeWithoutNullability.typeArgument;
-        }
-        if (returnTypeWithoutNullability is InterfaceType) {
-          if (returnTypeWithoutNullability.element ==
-              elementMap.commonElements.futureClass) {
-            return returnTypeWithoutNullability.typeArguments.first;
-          }
-        }
-        return dynamicType;
+        return elementMap.getDartType(
+            getFunctionNode(elementMap, function)!.futureValueType!);
       case AsyncMarker.ASYNC_STAR:
         if (returnTypeWithoutNullability is InterfaceType) {
           if (returnTypeWithoutNullability.element ==
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index c2c2186..9853b3b 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1367,7 +1367,7 @@
 
     // Add the type parameter for the generator's element type.
     DartType elementType = _elementEnvironment.getAsyncOrSyncStarElementType(
-        function.asyncMarker, _returnType!);
+        function, _returnType!);
 
     // TODO(sra): [elementType] can contain free type variables that are erased
     // due to no rtiNeed. We will get getter code if these type variables are
@@ -1454,7 +1454,7 @@
     // Call `_makeSyncStarIterable<T>(body)`. This usually gets inlined.
 
     final elementType = _elementEnvironment.getAsyncOrSyncStarElementType(
-        function.asyncMarker, _returnType!);
+        function, _returnType!);
     FunctionEntity method = _commonElements.syncStarIterableFactory;
     List<HInstruction> arguments = [pop()];
     List<DartType> typeArguments = const [];
diff --git a/tests/web/regress/issue/54317_test.dart b/tests/web/regress/issue/54317_test.dart
new file mode 100644
index 0000000..e4195f1
--- /dev/null
+++ b/tests/web/regress/issue/54317_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+void main() async {
+  final value = await fn();
+  Expect.equals(42, value);
+}
+
+FutureOr<Object> fn() async => 42;