@@ -68,6 +68,49 @@ namespace
6868 REQUIRE (weak_self.get () == nullptr );
6969 }
7070 };
71+
72+ struct WeakCreateWeakInDestructor : implements<WeakCreateWeakInDestructor, IStringable>
73+ {
74+ winrt::weak_ref<WeakCreateWeakInDestructor>& weak_self;
75+
76+ WeakCreateWeakInDestructor (winrt::weak_ref<WeakCreateWeakInDestructor>& magic) : weak_self(magic) {}
77+
78+ ~WeakCreateWeakInDestructor ()
79+ {
80+ // Creates a weak reference to itself in the destructor.
81+ weak_self = get_weak ();
82+ }
83+
84+ hstring ToString ()
85+ {
86+ return L" WeakCreateWeakInDestructor" ;
87+ }
88+ };
89+
90+ #ifdef WINRT_IMPL_COROUTINES
91+ // Returns an IAsyncAction that has already completed.
92+ winrt::Windows::Foundation::IAsyncAction Action ()
93+ {
94+ co_return ;
95+ }
96+
97+ // Returns an IAsyncAction that has not completed.
98+ // Call the resume() handle to complete it.
99+ winrt::Windows::Foundation::IAsyncAction SuspendAction (impl::coroutine_handle<>& resume)
100+ {
101+ struct awaiter
102+ {
103+ impl::coroutine_handle<>& resume;
104+ bool await_ready () { return false ; }
105+ void await_suspend (impl::coroutine_handle<> handle) { resume = handle; }
106+ void await_resume () {}
107+ };
108+
109+ co_await awaiter{ resume };
110+ co_return ;
111+ }
112+
113+ #endif
71114}
72115
73116TEST_CASE (" weak,source" )
@@ -413,3 +456,37 @@ TEST_CASE("weak,self")
413456 a.ToString ();
414457 a = nullptr ;
415458}
459+
460+ TEST_CASE (" weak,create_weak_in_destructor" )
461+ {
462+ weak_ref<WeakCreateWeakInDestructor> magic;
463+ IStringable a = make<WeakCreateWeakInDestructor>(magic);
464+ a.ToString ();
465+ a = nullptr ;
466+ REQUIRE (magic.get () == nullptr );
467+ }
468+
469+ #ifdef WINRT_IMPL_COROUTINES
470+ TEST_CASE (" weak,coroutine" )
471+ {
472+ // Run a coroutine to completion. Confirm that weak references fail to resolve.
473+ auto weak = winrt::weak_ref (Action ());
474+ REQUIRE (weak.get () == nullptr );
475+
476+ // Start a coroutine but don't complete it yet.
477+ // Confirm that weak references resolve.
478+ impl::coroutine_handle<> resume;
479+ weak = winrt::weak_ref (SuspendAction (resume));
480+ REQUIRE (weak.get () != nullptr );
481+ // Now complete the coroutine. Confirm that weak references no longer resolve.
482+ resume ();
483+ REQUIRE (weak.get () == nullptr );
484+
485+ // Verify that weak reference resolves as long as strong reference exists.
486+ auto action = Action ();
487+ weak = winrt::weak_ref (action);
488+ REQUIRE (weak.get () == action);
489+ action = nullptr ;
490+ REQUIRE (weak.get () == nullptr );
491+ }
492+ #endif
0 commit comments