Skip to content

Commit 3dfd95a

Browse files
authored
Ensure null-coalescing LHS is evaluated only once (PowerShell#12667)
1 parent 270eabc commit 3dfd95a

2 files changed

Lines changed: 26 additions & 10 deletions

File tree

src/System.Management.Automation/engine/parser/Compiler.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -982,19 +982,23 @@ private static Expression Coalesce(Expression left, Expression right)
982982
{
983983
return left;
984984
}
985-
else if (leftType == typeof(AutomationNull))
986-
{
987-
return right;
988-
}
989985
else
990986
{
991-
Expression lhs = left.Cast(typeof(object));
992-
Expression rhs = right.Cast(typeof(object));
987+
ParameterExpression lhsStoreVar = Expression.Variable(typeof(object));
988+
var blockParameters = new ParameterExpression[] { lhsStoreVar };
989+
var blockStatements = new Expression[]
990+
{
991+
Expression.Assign(lhsStoreVar, left.Cast(typeof(object))),
992+
Expression.Condition(
993+
Expression.Call(CachedReflectionInfo.LanguagePrimitives_IsNull, lhsStoreVar),
994+
right.Cast(typeof(object)),
995+
lhsStoreVar),
996+
};
993997

994-
return Expression.Condition(
995-
Expression.Call(CachedReflectionInfo.LanguagePrimitives_IsNull, lhs),
996-
rhs,
997-
lhs);
998+
return Expression.Block(
999+
typeof(object),
1000+
blockParameters,
1001+
blockStatements);
9981002
}
9991003
}
10001004

test/powershell/Language/Operators/NullConditional.Tests.ps1

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,18 @@ Describe 'NullCoalesceOperations' -Tags 'CI' {
172172
It 'Lhs is $?' {
173173
{$???$false} | Should -BeTrue
174174
}
175+
176+
It 'Should only evaluate LHS once when it IS null' {
177+
$testState = [pscustomobject]@{ Value = 0 }
178+
(& { [void]$testState.Value++ }) ?? 'Nothing' | Should -BeExactly 'Nothing'
179+
$testState.Value | Should -Be 1
180+
}
181+
182+
It 'Should only evaluate LHS once when it is NOT null' {
183+
$testState = [pscustomobject]@{ Value = 0 }
184+
(& { 'Test'; [void]$testState.Value++ }) ?? 'Nothing' | Should -BeExactly 'Test'
185+
$testState.Value | Should -Be 1
186+
}
175187
}
176188

177189
Context 'Null Coalesce ?? operator precedence' {

0 commit comments

Comments
 (0)