1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
4 using System.Collections.Generic;
5 using System.Runtime.InteropServices.JavaScript;
6 using Microsoft.CodeAnalysis.CSharp;
7 using Microsoft.CodeAnalysis.CSharp.Syntax;
8 using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
10 namespace Microsoft.Interop.JavaScript
12 internal sealed class TaskJSGenerator : BaseJSGenerator
14 private MarshalerType _resultMarshalerType;
15 public TaskJSGenerator(MarshalerType resultMarshalerType)
16 : base(MarshalerType.Task, new Forwarder())
18 _resultMarshalerType = resultMarshalerType;
21 public override IEnumerable<ExpressionSyntax> GenerateBind(TypePositionInfo info, StubCodeContext context)
23 var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)info.MarshallingAttributeInfo).TypeInfo;
24 if (jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void))
26 yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task), ArgumentList());
30 yield return InvocationExpression(MarshalerTypeName(MarshalerType.Task),
31 ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_resultMarshalerType)))));
35 public override IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
37 var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)info.MarshallingAttributeInfo).TypeInfo;
39 string argName = context.GetAdditionalIdentifier(info, "js_arg");
40 var target = info.IsManagedReturnPosition
41 ? Constants.ArgumentReturn
44 var source = info.IsManagedReturnPosition
45 ? Argument(IdentifierName(context.GetIdentifiers(info).native))
46 : _inner.AsArgument(info, context);
48 if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && info.IsManagedReturnPosition)
50 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
51 ? ToManagedMethodVoid(target, source)
52 : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
55 if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && info.IsManagedReturnPosition)
57 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
58 ? ToJSMethodVoid(target, source)
59 : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
62 foreach (var x in base.Generate(info, context))
67 if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsManagedReturnPosition)
69 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
70 ? ToJSMethodVoid(target, source)
71 : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
74 if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsManagedReturnPosition)
76 yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)
77 ? ToManagedMethodVoid(target, source)
78 : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
82 private StatementSyntax ToManagedMethodVoid(string target, ArgumentSyntax source)
84 return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
85 IdentifierName(target), GetToManagedMethod(Type)))
86 .WithArgumentList(ArgumentList(SingletonSeparatedList(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))))));
89 private StatementSyntax ToJSMethodVoid(string target, ArgumentSyntax source)
91 return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
92 IdentifierName(target), GetToJSMethod(Type)))
93 .WithArgumentList(ArgumentList(SingletonSeparatedList(source))));
96 private StatementSyntax ToManagedMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
98 return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
99 IdentifierName(target), GetToManagedMethod(Type)))
100 .WithArgumentList(ArgumentList(SeparatedList(new[]{
101 source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
102 Argument(ParenthesizedLambdaExpression()
103 .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
104 .WithParameterList(ParameterList(SeparatedList(new[]{
105 Parameter(Identifier("__task_result_arg"))
106 .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword)))
107 .WithType(IdentifierName(Constants.JSMarshalerArgumentGlobal)),
108 Parameter(Identifier("__task_result"))
109 .WithModifiers(TokenList(Token(SyntaxKind.OutKeyword)))
110 .WithType(sourceType)})))
111 .WithBlock(Block(SingletonList<StatementSyntax>(ExpressionStatement(
112 InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
113 IdentifierName("__task_result_arg"), GetToManagedMethod(_resultMarshalerType)))
114 .WithArgumentList(ArgumentList(SeparatedList(new[]{
115 Argument(IdentifierName("__task_result")).WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)),
119 private StatementSyntax ToJSMethod(string target, ArgumentSyntax source, TypeSyntax sourceType)
121 return ExpressionStatement(InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
122 IdentifierName(target), GetToJSMethod(Type)))
123 .WithArgumentList(ArgumentList(SeparatedList(new[]{
125 Argument(ParenthesizedLambdaExpression()
126 .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
127 .WithParameterList(ParameterList(SeparatedList(new[]{
128 Parameter(Identifier("__task_result_arg"))
129 .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword)))
130 .WithType(IdentifierName(Constants.JSMarshalerArgumentGlobal)),
131 Parameter(Identifier("__task_result"))
132 .WithType(sourceType)})))
133 .WithBlock(Block(SingletonList<StatementSyntax>(ExpressionStatement(
134 InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
135 IdentifierName("__task_result_arg"), GetToJSMethod(_resultMarshalerType)))
136 .WithArgumentList(ArgumentList(SeparatedList(new[]{
137 Argument(IdentifierName("__task_result")),