Skip to content

Commit

Permalink
Merge pull request #2 from SeeminglyScience/add-powershell-core-support
Browse files Browse the repository at this point in the history
Add support for PowerShell Core beta
  • Loading branch information
SeeminglyScience authored Aug 2, 2017
2 parents 9dc2edd + acab246 commit 051c336
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 14 deletions.
5 changes: 3 additions & 2 deletions ImpliedReflection.build.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#requires -Module InvokeBuild, PSScriptAnalyzer, Pester, PlatyPS -Version 5.1
#requires -Module @{ModuleName = 'Pester'; RequiredVersion = '3.4.3'}, InvokeBuild, PSScriptAnalyzer, PlatyPS -Version 5.1
[CmdletBinding()]
param()

Expand Down Expand Up @@ -58,7 +58,8 @@ task Test -If { $script:Discovery.HasTests -and $script:Settings.ShouldTest } {
$pesterCC = "$PSScriptRoot\module\*\*.ps1", "$PSScriptRoot\module\*.psm1"
Start-Job {
Set-Location $using:projectRoot
Invoke-Pester -PesterOption @{ IncludeVSCodeMarker = $true } -CodeCoverage $using:pesterCC

Invoke-Pester -CodeCoverage $using:pesterCC -PesterOption @{ IncludeVSCodeMarker = $true }
} | Receive-Job -Wait -AutoRemoveJob
}

Expand Down
4 changes: 2 additions & 2 deletions module/ImpliedReflection.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RootModule = 'ImpliedReflection.psm1'

# Version number of this module.
ModuleVersion = '0.1.1'
ModuleVersion = '0.1.2'

# ID used to uniquely identify this module
GUID = '8834a5bf-9bf2-4f09-8415-3c1e561109f6'
Expand Down Expand Up @@ -80,7 +80,7 @@ PrivateData = @{
# IconUri = ''

# ReleaseNotes of this module
ReleaseNotes = '- Fixed the module not loading.'
ReleaseNotes = '- Added support for PowerShell 6.0 beta 4.'

} # End of PSData hashtable

Expand Down
17 changes: 17 additions & 0 deletions module/ImpliedReflection.psm1
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
Import-LocalizedData -BindingVariable Strings -FileName Strings -ErrorAction Ignore

# In PowerShell 6 a lot of field names are changed to fit .NET standards. This is why you should
# avoid using reflection :)
$instancePrefix = ''
if ($PSVersionTable.PSVersion.Major -ge 6) {
$instancePrefix = '_'
}
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '',
Justification='Module scope variable used in other files.')]
$FIELD_REFERENCE = @{
adapter = "${instancePrefix}adapter"
indexes = "${instancePrefix}indexes"
# These haven't been changed yet, but probably will soon. Keeping it here so it's easy to fix.
dotNetStaticAdapter = 'dotNetStaticAdapter'
readOnly = 'readOnly'
writeOnly = 'writeOnly'
}

