You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I use strict mode religiously in pretty much every module and script I create. This helps me identify bugs that may otherwise not be apparent until after I ship the module or script, and it encourages me to write more robust code.
For the modules I publish (and I'll focus on modules since I don't publish many scripts), I simply invoke Set-PSStrictMode -Version Latest at the top of the psm1 file, knowing that it sets me up for strict mode throughout my module. Unfortunately this dependency means I would be against the Change Set-StrictMode alternate proposal because I would have to redo every module I have in order to get the same benefit I get today.
It sounds to me like the goal here is to be able to invoke other PowerShell code that isn't designed to run in strict mode without generating errors while still getting the benefits of strict mode in your own code. I don't think lexical strict mode is the right way to provide this. Instead, maybe it would be better to provide syntax allowing people who use strict mode to be able to easily invoke other PowerShell logic with strict mode disabled/lowered to another level without affecting the rest of their code. That leaves Set-StrictMode working as it does today, as well as Set-StrictMode -Off, both of which are really easy to use, as well as for those scenarios where you're calling into code that you don't manage (and that therefore may not support strict mode). With that, I have another alternate proposal.
Alternate Proposal
Extend Set-StrictMode
Add an additional optional ScriptBlock parameter to Set-StrictMode, as follows:
When invoking Set-StrictMode using the first parameter set without the optional -ScriptBlock parameter, it would function exactly as it does today. If, however, you passed in a ScriptBlock to the optional -ScriptBlock parameter, the command would store the current strict-mode level, set the strict-mode level to the requested level, invoke the script block in the current scope, and then reset the strict-mode level back to the original level.
The second parameter set would function in a similar fashion. Without the optional -ScriptBlock parameter, Set-StrictMode -Off would turn strict mode off in the current scope. With the optional -ScriptBlock parameter included, Set-StrictMode would store the current strict mode level, turn strict mode off, invoke the script block in the current scope, and then reset strict-mode back to the state (off or a specific level) it was in before the script block was invoked.
This proposal doesn't introduce new syntax other than an additional parameter on Set-StrictMode. It allows Set-StrictMode to function as it does today while also allowing script/module authors familiar with Set-StrictMode to be able to temporarily set the level they want within a script block they are about to invoke, so that they can call commands or script blocks that are not ready for strict mode without issue.
Good feedback here. One thing that we want to be clear about is that we're not changing the existing behavior of Set-StrictMode but adding new behavior with the using strict syntax. Bruce Payette (@BrucePay): "I wanted to be clear the former happens at runtime while the latter happens at parse-time."
The reason that using strict is useful is because it won't impose strict mode on code outside your lexical block (e.g. outside of a script scope), so you can validate that your code is strict mode clean without worrying about the behavior of other modules, scripts, or functions.
Kirk Munro (@KirkMunro) Given the above, can you explain why you're interested in the negative case of dropping out of strict mode for a single script block? In what scenario is this useful?
Open items:
Scenario for "negative case"
Concern that using (as opposed to #using) will break on older versions of PS
The most common negative case scenario is that you put Set-StrictMode -Version latest at the top of the script but then selectively disable it in certain tiny regions of code to treat non-existent property access as benign.
Without Set-StrictMode -Off here, you have to resort to working around it with if ($null -ne $obj.psobject.Members.Item('Foo')) { $obj.Foo } which is chatty, error prone, and orders of magnitude slower.
If PowerShell had a pseudo "keyword member" construct like $obj.Foo.-or($null) that ran approximately the same speed as $obj.Foo with unstrict property access, it wouldn't be so bad.
WRT DerpMcDerp's comment, we should probably add support for the null-coalescing operator.?? and other "null-conditional operators" like the ?. operator from C#. See https://msdn.microsoft.com/en-us/library/dn986595.aspx Doing this should allow users to work around most of the "problems" introduced by the runtime Strict-Mode.
Reacted by Kirk Munro, Joel Bennett, Michael Klement and gaelcolas
Joey Aiello (@joeyaiello) I was misunderstanding the intent. My comments were based on thinking it would just happen at runtime. The suggestions Bruce Payette (@BrucePay) made about having strict checking at parse time would be great, as would null-coalescing and null-conditional operators (as would the conditional ?: operator while you're at it).
With this idea being about parse-time checking though, I guess I'm a confused by the idea of enabling parse-time checking for certain issues that are ignored by default by modifying the file itself. In my mind, that's more of an IDE feature where you can throttle the warning level used during compilation. If you have to put it in the file though, my preference would be for #using over using. Otherwise it will just be a feature that either (a) sits on the shelf for a long time or (b) one that I create an extension for (VS Code or ISE) to remove the using statement before shipping for downlevel versions.
@PowerShell/powershell-committee talked some more. We agreed that there is value in having a parse-time check (fail fast, ability to do more parse time checks, etc.), but those don't seem to help with the motivation outlined in the RFC (namely, that calling other people's scripts which fail strict mode won't be impacted by setting strict mode from within a script/module).
We had additional discussion and disagreement around whether the original motivation should be addressed as a new parameter on Set-StrictMode vs. using strict. Ultimately though, we agree with Jason Shirk (@lzybkr) 's point about complexity, and don't think that we should implement this within Set-StrictMode.
Given that, the next steps on this RFC should be to extend the motivations to address the additional benefits of a parse-time using strict.
Setting this as up-for-grabs assuming that anyone who is interested will speak with us first to make sure that their implementation will meet our discussion's requirements per the above.
Activity
KirkMunro commentedon Feb 27, 2016
I use strict mode religiously in pretty much every module and script I create. This helps me identify bugs that may otherwise not be apparent until after I ship the module or script, and it encourages me to write more robust code.
For the modules I publish (and I'll focus on modules since I don't publish many scripts), I simply invoke Set-PSStrictMode -Version Latest at the top of the psm1 file, knowing that it sets me up for strict mode throughout my module. Unfortunately this dependency means I would be against the Change Set-StrictMode alternate proposal because I would have to redo every module I have in order to get the same benefit I get today.
It sounds to me like the goal here is to be able to invoke other PowerShell code that isn't designed to run in strict mode without generating errors while still getting the benefits of strict mode in your own code. I don't think lexical strict mode is the right way to provide this. Instead, maybe it would be better to provide syntax allowing people who use strict mode to be able to easily invoke other PowerShell logic with strict mode disabled/lowered to another level without affecting the rest of their code. That leaves Set-StrictMode working as it does today, as well as Set-StrictMode -Off, both of which are really easy to use, as well as for those scenarios where you're calling into code that you don't manage (and that therefore may not support strict mode). With that, I have another alternate proposal.
Alternate Proposal
Extend Set-StrictMode
Add an additional optional ScriptBlock parameter to Set-StrictMode, as follows:
When invoking Set-StrictMode using the first parameter set without the optional -ScriptBlock parameter, it would function exactly as it does today. If, however, you passed in a ScriptBlock to the optional -ScriptBlock parameter, the command would store the current strict-mode level, set the strict-mode level to the requested level, invoke the script block in the current scope, and then reset the strict-mode level back to the original level.
The second parameter set would function in a similar fashion. Without the optional -ScriptBlock parameter, Set-StrictMode -Off would turn strict mode off in the current scope. With the optional -ScriptBlock parameter included, Set-StrictMode would store the current strict mode level, turn strict mode off, invoke the script block in the current scope, and then reset strict-mode back to the state (off or a specific level) it was in before the script block was invoked.
This proposal doesn't introduce new syntax other than an additional parameter on Set-StrictMode. It allows Set-StrictMode to function as it does today while also allowing script/module authors familiar with Set-StrictMode to be able to temporarily set the level they want within a script block they are about to invoke, so that they can call commands or script blocks that are not ready for strict mode without issue.
nightroman commentedon Feb 27, 2016
Just a thought.
can be done as
so that it can be used in later versions without breaking earlier versions.
[-]RFC003-Lexical-Strict-Mode comments[/-][+]RFC0003-Lexical-Strict-Mode comments[/+]joeyaiello commentedon Mar 25, 2016
Good feedback here. One thing that we want to be clear about is that we're not changing the existing behavior of Set-StrictMode but adding new behavior with the
using strictsyntax. Bruce Payette (@BrucePay): "I wanted to be clear the former happens at runtime while the latter happens at parse-time."The reason that
using strictis useful is because it won't impose strict mode on code outside your lexical block (e.g. outside of a script scope), so you can validate that your code is strict mode clean without worrying about the behavior of other modules, scripts, or functions.Kirk Munro (@KirkMunro) Given the above, can you explain why you're interested in the negative case of dropping out of strict mode for a single script block? In what scenario is this useful?
Open items:
using(as opposed to#using) will break on older versions of PSDerpMcDerp commentedon Mar 25, 2016
The most common negative case scenario is that you put
Set-StrictMode -Version latestat the top of the script but then selectively disable it in certain tiny regions of code to treat non-existent property access as benign.Without
Set-StrictMode -Offhere, you have to resort to working around it withif ($null -ne $obj.psobject.Members.Item('Foo')) { $obj.Foo }which is chatty, error prone, and orders of magnitude slower.If PowerShell had a pseudo "keyword member" construct like
$obj.Foo.-or($null)that ran approximately the same speed as$obj.Foowith unstrict property access, it wouldn't be so bad.BrucePay commentedon Apr 1, 2016
WRT DerpMcDerp's comment, we should probably add support for the null-coalescing operator.?? and other "null-conditional operators" like the ?. operator from C#. See https://msdn.microsoft.com/en-us/library/dn986595.aspx Doing this should allow users to work around most of the "problems" introduced by the runtime Strict-Mode.
KirkMunro commentedon Apr 1, 2016
Joey Aiello (@joeyaiello) I was misunderstanding the intent. My comments were based on thinking it would just happen at runtime. The suggestions Bruce Payette (@BrucePay) made about having strict checking at parse time would be great, as would null-coalescing and null-conditional operators (as would the conditional ?: operator while you're at it).
With this idea being about parse-time checking though, I guess I'm a confused by the idea of enabling parse-time checking for certain issues that are ignored by default by modifying the file itself. In my mind, that's more of an IDE feature where you can throttle the warning level used during compilation. If you have to put it in the file though, my preference would be for #using over using. Otherwise it will just be a feature that either (a) sits on the shelf for a long time or (b) one that I create an extension for (VS Code or ISE) to remove the using statement before shipping for downlevel versions.
joeyaiello commentedon Nov 12, 2018
@PowerShell/powershell-committee has been working to drive down our RFC debt. Here are the notes that resulted out a meeting on this one:
Set-StrictModeinstead of usingusingSet-StrictMode -Offshould turn off whatever strict mode is enabledglobal strict mode above them
Set-StrictMode -Lexicalat the top of a.psm1but we don't have any great ideas
-NoInheritance?-Lexical?lzybkr commentedon Nov 12, 2018
To be clear here - my proposal was for parse time checks. Is the @PowerShell/powershell-committee thinking lexical checking should occur at runtime?
Runtime checks have definite downsides:
joeyaiello commentedon Nov 14, 2018
@PowerShell/powershell-committee talked some more. We agreed that there is value in having a parse-time check (fail fast, ability to do more parse time checks, etc.), but those don't seem to help with the motivation outlined in the RFC (namely, that calling other people's scripts which fail strict mode won't be impacted by setting strict mode from within a script/module).
We had additional discussion and disagreement around whether the original motivation should be addressed as a new parameter on
Set-StrictModevs.using strict. Ultimately though, we agree with Jason Shirk (@lzybkr) 's point about complexity, and don't think that we should implement this withinSet-StrictMode.Given that, the next steps on this RFC should be to extend the motivations to address the additional benefits of a parse-time
using strict.mklement0 commentedon Feb 12, 2019
Derp McDerp (@DerpMcDerp): Good point re selective bypassing of strict-mode checks; there's now a feature request to implement the null-conditional (null-soaking) feature (and others) that Bruce Payette (@BrucePay) references: PowerShell/PowerShell#3240
joeyaiello commentedon Mar 25, 2019
Setting this as up-for-grabs assuming that anyone who is interested will speak with us first to make sure that their implementation will meet our discussion's requirements per the above.