-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2108d3f
commit d7683d3
Showing
22 changed files
with
592 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import C_BINDINGS_MODULE | ||
|
||
internal let IID_IWeakReference: IID = IID(Data1: 0x00000037, Data2: 0x0000, Data3: 0x0000, Data4: (0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)) // 00000037-0000-0000-C000-000000000046 | ||
|
||
fileprivate extension IUnknownRef { | ||
func copyTo(_ riid: REFIID?, _ ppvObj: UnsafeMutablePointer<LPVOID?>?) -> HRESULT { | ||
self.borrow.pointee.lpVtbl.pointee.QueryInterface(self.borrow, riid, ppvObj) | ||
} | ||
} | ||
|
||
func makeWeakReference(_ object: AnyObject, _ result: UnsafeMutablePointer<UnsafeMutableRawPointer?>) throws { | ||
let wrapper = WeakReferenceWrapper(WeakReference(object)) | ||
try wrapper.toABI { | ||
_ = $0.pointee.lpVtbl.pointee.AddRef($0) | ||
result.pointee = UnsafeMutableRawPointer($0) | ||
} | ||
} | ||
|
||
fileprivate class WeakReference { | ||
public weak var target: AnyObject? | ||
public init(_ target: AnyObject) { | ||
self.target = target | ||
} | ||
} | ||
|
||
fileprivate class WeakReferenceWrapper: WinRTAbiBridgeWrapper<IWeakReferenceBridge> { | ||
init(_ weakReference: WeakReference){ | ||
super.init(IWeakReferenceBridge.makeAbi(), weakReference) | ||
} | ||
|
||
internal static func queryInterface(_ pUnk: UnsafeMutablePointer<C_IInspectable>?, _ riid: UnsafePointer<SUPPORT_MODULE.IID>?, _ ppvObject: UnsafeMutablePointer<UnsafeMutableRawPointer?>?) -> HRESULT { | ||
guard let pUnk, let riid, let ppvObject else { return E_INVALIDARG } | ||
switch riid.pointee { | ||
case IID_IWeakReference: | ||
_ = pUnk.pointee.lpVtbl.pointee.AddRef(pUnk) | ||
return S_OK | ||
default: | ||
guard let obj = WeakReferenceWrapper.tryUnwrapFromBase(raw: pUnk) else { return E_NOINTERFACE } | ||
let anyWrapper = __ABI_.AnyWrapper(obj)! | ||
return __ABI_.AnyWrapper.queryInterface(try! anyWrapper.toABI { $0 }, riid, ppvObject) | ||
} | ||
} | ||
} | ||
|
||
fileprivate enum IWeakReferenceBridge: AbiBridge { | ||
typealias CABI = C_IWeakReference | ||
typealias SwiftProjection = WeakReference | ||
|
||
static func makeAbi() -> C_IWeakReference { | ||
return C_IWeakReference(lpVtbl: &IWeakReferenceVTable) | ||
} | ||
|
||
static func from(abi: ComPtr<C_IWeakReference>?) -> WeakReference? { | ||
fatalError("Not needed") | ||
} | ||
} | ||
|
||
fileprivate var IWeakReferenceVTable: C_IWeakReferenceVtbl = .init( | ||
QueryInterface: { WeakReferenceWrapper.queryInterface($0, $1, $2) }, | ||
AddRef: { WeakReferenceWrapper.addRef($0) }, | ||
Release: { WeakReferenceWrapper.release($0) }, | ||
Resolve: { Resolve($0, $1, $2) } | ||
) | ||
|
||
fileprivate func Resolve( | ||
_ this: UnsafeMutablePointer<C_IWeakReference>?, | ||
_ riid: UnsafePointer<GUID_Workaround>?, | ||
_ ppvObject: UnsafeMutablePointer<UnsafeMutablePointer<C_IInspectable>?>?) -> HRESULT { | ||
guard let this, let riid, let ppvObject else { return E_INVALIDARG } | ||
guard let weakReference = WeakReferenceWrapper.tryUnwrapFrom(abi: ComPtr(this)) else { return E_FAIL } | ||
ppvObject.pointee = nil | ||
// https://learn.microsoft.com/en-us/windows/win32/api/weakreference/nf-weakreference-iweakreference-resolve(refiid_iinspectable): | ||
// "If you try to resolve a weak reference to a strong reference for an object that is no longer available, | ||
// then IWeakReference::Resolve returns S_OK, but the objectReference parameter points to null. | ||
guard let target = weakReference.target else { return S_OK } | ||
|
||
let anyWrapper = __ABI_.AnyWrapper(target)! | ||
var rawObject: UnsafeMutableRawPointer? = nil | ||
let result = __ABI_.AnyWrapper.queryInterface(try! anyWrapper.toABI { $0 }, riid, &rawObject) | ||
ppvObject.pointee = rawObject?.bindMemory(to: C_IInspectable.self, capacity: 1) | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import C_BINDINGS_MODULE | ||
|
||
internal let IID_IWeakReferenceSource: IID = IID(Data1: 0x00000038, Data2: 0x0000, Data3: 0x0000, Data4: (0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)) // 00000038-0000-0000-C000-000000000046 | ||
|
||
fileprivate extension IUnknownRef { | ||
func copyTo(_ riid: REFIID?, _ ppvObj: UnsafeMutablePointer<LPVOID?>?) -> HRESULT { | ||
self.borrow.pointee.lpVtbl.pointee.QueryInterface(self.borrow, riid, ppvObj) | ||
} | ||
} | ||
|
||
func makeWeakReferenceSource(_ object: AnyObject, _ result: UnsafeMutablePointer<UnsafeMutableRawPointer?>) throws { | ||
let wrapper = WeakReferenceSourceWrapper(object) | ||
try wrapper.toABI { | ||
_ = $0.pointee.lpVtbl.pointee.AddRef($0) | ||
result.pointee = UnsafeMutableRawPointer($0) | ||
} | ||
} | ||
|
||
fileprivate class WeakReferenceSourceWrapper: WinRTAbiBridgeWrapper<IWeakReferenceSourceBridge> { | ||
init(_ object: AnyObject){ | ||
super.init(IWeakReferenceSourceBridge.makeAbi(), object) | ||
} | ||
|
||
internal static func queryInterface(_ pUnk: UnsafeMutablePointer<C_IInspectable>?, _ riid: UnsafePointer<SUPPORT_MODULE.IID>?, _ ppvObject: UnsafeMutablePointer<UnsafeMutableRawPointer?>?) -> HRESULT { | ||
guard let pUnk, let riid, let ppvObject else { return E_INVALIDARG } | ||
switch riid.pointee { | ||
case IID_IWeakReferenceSource: | ||
_ = pUnk.pointee.lpVtbl.pointee.AddRef(pUnk) | ||
return S_OK | ||
default: | ||
guard let obj = WeakReferenceSourceWrapper.tryUnwrapFromBase(raw: pUnk) else { return E_NOINTERFACE } | ||
let anyWrapper = __ABI_.AnyWrapper(obj)! | ||
return __ABI_.AnyWrapper.queryInterface(try! anyWrapper.toABI { $0 }, riid, ppvObject) | ||
} | ||
} | ||
} | ||
|
||
fileprivate enum IWeakReferenceSourceBridge: AbiBridge { | ||
typealias CABI = C_IWeakReferenceSource | ||
typealias SwiftProjection = AnyObject | ||
|
||
static func makeAbi() -> C_IWeakReferenceSource { | ||
return C_IWeakReferenceSource(lpVtbl: &IWeakReferenceSourceVTable) | ||
} | ||
|
||
static func from(abi: ComPtr<C_IWeakReferenceSource>?) -> AnyObject? { | ||
fatalError("Not needed") | ||
} | ||
} | ||
|
||
fileprivate var IWeakReferenceSourceVTable: C_IWeakReferenceSourceVtbl = .init( | ||
QueryInterface: { WeakReferenceSourceWrapper.queryInterface($0, $1, $2) }, | ||
AddRef: { WeakReferenceSourceWrapper.addRef($0) }, | ||
Release: { WeakReferenceSourceWrapper.release($0) }, | ||
GetWeakReference: { GetWeakReference($0, $1) } | ||
) | ||
|
||
fileprivate func GetWeakReference( | ||
_ this: UnsafeMutablePointer<C_IWeakReferenceSource>?, | ||
_ weakReference: UnsafeMutablePointer<UnsafeMutablePointer<C_IWeakReference>?>?) -> HRESULT { | ||
guard let object = WeakReferenceSourceWrapper.tryUnwrapFrom(abi: ComPtr(this)) else { return E_FAIL } | ||
guard let weakReference else { return E_INVALIDARG } | ||
do { | ||
var rawWeakReference: UnsafeMutableRawPointer? = nil | ||
try makeWeakReference(object, &rawWeakReference) | ||
weakReference.pointee = rawWeakReference?.bindMemory(to: C_IWeakReference.self, capacity: 1) | ||
return S_OK | ||
} catch { | ||
return E_FAIL | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import WinSDK | ||
import XCTest | ||
@_spi(WinRTInternal) import test_component | ||
import Ctest_component | ||
import Foundation | ||
|
||
class WeakReferenceTests : XCTestCase { | ||
class Target: IReferenceTarget { | ||
func method() {} | ||
} | ||
|
||
public func testCreateAndResolve() throws { | ||
let original = Target() | ||
let weakReferencer = WeakReferencer(original) | ||
let roundtrippedAny = try XCTUnwrap(weakReferencer.resolve()) | ||
let roundtripped = try XCTUnwrap(roundtrippedAny as? Target) | ||
XCTAssertIdentical(roundtripped, original) | ||
} | ||
|
||
public func testNotStrong() throws { | ||
var original: Target! = Target() | ||
let weakReferencer = WeakReferencer(original) | ||
original = nil | ||
XCTAssertNil(try weakReferencer.resolve()) | ||
} | ||
} | ||
|
||
var weakReferenceTests: [XCTestCaseEntry] = [ | ||
testCase([ | ||
("testCreateAndResolve", WeakReferenceTests.testCreateAndResolve), | ||
("testNotStrong", WeakReferenceTests.testNotStrong) | ||
]) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.