[CFE] Add 'futureValueType' to visitors/transformers

Closes https://github.com/dart-lang/sdk/issues/48835

This fixes an issue in which erasure is incomplete for
static interop types.

Change-Id: Ia2aef8c009d83df30bbb63b9c4dbb5b96e9f8e34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241820
Commit-Queue: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 6ef2967..f3f7728 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3855,6 +3855,7 @@
     visitList(positionalParameters, v);
     visitList(namedParameters, v);
     returnType.accept(v);
+    futureValueType?.accept(v);
     body?.accept(v);
   }
 
@@ -3864,6 +3865,9 @@
     v.transformList(positionalParameters, this);
     v.transformList(namedParameters, this);
     returnType = v.visitDartType(returnType);
+    if (futureValueType != null) {
+      futureValueType = v.visitDartType(futureValueType!);
+    }
     if (body != null) {
       body = v.transform(body!);
       body?.parent = this;
@@ -3876,6 +3880,9 @@
     v.transformVariableDeclarationList(positionalParameters, this);
     v.transformVariableDeclarationList(namedParameters, this);
     returnType = v.visitDartType(returnType, cannotRemoveSentinel);
+    if (futureValueType != null) {
+      futureValueType = v.visitDartType(futureValueType!, cannotRemoveSentinel);
+    }
     if (body != null) {
       body = v.transformOrRemoveStatement(body!);
       body?.parent = this;
diff --git a/tests/lib/js/static_interop_test/futurevaluetype_test.dart b/tests/lib/js/static_interop_test/futurevaluetype_test.dart
new file mode 100644
index 0000000..ac2a5df
--- /dev/null
+++ b/tests/lib/js/static_interop_test/futurevaluetype_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, 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.
+
+// Test that `FunctionNode`'s `futureValueType`s are correctly transformed.
+// See https://github.com/dart-lang/sdk/issues/48835 for more details.
+
+@JS()
+library futurevaluetype_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+
+@JS()
+@staticInterop
+class JSWindow {}
+
+// `futureValueType` corresponds to the `JSWindow` type parameter in the return
+// value here. If this isn't correctly erased, we should see a runtime type
+// error when using this method, as we'll be attemting to return a `@Native`
+// type (`Window`) where a `package:js` type is expected instead of a
+// `JavaScriptObject`.
+Future<JSWindow> returnInteropType() async {
+  return window as JSWindow;
+}
+
+void main() async {
+  await returnInteropType();
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index f47d8cc..2f3fffb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -12,7 +12,8 @@
 isolate/issue_24243_parent_isolate_test: Skip # Requires checked mode
 
 [ $runtime == d8 ]
-js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Uses dart:html.
+js/js_util/javascriptobject_extensions_test: SkipByDesign # Uses dart:html.
+js/static_interop_test/futurevaluetype_test: SkipByDesign # Uses dart:html.
 
 [ $runtime == dart_precompiled ]
 isolate/package_config_getter_test: SkipByDesign # AOT mode doesn't preserve package structure.
diff --git a/tests/lib_2/js/static_interop_test/futurevaluetype_test.dart b/tests/lib_2/js/static_interop_test/futurevaluetype_test.dart
new file mode 100644
index 0000000..ac2a5df
--- /dev/null
+++ b/tests/lib_2/js/static_interop_test/futurevaluetype_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, 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.
+
+// Test that `FunctionNode`'s `futureValueType`s are correctly transformed.
+// See https://github.com/dart-lang/sdk/issues/48835 for more details.
+
+@JS()
+library futurevaluetype_test;
+
+import 'dart:html';
+
+import 'package:js/js.dart';
+
+@JS()
+@staticInterop
+class JSWindow {}
+
+// `futureValueType` corresponds to the `JSWindow` type parameter in the return
+// value here. If this isn't correctly erased, we should see a runtime type
+// error when using this method, as we'll be attemting to return a `@Native`
+// type (`Window`) where a `package:js` type is expected instead of a
+// `JavaScriptObject`.
+Future<JSWindow> returnInteropType() async {
+  return window as JSWindow;
+}
+
+void main() async {
+  await returnInteropType();
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index b253bfd..1feee84 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -12,7 +12,8 @@
 isolate/issue_24243_parent_isolate_test: Skip # Requires checked mode
 
 [ $runtime == d8 ]
-js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Uses dart:html.
+js/js_util/javascriptobject_extensions_test: SkipByDesign # Uses dart:html.
+js/static_interop_test/futurevaluetype_test: SkipByDesign # Uses dart:html.
 
 [ $runtime == dart_precompiled ]
 isolate/package_config_getter_test: SkipByDesign # AOT mode doesn't preserve package structure.