|
10 | 10 | using System.Linq; |
11 | 11 | using System.Numerics; |
12 | 12 | using System.Reflection; |
| 13 | +using System.Threading.Tasks; |
13 | 14 |
|
14 | 15 | using Microsoft.Scripting; |
15 | 16 | using Microsoft.Scripting.Actions; |
@@ -672,6 +673,9 @@ private class ProtectedMemberResolver : MemberResolver { |
672 | 673 | new OneOffResolver("__len__", LengthResolver), |
673 | 674 | new OneOffResolver("__format__", FormatResolver), |
674 | 675 | new OneOffResolver("__next__", NextResolver), |
| 676 | + new OneOffResolver("__await__", AwaitResolver), |
| 677 | + new OneOffResolver("__aiter__", AsyncIterResolver), |
| 678 | + new OneOffResolver("__anext__", AsyncNextResolver), |
675 | 679 |
|
676 | 680 | new OneOffResolver("__complex__", ComplexResolver), |
677 | 681 | new OneOffResolver("__float__", FloatResolver), |
@@ -965,6 +969,83 @@ internal static MemberGroup GetExtensionMemberGroup(Type type, MemberInfo[] news |
965 | 969 | return MemberGroup.EmptyGroup; |
966 | 970 | } |
967 | 971 |
|
| 972 | + /// <summary> |
| 973 | + /// Provides a resolution for __await__ on Task, Task<T>, ValueTask and ValueTask<T>. |
| 974 | + /// </summary> |
| 975 | + private static MemberGroup/*!*/ AwaitResolver(MemberBinder/*!*/ binder, Type/*!*/ type) { |
| 976 | + foreach (Type t in binder.GetContributingTypes(type)) { |
| 977 | + if (t.GetMember("__await__").Length > 0) { |
| 978 | + return MemberGroup.EmptyGroup; |
| 979 | + } |
| 980 | + } |
| 981 | + |
| 982 | + if (typeof(Task).IsAssignableFrom(type)) { |
| 983 | + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) { |
| 984 | + // Only use the generic TaskAwaitable<T> if the result type is visible |
| 985 | + // (e.g. Task.CompletedTask is Task<VoidTaskResult> at runtime where |
| 986 | + // VoidTaskResult is internal — fall back to non-generic TaskAwaitable) |
| 987 | + Type resultType = type.GetGenericArguments()[0]; |
| 988 | + if (resultType.IsVisible) { |
| 989 | + MethodInfo genMeth = typeof(InstanceOps).GetMethod(nameof(InstanceOps.TaskAwaitMethodGeneric)); |
| 990 | + return new MemberGroup( |
| 991 | + MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(type.GetGenericArguments()), type) |
| 992 | + ); |
| 993 | + } |
| 994 | + } |
| 995 | + return GetInstanceOpsMethod(type, nameof(InstanceOps.TaskAwaitMethod)); |
| 996 | + } |
| 997 | + |
| 998 | +#if NET |
| 999 | + if (type.IsGenericType) { |
| 1000 | + Type genDef = type.GetGenericTypeDefinition(); |
| 1001 | + if (genDef == typeof(ValueTask<>)) { |
| 1002 | + MethodInfo genMeth = typeof(InstanceOps).GetMethod(nameof(InstanceOps.ValueTaskAwaitMethodGeneric)); |
| 1003 | + return new MemberGroup( |
| 1004 | + MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(type.GetGenericArguments()), type) |
| 1005 | + ); |
| 1006 | + } |
| 1007 | + } |
| 1008 | + |
| 1009 | + if (type == typeof(ValueTask)) { |
| 1010 | + return GetInstanceOpsMethod(type, nameof(InstanceOps.ValueTaskAwaitMethod)); |
| 1011 | + } |
| 1012 | +#endif |
| 1013 | + |
| 1014 | + return MemberGroup.EmptyGroup; |
| 1015 | + } |
| 1016 | + |
| 1017 | + /// <summary> |
| 1018 | + /// Provides a resolution for __aiter__ on IAsyncEnumerable<T>. |
| 1019 | + /// </summary> |
| 1020 | + private static MemberGroup/*!*/ AsyncIterResolver(MemberBinder/*!*/ binder, Type/*!*/ type) { |
| 1021 | +#if NET |
| 1022 | + foreach (Type t in binder.GetContributingTypes(type)) { |
| 1023 | + if (t.GetMember("__aiter__").Length > 0) { |
| 1024 | + return MemberGroup.EmptyGroup; |
| 1025 | + } |
| 1026 | + } |
| 1027 | + |
| 1028 | + foreach (Type t in binder.GetInterfaces(type)) { |
| 1029 | + if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>)) { |
| 1030 | + MethodInfo genMeth = typeof(InstanceOps).GetMethod(nameof(InstanceOps.AsyncIterMethod)); |
| 1031 | + return new MemberGroup( |
| 1032 | + MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(t.GetGenericArguments()), type) |
| 1033 | + ); |
| 1034 | + } |
| 1035 | + } |
| 1036 | +#endif |
| 1037 | + |
| 1038 | + return MemberGroup.EmptyGroup; |
| 1039 | + } |
| 1040 | + |
| 1041 | + /// <summary> |
| 1042 | + /// Provides a resolution for __anext__ on AsyncEnumeratorWrapper<T>. |
| 1043 | + /// Not auto-mapped from interfaces; the wrapper class provides __anext__ directly. |
| 1044 | + /// </summary> |
| 1045 | + private static MemberGroup/*!*/ AsyncNextResolver(MemberBinder/*!*/ binder, Type/*!*/ type) { |
| 1046 | + return MemberGroup.EmptyGroup; |
| 1047 | + } |
| 1048 | + |
968 | 1049 | /// <summary> |
969 | 1050 | /// Provides a resolution for __len__ |
970 | 1051 | /// </summary> |
|
0 commit comments