Make some experimental features stable (#26348)

The following experimental features are made stable:
- PSNativeWindowsTildeExpansion
- PSRedirectToVariable
- PSSubsystemPluginModel
This commit is contained in:
Dongbo Wang
2025-10-30 14:26:03 -07:00
committed by GitHub
parent d38d6fadf9
commit 943257b247
11 changed files with 37 additions and 84 deletions
@@ -697,7 +697,6 @@ namespace Microsoft.PowerShell.Commands
/// Gets whether we will append to the variable if it exists.
/// </summary>
[Parameter]
[Experimental(ExperimentalFeature.PSRedirectToVariable, ExperimentAction.Show)]
public SwitchParameter Append { get; set; }
private bool _nameIsFormalParameter;
@@ -22,8 +22,6 @@ namespace System.Management.Automation
internal const string EngineSource = "PSEngine";
internal const string PSFeedbackProvider = "PSFeedbackProvider";
internal const string PSNativeWindowsTildeExpansion = nameof(PSNativeWindowsTildeExpansion);
internal const string PSRedirectToVariable = "PSRedirectToVariable";
internal const string PSSerializeJSONLongEnumAsNumber = nameof(PSSerializeJSONLongEnumAsNumber);
#endregion
@@ -107,21 +105,12 @@ namespace System.Management.Automation
name: "PSFileSystemProviderV2",
description: "Replace the old FileSystemProvider with cleaner design and faster code"),
*/
new ExperimentalFeature(
name: "PSSubsystemPluginModel",
description: "A plugin model for registering and un-registering PowerShell subsystems"),
new ExperimentalFeature(
name: "PSLoadAssemblyFromNativeCode",
description: "Expose an API to allow assembly loading from native code"),
new ExperimentalFeature(
name: PSFeedbackProvider,
description: "Replace the hard-coded suggestion framework with the extensible feedback provider"),
new ExperimentalFeature(
name: PSNativeWindowsTildeExpansion,
description: "On Windows, expand unquoted tilde (`~`) with the user's current home folder."),
new ExperimentalFeature(
name: PSRedirectToVariable,
description: "Add support for redirecting to the variable drive"),
new ExperimentalFeature(
name: PSSerializeJSONLongEnumAsNumber,
description: "Serialize enums based on long or ulong as an numeric value rather than the string representation when using ConvertTo-Json."
@@ -5478,6 +5478,7 @@ end {
{ "Get-Module", new SessionStateCmdletEntry("Get-Module", typeof(GetModuleCommand), helpFile) },
{ "Get-PSHostProcessInfo", new SessionStateCmdletEntry("Get-PSHostProcessInfo", typeof(GetPSHostProcessInfoCommand), helpFile) },
{ "Get-PSSession", new SessionStateCmdletEntry("Get-PSSession", typeof(GetPSSessionCommand), helpFile) },
{ "Get-PSSubsystem", new SessionStateCmdletEntry("Get-PSSubsystem", typeof(Subsystem.GetPSSubsystemCommand), helpFile) },
{ "Import-Module", new SessionStateCmdletEntry("Import-Module", typeof(ImportModuleCommand), helpFile) },
{ "Invoke-Command", new SessionStateCmdletEntry("Invoke-Command", typeof(InvokeCommandCommand), helpFile) },
{ "Invoke-History", new SessionStateCmdletEntry("Invoke-History", typeof(InvokeHistoryCommand), helpFile) },
@@ -5518,11 +5519,6 @@ end {
{ "Format-Default", new SessionStateCmdletEntry("Format-Default", typeof(FormatDefaultCommand), helpFile) },
};
if (ExperimentalFeature.IsEnabled("PSSubsystemPluginModel"))
{
cmdlets.Add("Get-PSSubsystem", new SessionStateCmdletEntry("Get-PSSubsystem", typeof(Subsystem.GetPSSubsystemCommand), helpFile));
}
#if UNIX
cmdlets.Add("Switch-Process", new SessionStateCmdletEntry("Switch-Process", typeof(SwitchProcessCommand), helpFile));
#endif
@@ -406,12 +406,9 @@ namespace System.Management.Automation
}
}
#else
if (!usedQuotes && ExperimentalFeature.IsEnabled(ExperimentalFeature.PSNativeWindowsTildeExpansion))
if (!usedQuotes && ExpandTilde(arg, parameter))
{
if (ExpandTilde(arg, parameter))
{
argExpanded = true;
}
argExpanded = true;
}
#endif
@@ -8,7 +8,6 @@ namespace System.Management.Automation.Subsystem
/// <summary>
/// Implementation of 'Get-PSSubsystem' cmdlet.
/// </summary>
[Experimental("PSSubsystemPluginModel", ExperimentAction.Show)]
[Cmdlet(VerbsCommon.Get, "PSSubsystem", DefaultParameterSetName = AllSet)]
[OutputType(typeof(SubsystemInfo))]
public sealed class GetPSSubsystemCommand : PSCmdlet
@@ -1092,14 +1092,11 @@ namespace System.Management.Automation
{
// Check first to see if File is a variable path. If so, we'll not create the FileBytePipe
bool redirectToVariable = false;
if (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSRedirectToVariable))
context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(File, out ProviderInfo p, out _);
if (p != null && p.NameEquals(context.ProviderNames.Variable))
{
ProviderInfo p;
context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(File, out p, out _);
if (p != null && p.NameEquals(context.ProviderNames.Variable))
{
redirectToVariable = true;
}
redirectToVariable = true;
}
if (commandProcessor is NativeCommandProcessor nativeCommand
@@ -1223,12 +1220,10 @@ namespace System.Management.Automation
// determine whether we're trying to set a variable by inspecting the file path
// if we can determine that it's a variable, we'll use Set-Variable rather than Out-File
ProviderInfo p;
PSDriveInfo d;
CommandProcessorBase commandProcessor;
var name = context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(File, out p, out d);
var name = context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(File, out ProviderInfo p, out _);
if (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSRedirectToVariable) && p != null && p.NameEquals(context.ProviderNames.Variable))
if (p != null && p.NameEquals(context.ProviderNames.Variable))
{
commandProcessor = context.CreateCommand("Set-Variable", false);
Diagnostics.Assert(commandProcessor != null, "CreateCommand returned null");
@@ -127,12 +127,6 @@ Describe "File redirection should have 'DoComplete' called on the underlying pip
Describe "Redirection and Set-Variable -append tests" -tags CI {
Context "variable redirection should work" {
BeforeAll {
if ( $EnabledExperimentalFeatures -contains "PSRedirectToVariable" ) {
$skipTest = $false
}
else {
$skipTest = $true
}
$testCases = @{ Name = "Variable should be created"; scriptBlock = { 1..3>variable:a }; Validation = { ($a -join "") | Should -Be ((1..3) -join "") } },
@{ Name = "variable should be appended"; scriptBlock = {1..3>variable:a; 4..6>>variable:a}; Validation = { ($a -join "") | Should -Be ((1..6) -join "")}},
@{ Name = "variable should maintain type"; scriptBlock = {@{one=1}>variable:a};Validation = {$a | Should -BeOfType [hashtable]}},
@@ -220,7 +214,7 @@ Describe "Redirection and Set-Variable -append tests" -tags CI {
}
It "<name>" -TestCases $testCases -skip:$skipTest {
It "<name>" -TestCases $testCases {
param ( $scriptBlock, $validation )
. $scriptBlock
. $validation
@@ -5,7 +5,6 @@ Describe 'Native Windows tilde expansion tests' -tags "CI" {
BeforeAll {
$originalDefaultParams = $PSDefaultParameterValues.Clone()
$PSDefaultParameterValues["it:skip"] = -Not $IsWindows
$EnabledExperimentalFeatures.Contains('PSNativeWindowsTildeExpansion') | Should -BeTrue
}
AfterAll {
@@ -21,12 +20,13 @@ Describe 'Native Windows tilde expansion tests' -tags "CI" {
cmd /c echo ~/foo | Should -BeExactly "$($ExecutionContext.SessionState.Provider.Get("FileSystem").Home)/foo"
cmd /c echo ~\foo | Should -BeExactly "$($ExecutionContext.SessionState.Provider.Get("FileSystem").Home)\foo"
}
It '~ should not be replaced when quoted' {
cmd /c echo '~' | Should -BeExactly '~'
cmd /c echo "~" | Should -BeExactly '~'
cmd /c echo '~/foo' | Should -BeExactly '~/foo'
cmd /c echo "~/foo" | Should -BeExactly '~/foo'
It '~ should not be replaced when quoted' {
cmd /c echo '~' | Should -BeExactly '~'
cmd /c echo "~" | Should -BeExactly '~'
cmd /c echo '~/foo' | Should -BeExactly '~/foo'
cmd /c echo "~/foo" | Should -BeExactly '~/foo'
cmd /c echo '~\foo' | Should -BeExactly '~\foo'
cmd /c echo "~\foo" | Should -BeExactly '~\foo'
}
cmd /c echo "~\foo" | Should -BeExactly '~\foo'
}
}
@@ -244,44 +244,30 @@ Describe "Set-Variable" -Tags "CI" {
Context "Set-Variable -Append tests" {
BeforeAll {
if (! (Get-ExperimentalFeature PSRedirectToVariable).Enabled) {
$skipTest = $true
}
$testCases = @{ value = 2; Count = 2 },
@{ value = @(2,3,4); Count = 2},
@{ value = "abc",(Get-Process -Id $PID) ; count = 2}
$testCases = @{ value = 2; Count = 2 },
@{ value = @(2,3,4); Count = 2},
@{ value = "abc",(Get-Process -Id $PID) ; count = 2}
}
It "Can append values <value> to a variable" -testCases $testCases {
param ($value, $count)
It "Can append values <value> to a variable" -testCases $testCases {
param ($value, $count)
if ($skipTest) {
Set-ItResult -skip -because "Experimental Feature PSRedirectToVariable not enabled"
return
}
$variableName = "testVar"
Set-Variable -Name $variableName -Value 1
Set-Variable -Name $variableName -Value $value -Append
$variableName = "testVar"
Set-Variable -Name $variableName -Value 1
Set-Variable -Name $variableName -Value $value -Append
$observedValues = Get-Variable $variableName -Value
$observedValues = Get-Variable $variableName -Value
$observedValues.Count | Should -Be $count
$observedValues[0] | Should -Be 1
$observedValues.Count | Should -Be $count
$observedValues[0] | Should -Be 1
$observedValues[1] | Should -Be $value
}
$observedValues[1] | Should -Be $value
}
It "Can use set-variable via streaming and append values" {
if ($skipTest) {
Set-ItResult -skip -because "Experimental Feature PSRedirectToVariable not enabled"
return
}
$testVar = 1
4..6 | Set-Variable -Name testVar -Append
$testVar | Should -Be @(1,4,5,6)
}
It "Can use set-variable via streaming and append values" {
$testVar = 1
4..6 | Set-Variable -Name testVar -Append
$testVar | Should -Be @(1,4,5,6)
}
}
}
@@ -337,6 +337,7 @@ Describe "Verify aliases and cmdlets" -Tags "CI" {
"Cmdlet", "Get-PSSessionCapability", "", $($FullCLR -or $CoreWindows ), "", "", "None"
"Cmdlet", "Get-PSSessionConfiguration", "", $($FullCLR -or $CoreWindows ), "", "", "None"
"Cmdlet", "Get-PSSnapin", "", $($FullCLR ), "", "", ""
"Cmdlet", "Get-PSSubsystem", "", $( $CoreWindows -or $CoreUnix), "", "", "None"
"Cmdlet", "Get-Random", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
"Cmdlet", "Get-Runspace", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
"Cmdlet", "Get-RunspaceDebug", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
-3
View File
@@ -1,9 +1,6 @@
{
"ExperimentalFeatures": {
"ExpTest.FeatureOne": [ "test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1" ],
"PSCultureInvariantReplaceOperator": [ "test/powershell/Language/Operators/ReplaceOperator.Tests.ps1" ],
"Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace": [ "test/powershell/Modules/Microsoft.PowerShell.Utility/RunspaceBreakpointManagement.Tests.ps1" ],
"PSNativeWindowsTildeExpansion": [ "test/powershell/Language/Scripting/NativeExecution/NativeWindowsTildeExpansion.Tests.ps1" ],
"PSSerializeJSONLongEnumAsNumber": [ "test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.PSSerializeJSONLongEnumAsNumber.Tests.ps1" ]
}
}