# Include all function files.
Get-ChildItem $PSScriptRoot\Public\*.ps1 | ForEach-Object {
. $PSItem.FullName
Expand Down
12 changes: 6 additions & 6 deletions module/Public/Add-PrivateMember.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ function Add-PrivateMember {
function NewPropertyCacheEntry([MemberInfo] $property) {
$cacheEntry = [ref].Assembly.
GetType('System.Management.Automation.DotNetAdapter+PropertyCacheEntry').
GetConstructor(60, $null, @($property.GetType()), 1).
GetConstructor($FLAG_MAP.Instance, $null, @($property.GetType()), 1).
Invoke($property)

# The cache entry uses these fields to determine if the properties for the
# Getter/Setter delegates should create the delegate. They are set to false during
# construction if the method isn't public.
$cacheEntry.GetType().GetField('writeOnly', 60).SetValue($cacheEntry, $false)
$cacheEntry.GetType().GetField($script:FIELD_REFERENCE.writeOnly, 60).SetValue($cacheEntry, $false)
$isWritable = $property.SetMethod -or
('Field' -eq $property.MemberType -and
-not $property.IsInitOnly)

if ($isWritable) {
$cacheEntry.GetType().GetField('readOnly', 60).SetValue($cacheEntry, $false)
$cacheEntry.GetType().GetField($script:FIELD_REFERENCE.readOnly, 60).SetValue($cacheEntry, $false)
}
return $cacheEntry
}
Expand Down Expand Up @@ -128,7 +128,7 @@ function Add-PrivateMember {
Type = $target.psobject.BaseObject
Flags = $FLAG_MAP.Static
Adapter = [psobject].
GetField('dotNetStaticAdapter', $FLAG_MAP.Static).
GetField($script:FIELD_REFERENCE.dotNetStaticAdapter, $FLAG_MAP.Static).
GetValue($null)
}
}
Expand All @@ -137,7 +137,7 @@ function Add-PrivateMember {
Type = $target.GetType()
Flags = $FLAG_MAP.Instance
Adapter = [PSMethod].
GetField('adapter', $FLAG_MAP.Instance).
GetField($script:FIELD_REFERENCE.adapter, $FLAG_MAP.Instance).
GetValue($target.psobject.Methods.Item('GetType'))
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@ function Add-PrivateMember {

$alreadyExists = $table.
GetType().
GetField('indexes', $FLAG_MAP.Instance).
GetField($script:FIELD_REFERENCE.indexes, $FLAG_MAP.Instance).
GetValue($table).
ContainsKey($memberName)

Expand Down
6 changes: 5 additions & 1 deletion module/Public/Disable-ImpliedReflection.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ function Disable-ImpliedReflection {
[ErrorCategory]::InvalidOperation,
$null))
}
$fieldPrefix = ''
if ($PSVersionTable.PSVersion.Major -ge 6) {
$fieldPrefix = 's_'
}
foreach ($visibilityScope in 'static', 'instance') {
foreach ($memberType in 'Property', 'Method') {
[ref].Assembly.
GetType('System.Management.Automation.DotNetAdapter').
GetField("${visibilityScope}${memberType}CacheTable", [BindingFlags]'Static, NonPublic').
GetField("${fieldPrefix}${visibilityScope}${memberType}CacheTable", [BindingFlags]'Static, NonPublic').
GetValue($null).
Clear()
}
Expand Down
20 changes: 17 additions & 3 deletions test/Add-PrivateMember.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,15 @@ Describe 'Add-PrivateMember operation' {
$ExecutionContext._context._formatDBManager | Should Be $null
}
It 'can chain with return property parameter' {
# More examples of why not to use reflection.
$moduleTable = '_moduleTable'
if ($PSVersionTable.PSVersion.Major -ge 6) {
$moduleTable = 'ModuleTable'
}
$ExecutionContext |
Add-PrivateMember _context |
Add-PrivateMember Modules |
Add-PrivateMember _moduleTable |
Add-PrivateMember $moduleTable |
Should BeOfType 'System.Collections.Generic.Dictionary[string,psmoduleinfo]'
}
It 'returns the object with PassThru' {
Expand All @@ -57,13 +62,22 @@ Describe 'Add-PrivateMember operation' {
[scriptblock]::EmptyScriptBlock | Should BeOfType scriptblock
}
It 'can access fields' {
[scriptblock]::_cachedScripts.GetType().Name | Should Be 'ConcurrentDictionary`2'
if ($PSVersionTable.PSVersion.Major -ge 6) {
[scriptblock]::s_cachedScripts.GetType().Name | Should Be 'ConcurrentDictionary`2'
} else {
[scriptblock]::_cachedScripts.GetType().Name | Should Be 'ConcurrentDictionary`2'
}
}
It 'can access methods' {
[scriptblock]::TokenizeWordElements('one two three') | Should Be 'one','two','three'
}
It 'added methods are the correct type' {
[scriptblock]::BindArgumentsForScripblockInvoke |
# Always wondered if this misspelling was for some reason on purpose.
$methodName = 'BindArgumentsForScripBlockInvoke'
if ($PSVersionTable.PSVersion.Major -ge 6) {
$methodName = 'BindArgumentsForScriptBlockInvoke'
}
[scriptblock]::$methodName |
Should BeOfType 'System.Management.Automation.PSMethod'
}
}
Expand Down

0 comments on commit 051c336

Please sign in to comment.