mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Push locals of automatic variables to 'DottedScopes' when dotting script cmdlets (#4709)
When dotting a script cmdlet, the locals of automatic variables from the `PSScriptCmdlet` is not set up in the current scope before parameter binding. The fix is to push the locals in `CommandProcessor.OnSetCurrentScope` and pop them in `CommandProcessor.OnRestorePreviousScope`, which will be called from `SetCurrentScopeToExecutionScope` and `RestorePreviousScope` respectively. Summary of changes: 1. When a new local scope is used, currently we set the locals for `CommandProcessor` right before parameter binding (in `BindCommandLineParametersNoValidation`); we set the locals for `ScriptCommandProcessor` in `Prepare`. I moved both to the constructor, right after the new scope is created so that the code is more consistent. 2. In `CmdletParameterBinderController.cs`, we set up the `PSBoundParameters` and `MyInvocation` variables in `HandleCommandLineDynamicParameters` again, which I think is unnecessary because this method is only called from `BindCommandLineParametersNoValidation`, where the setup is done for the first time. 3. Currently, the locals will be set for dotted script cmdlet in `EnterScope()` and `ExitScope()`. Now, that logic is moved to `OnSetCurrentScope` and `OnRestorePreviousScope` of `CommandProcessor`. This not only makes sure that locals are set before parameter binding, but also is consistent with the `ScriptCommandProcessor`.
This commit is contained in:
@@ -280,4 +280,53 @@
|
||||
$_.Exception.Message | should match "Parameter2"
|
||||
}
|
||||
}
|
||||
|
||||
Context "Use automatic variables as default value for parameters" {
|
||||
BeforeAll {
|
||||
## Explicit use of 'CmdletBinding' make it a script cmdlet
|
||||
$test1 = @'
|
||||
[CmdletBinding()]
|
||||
param ($Root = $PSScriptRoot)
|
||||
"[$Root]"
|
||||
'@
|
||||
## Use of 'Parameter' implicitly make it a script cmdlet
|
||||
$test2 = @'
|
||||
param (
|
||||
[Parameter()]
|
||||
$Root = $PSScriptRoot
|
||||
)
|
||||
"[$Root]"
|
||||
'@
|
||||
$tempDir = Join-Path -Path $TestDrive -ChildPath "DefaultValueTest"
|
||||
$test1File = Join-Path -Path $tempDir -ChildPath "test1.ps1"
|
||||
$test2File = Join-Path -Path $tempDir -ChildPath "test2.ps1"
|
||||
|
||||
$expected = "[$tempDir]"
|
||||
$psPath = "$PSHOME\powershell"
|
||||
|
||||
$null = New-Item -Path $tempDir -ItemType Directory -Force
|
||||
Set-Content -Path $test1File -Value $test1 -Force
|
||||
Set-Content -Path $test2File -Value $test2 -Force
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It "Test dot-source should evaluate '`$PSScriptRoot' for parameter default value" {
|
||||
$result = . $test1File
|
||||
$result | Should Be $expected
|
||||
|
||||
$result = . $test2File
|
||||
$result | Should Be $expected
|
||||
}
|
||||
|
||||
It "Test 'powershell -File' should evaluate '`$PSScriptRoot' for parameter default value" {
|
||||
$result = & $psPath -NoProfile -File $test1File
|
||||
$result | Should Be $expected
|
||||
|
||||
$result = & $psPath -NoProfile -File $test2File
|
||||
$result | Should Be $expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user