Fix array expression to not return null or throw error (#4296)

This change fixes 3 issues:
- According to [PowerShell Language Specification Version 3.0](https://www.microsoft.com/en-us/download/details.aspx?id=36389), as quoted: "_The result is the (possibly empty) unconstrained 1-dimensional array_", `@(...)` should only return `object[]` array.
- `@([object[]]$null).GetType()` fails with error `"You cannot call a method on a null-valued expression."`
- `@([System.Collections.Generic.List[object]]$null)` fails with error `"Object reference not set to an instance of an object."`
This commit is contained in:
Dongbo Wang
2017-07-24 21:52:30 -07:00
committed by GitHub
parent d24d1634ba
commit 0d8eff6446
2 changed files with 83 additions and 10 deletions
@@ -5477,6 +5477,8 @@ namespace System.Management.Automation.Language
public object VisitArrayExpression(ArrayExpressionAst arrayExpressionAst)
{
Expression values = null;
ExpressionAst pureExprAst = null;
var subExpr = arrayExpressionAst.SubExpression;
if (subExpr.Traps == null)
{
@@ -5485,10 +5487,10 @@ namespace System.Management.Automation.Language
var pipelineBase = subExpr.Statements[0] as PipelineBaseAst;
if (pipelineBase != null)
{
var exprAst = pipelineBase.GetPureExpression();
if (exprAst != null)
pureExprAst = pipelineBase.GetPureExpression();
if (pureExprAst != null)
{
values = Compile(exprAst);
values = Compile(pureExprAst);
}
}
}
@@ -5500,16 +5502,12 @@ namespace System.Management.Automation.Language
}
values = values ?? CaptureAstResults(subExpr, CaptureAstContext.Enumerable);
if (values.Type.IsArray)
if (pureExprAst is ArrayLiteralAst)
{
// If the result is already an array, don't wrap the array.
// If the pure expression is ArrayLiteralAst, just return the result.
return values;
}
if (values.Type == typeof(List<object>))
{
return Expression.Call(values, CachedReflectionInfo.ObjectList_ToArray);
}
if (values.Type.GetTypeInfo().IsPrimitive || values.Type == typeof(string))
if (values.Type.IsPrimitive || values.Type == typeof(string))
{
// Slight optimization - no need for a dynamic site. We could special case other
// types as well, but it's probably not worth it.
@@ -0,0 +1,75 @@
Describe "ArrayExpression Tests" -Tags "CI" {
It "@([object[]](1,2,3)) should return a 3-element array of object[]" {
$result = @([object[]](1,2,3))
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 3
}
It "@([int[]](1,2,3)) should return a 3-element array of object[]" {
$result = @([int[]](1,2,3))
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 3
}
It "@([object[]]`$null) should return a 1-element(`$null) array of object[]" {
$result = @([object[]]$null)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
It "@([int[]]`$null) should return a 1-element(`$null) array of object[]" {
$result = @([int[]]$null)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
It "@([object[]][System.Management.Automation.Internal.AutomationNull]::Value) should return a 1-element(`$null) array of object[]" {
$result = @([object[]][System.Management.Automation.Internal.AutomationNull]::Value)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
It "@([int[]][System.Management.Automation.Internal.AutomationNull]::Value) should return a 1-element(`$null) array of object[]" {
$result = @([int[]][System.Management.Automation.Internal.AutomationNull]::Value)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
It "@(`$null) should return a 1-element(`$null) array of object[]" {
$result = @($null)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
It "@([System.Management.Automation.Internal.AutomationNull]::Value) should return an empty array of object[]" {
$result = @([System.Management.Automation.Internal.AutomationNull]::Value)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 0
}
It "@([object[]]`$a) should return a new array" {
$a = 1,2,3
$result = @([object[]]$a)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 3
}
It "@([int[]]`$a) should return a new array" {
$a = 1,2,3
$result = @([int[]]$a)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 3
}
It "@([System.Collections.Generic.List[object]]`$null) should return a 1-element(`$null) array of object[]" {
$result = @([System.Collections.Generic.List[object]]$null)
$result.GetType().FullName | Should Be "System.Object[]"
$result.Length | Should Be 1
$result[0] | Should Be $null
}
}