Revert the PR #17856 (Do not preserve temporary results when no need to do so) (#21368)

This commit is contained in:
Dongbo Wang 2024-03-25 14:09:11 -07:00 committed by GitHub
parent ad7278bbff
commit 171d9dfa71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 35 deletions

View File

@ -2278,25 +2278,26 @@ namespace System.Management.Automation.Language
switch (context)
{
case CaptureAstContext.AssignmentWithResultPreservation:
result = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, resultList);
// PipelineResult might get skipped in some circumstances due to an early return or a FlowControlException thrown out, in which case
// we write to the oldPipe. This can happen in cases like:
// $(1;2;return 3)
finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, oldPipe, resultList));
break;
case CaptureAstContext.AssignmentWithoutResultPreservation:
result = Expression.Call(CachedReflectionInfo.PipelineOps_PipelineResult, resultList);
// Clear the temporary pipe in case of exception, if we are not required to preserve the results
var catchExprs = new List<Expression>
if (context == CaptureAstContext.AssignmentWithoutResultPreservation)
{
Expression.Call(CachedReflectionInfo.PipelineOps_ClearPipe, resultList),
Expression.Rethrow(),
Expression.Constant(null, typeof(object))
};
var catchExprs = new List<Expression>
{
Expression.Call(CachedReflectionInfo.PipelineOps_ClearPipe, resultList),
Expression.Rethrow(),
Expression.Constant(null, typeof(object))
};
catches.Add(Expression.Catch(typeof(RuntimeException), Expression.Block(typeof(object), catchExprs)));
catches.Add(Expression.Catch(typeof(RuntimeException), Expression.Block(typeof(object), catchExprs)));
}
// PipelineResult might get skipped in some circumstances due to an early return or a FlowControlException thrown out,
// in which case we write to the oldPipe. This can happen in cases like:
// $(1;2;return 3)
finallyExprs.Add(Expression.Call(CachedReflectionInfo.PipelineOps_FlushPipe, oldPipe, resultList));
break;
case CaptureAstContext.Condition:
result = DynamicExpression.Dynamic(PSPipelineResultToBoolBinder.Get(), typeof(bool), resultList);

View File

@ -81,28 +81,6 @@ Describe "Scripting.Followup.Tests" -Tags "CI" {
$result | Should -BeOfType 'System.Collections.Specialized.OrderedDictionary'
}
It "Don't preserve result when no need to do so in case of flow-control exception" {
function TestFunc1([switch]$p) {
## No need to preserve and flush the results from the IF statement to the outer
## pipeline, because the results are supposed to be assigned to a variable.
if ($p) {
$null = if ($true) { "one"; return "two" }
} else {
$a = foreach ($a in 1) { "one"; return; }
}
}
function TestFunc2 {
## The results from the sub-expression need to be preserved and flushed to the outer pipeline.
$("1";return "2")
}
TestFunc1 | Should -Be $null
TestFunc1 -p | Should -Be $null
TestFunc2 | Should -Be @("1", "2")
}
It "'[NullString]::Value' should be treated as string type when resolving .NET method" {
$testType = 'NullStringTest' -as [type]
if (-not $testType) {
@ -146,4 +124,27 @@ public class NullStringTest {
$result = & $powershell -noprofile -c '[System.Text.Encoding]::GetEncoding("IBM437").WebName'
$result | Should -BeExactly "ibm437"
}
It 'Return statement on the right side of an assignment should write the retrun value to outer pipe' {
function TestFunc1 {
## The return value are not assigned to the variable but should be written to the outer pipe.
$Global:mylhsvar = if ($true) { return "one" }
}
function TestFunc2 {
## The results from the sub-expression need to be preserved and flushed to the outer pipeline.
$("1";return "2")
}
try {
$Global:mylhsvar = $null
TestFunc1 | Should -BeExactly "one"
TestFunc2 | Should -Be @("1", "2")
$Global:mylhsvar | Should -Be $null
}
finally {
Remove-Variable -Name mylhsvar -Scope Global
}
}
}