From f1afe2b48d7ccecceac27028c17d86e5fc9f9bbd Mon Sep 17 00:00:00 2001 From: Aaron Jensen Date: Mon, 4 Aug 2025 10:27:00 -0700 Subject: [PATCH 1/3] fix: ps1 scripts in powershell 5.1 (#8469) Fixes issue #8468: npm.ps1 and npx.ps1 fail on Windows PowerShell 5.1 when run in strict mode. --- bin/npm.ps1 | 4 +++- bin/npx.ps1 | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/npm.ps1 b/bin/npm.ps1 index 5993adaf55662..4e4aaa78c87ca 100644 --- a/bin/npm.ps1 +++ b/bin/npm.ps1 @@ -1,5 +1,7 @@ #!/usr/bin/env pwsh +Set-StrictMode -Version 'Latest' + $NODE_EXE="$PSScriptRoot/node.exe" if (-not (Test-Path $NODE_EXE)) { $NODE_EXE="$PSScriptRoot/node" @@ -27,7 +29,7 @@ if ($MyInvocation.ExpectingInput) { # takes pipeline input } elseif (-not $MyInvocation.Line) { # used "-File" argument & $NODE_EXE $NPM_CLI_JS $args } else { # used "-Command" argument - if ($MyInvocation.Statement) { + if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { $NPM_ORIGINAL_COMMAND = $MyInvocation.Statement } else { $NPM_ORIGINAL_COMMAND = ( diff --git a/bin/npx.ps1 b/bin/npx.ps1 index cc1aa047bdc21..05c76825e0d01 100644 --- a/bin/npx.ps1 +++ b/bin/npx.ps1 @@ -1,5 +1,7 @@ #!/usr/bin/env pwsh +Set-StrictMode -Version 'Latest' + $NODE_EXE="$PSScriptRoot/node.exe" if (-not (Test-Path $NODE_EXE)) { $NODE_EXE="$PSScriptRoot/node" @@ -27,7 +29,7 @@ if ($MyInvocation.ExpectingInput) { # takes pipeline input } elseif (-not $MyInvocation.Line) { # used "-File" argument & $NODE_EXE $NPX_CLI_JS $args } else { # used "-Command" argument - if ($MyInvocation.Statement) { + if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { $NPX_ORIGINAL_COMMAND = $MyInvocation.Statement } else { $NPX_ORIGINAL_COMMAND = ( From 4c0969aad143ee1f3619a30bcaab3219edfdf373 Mon Sep 17 00:00:00 2001 From: Alex Schwartz Date: Thu, 28 Aug 2025 12:40:01 -0400 Subject: [PATCH 2/3] fix(powershell): fix issue with modified InvocationName (#8532) Fixes https://github.com/npm/cli/issues/8528 --- bin/npm.ps1 | 2 +- bin/npx.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/npm.ps1 b/bin/npm.ps1 index 4e4aaa78c87ca..e18a672625354 100644 --- a/bin/npm.ps1 +++ b/bin/npm.ps1 @@ -26,7 +26,7 @@ if (Test-Path $NPM_PREFIX_NPM_CLI_JS) { if ($MyInvocation.ExpectingInput) { # takes pipeline input $input | & $NODE_EXE $NPM_CLI_JS $args -} elseif (-not $MyInvocation.Line) { # used "-File" argument +} elseif (-not $MyInvocation.Line -or $MyInvocation.InvocationName -in '&', '.') { # used "-File" argument & $NODE_EXE $NPM_CLI_JS $args } else { # used "-Command" argument if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { diff --git a/bin/npx.ps1 b/bin/npx.ps1 index 05c76825e0d01..60ba47ba39641 100644 --- a/bin/npx.ps1 +++ b/bin/npx.ps1 @@ -26,7 +26,7 @@ if (Test-Path $NPM_PREFIX_NPX_CLI_JS) { if ($MyInvocation.ExpectingInput) { # takes pipeline input $input | & $NODE_EXE $NPX_CLI_JS $args -} elseif (-not $MyInvocation.Line) { # used "-File" argument +} elseif (-not $MyInvocation.Line -or $MyInvocation.InvocationName -in '&', '.') { # used "-File" argument & $NODE_EXE $NPX_CLI_JS $args } else { # used "-Command" argument if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { From b62da5a31f6b28f4ea04123e41ec4e462faacc42 Mon Sep 17 00:00:00 2001 From: Alex Schwartz Date: Tue, 2 Sep 2025 17:53:55 -0400 Subject: [PATCH 3/3] fix(powershell): improve argument parsing (#8539) improve the argument parsing PS1 logic - support `& npm args` and `. npm args` properly - support syntax such as `C:\"Program Files"\nodejs\npm.ps1 args` **of course ^ for both npm and npx version of the script** Code Explanation: instead of getting the `CommandElements.Extent.Text` array and joining it with spaces right away, now it's getting the same array and only capturing everything after the first element --- bin/npm.ps1 | 8 ++++---- bin/npx.ps1 | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/npm.ps1 b/bin/npm.ps1 index e18a672625354..efed03fe5655e 100644 --- a/bin/npm.ps1 +++ b/bin/npm.ps1 @@ -26,7 +26,7 @@ if (Test-Path $NPM_PREFIX_NPM_CLI_JS) { if ($MyInvocation.ExpectingInput) { # takes pipeline input $input | & $NODE_EXE $NPM_CLI_JS $args -} elseif (-not $MyInvocation.Line -or $MyInvocation.InvocationName -in '&', '.') { # used "-File" argument +} elseif (-not $MyInvocation.Line) { # used "-File" argument & $NODE_EXE $NPM_CLI_JS $args } else { # used "-Command" argument if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { @@ -40,9 +40,9 @@ if ($MyInvocation.ExpectingInput) { # takes pipeline input $NODE_EXE = $NODE_EXE.Replace("``", "````") $NPM_CLI_JS = $NPM_CLI_JS.Replace("``", "````") - $NPM_NO_REDIRECTS_COMMAND = [Management.Automation.Language.Parser]::ParseInput($NPM_ORIGINAL_COMMAND, [ref] $null, [ref] $null). - EndBlock.Statements.PipelineElements.CommandElements.Extent.Text -join ' ' - $NPM_ARGS = $NPM_NO_REDIRECTS_COMMAND.Substring($MyInvocation.InvocationName.Length).Trim() + $NPM_COMMAND_ARRAY = [Management.Automation.Language.Parser]::ParseInput($NPM_ORIGINAL_COMMAND, [ref] $null, [ref] $null). + EndBlock.Statements.PipelineElements.CommandElements.Extent.Text + $NPM_ARGS = ($NPM_COMMAND_ARRAY | Select-Object -Skip 1) -join ' ' Invoke-Expression "& `"$NODE_EXE`" `"$NPM_CLI_JS`" $NPM_ARGS" } diff --git a/bin/npx.ps1 b/bin/npx.ps1 index 60ba47ba39641..3fe7b5435763a 100644 --- a/bin/npx.ps1 +++ b/bin/npx.ps1 @@ -26,7 +26,7 @@ if (Test-Path $NPM_PREFIX_NPX_CLI_JS) { if ($MyInvocation.ExpectingInput) { # takes pipeline input $input | & $NODE_EXE $NPX_CLI_JS $args -} elseif (-not $MyInvocation.Line -or $MyInvocation.InvocationName -in '&', '.') { # used "-File" argument +} elseif (-not $MyInvocation.Line) { # used "-File" argument & $NODE_EXE $NPX_CLI_JS $args } else { # used "-Command" argument if (($MyInvocation | Get-Member -Name 'Statement') -and $MyInvocation.Statement) { @@ -40,9 +40,9 @@ if ($MyInvocation.ExpectingInput) { # takes pipeline input $NODE_EXE = $NODE_EXE.Replace("``", "````") $NPX_CLI_JS = $NPX_CLI_JS.Replace("``", "````") - $NPX_NO_REDIRECTS_COMMAND = [Management.Automation.Language.Parser]::ParseInput($NPX_ORIGINAL_COMMAND, [ref] $null, [ref] $null). - EndBlock.Statements.PipelineElements.CommandElements.Extent.Text -join ' ' - $NPX_ARGS = $NPX_NO_REDIRECTS_COMMAND.Substring($MyInvocation.InvocationName.Length).Trim() + $NPX_COMMAND_ARRAY = [Management.Automation.Language.Parser]::ParseInput($NPX_ORIGINAL_COMMAND, [ref] $null, [ref] $null). + EndBlock.Statements.PipelineElements.CommandElements.Extent.Text + $NPX_ARGS = ($NPX_COMMAND_ARRAY | Select-Object -Skip 1) -join ' ' Invoke-Expression "& `"$NODE_EXE`" `"$NPX_CLI_JS`" $NPX_ARGS" }