diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 0a18241ef7c767..a00fc9e4024f76 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -59,7 +59,7 @@ public JSExportCodeGenerator( public BlockSyntax GenerateJSExportBody() { - StatementSyntax invoke = InvokeSyntax(); + List invoke = InvokeSyntax(); GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables); @@ -79,7 +79,7 @@ public BlockSyntax GenerateJSExportBody() var tryStatements = new List(); tryStatements.AddRange(statements.Unmarshal); - tryStatements.Add(invoke); + tryStatements.AddRange(invoke); if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { @@ -93,6 +93,18 @@ public BlockSyntax GenerateJSExportBody() tryStatements.AddRange(statements.Marshal); List allStatements = setupStatements; + + // Wrap unmarshall, invocation and return value marshalling in try-catch. + // In case of exception, marshal exception instead of return value. + var tryInvokeAndMarshal = TryStatement(SingletonList(CatchClause() + .WithDeclaration(CatchDeclaration(IdentifierName(Constants.ExceptionGlobal)).WithIdentifier(Identifier("ex"))) + .WithBlock(Block(SingletonList( + ExpressionStatement(InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(Constants.ArgumentException), IdentifierName(Constants.ToJSMethod))) + .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("ex"))))))))))) + .WithBlock(Block(tryStatements)); + List finallyStatements = new List(); if (!(statements.GuaranteedUnmarshal.IsEmpty && statements.CleanupCalleeAllocated.IsEmpty)) { @@ -100,16 +112,14 @@ public BlockSyntax GenerateJSExportBody() } finallyStatements.AddRange(statements.CleanupCallerAllocated); + if (finallyStatements.Count > 0) { - allStatements.Add( - TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements)))); - } - else - { - allStatements.AddRange(tryStatements); + tryInvokeAndMarshal = TryStatement(Block(tryInvokeAndMarshal), default, FinallyClause(Block(finallyStatements))); } + allStatements.Add(tryInvokeAndMarshal); + return Block(allStatements); } @@ -175,7 +185,7 @@ private void SetupSyntax(List statementsToUpdate) Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1))))))))))))); } - private TryStatementSyntax InvokeSyntax() + private List InvokeSyntax() { var statements = new List(); var arguments = new List(); @@ -205,16 +215,8 @@ private TryStatementSyntax InvokeSyntax() IdentifierName(nativeIdentifier), invocation)); statements.Add(statement); - statements.AddRange(_marshallers.ManagedReturnMarshaller.Generator.Generate(_marshallers.ManagedReturnMarshaller.TypeInfo, _context with { CurrentStage = StubCodeContext.Stage.Marshal })); } - return TryStatement(SingletonList(CatchClause() - .WithDeclaration(CatchDeclaration(IdentifierName(Constants.ExceptionGlobal)).WithIdentifier(Identifier("ex"))) - .WithBlock(Block(SingletonList( - ExpressionStatement(InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(Constants.ArgumentException), IdentifierName(Constants.ToJSMethod))) - .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("ex"))))))))))) - .WithBlock(Block(statements)); + return statements; }