Do not wrap return result to PSObject when converting ScriptBlock to delegate (#10619)

This is a breaking change for the delegate types with the object return type:

Before this change, the returned object will always be an PSObject instance.
After this change, the returned object is the underlying object, which could still be an PSObject if that's what the script actually returns.
This commit is contained in:
Dongbo Wang
2020-03-30 21:46:12 +05:00
committed by GitHub
parent e741dc58dd
commit c0c17ded03
2 changed files with 56 additions and 5 deletions
@@ -647,16 +647,17 @@ namespace System.Management.Automation
/// <remarks>
/// This does normal array reduction in the case of a one-element array.
/// </remarks>
internal static object GetRawResult(List<object> result)
internal static object GetRawResult(List<object> result, bool wrapToPSObject)
{
switch (result.Count)
{
case 0:
return AutomationNull.Value;
case 1:
return LanguagePrimitives.AsPSObjectOrNull(result[0]);
return wrapToPSObject ? LanguagePrimitives.AsPSObjectOrNull(result[0]) : result[0];
default:
return LanguagePrimitives.AsPSObjectOrNull(result.ToArray());
object resultArray = result.ToArray();
return wrapToPSObject ? LanguagePrimitives.AsPSObjectOrNull(resultArray) : resultArray;
}
}
@@ -807,7 +808,7 @@ namespace System.Management.Automation
outputPipe: outputPipe,
invocationInfo: null,
args: args);
return GetRawResult(rawResult);
return GetRawResult(rawResult, wrapToPSObject: false);
}
#endregion
@@ -934,7 +935,7 @@ namespace System.Management.Automation
outputPipe: outputPipe,
invocationInfo: null,
args: args);
return GetRawResult(result);
return GetRawResult(result, wrapToPSObject: true);
}
internal void InvokeWithPipe(
@@ -102,4 +102,54 @@ Describe "Language Primitive Tests" -Tags "CI" {
$val | Should -BeTrue
$result | Should -BeExactly $compareResult
}
It "Convert ScriptBlock to delegate type" {
$code = @'
using System;
namespace Test.API
{
public enum TestEnum
{
Music,
Video
}
public class LanguagePrimitivesTest
{
Func<string, object> _handlerReturnObject;
Func<string, TestEnum> _handlerReturnEnum;
public LanguagePrimitivesTest(Func<string, object> handlerReturnObject, Func<string, TestEnum> handlerReturnEnum)
{
_handlerReturnObject = handlerReturnObject;
_handlerReturnEnum = handlerReturnEnum;
}
public bool TestHandlerReturnEnum()
{
var value = _handlerReturnEnum("bar");
return value == TestEnum.Music;
}
public bool TestHandlerReturnObject()
{
object value = _handlerReturnObject("bar");
return value is TestEnum;
}
}
}
'@
if (-not ("Test.API.TestEnum" -as [type]))
{
Add-Type -TypeDefinition $code
}
# The script actually returns a enum value, and the converted delegate should return the boxed enum value.
$handlerReturnObject = [System.Func[string, object]] { param([string]$str) [Test.API.TestEnum]::Music }
# The script actually returns a string, and the converted delegate should return the corresponding enum value.
$handlerReturnEnum = [System.Func[string, Test.API.TestEnum]] { param([string]$str) "Music" }
$test = [Test.API.LanguagePrimitivesTest]::new($handlerReturnObject, $handlerReturnEnum)
$test.TestHandlerReturnEnum() | Should -BeTrue
$test.TestHandlerReturnObject() | Should -BeTrue
}
}