@@ -69,4 +69,71 @@ describe('AsyncAbortController', () => {
6969
7070 expect ( order ) . toEqual ( [ 'root:start' , 'root:end' , 'child' , 'grandchild' ] )
7171 } )
72+
73+ it ( 'forwards the real abort event to function listeners with the signal as context' , async ( ) => {
74+ const controller = new AsyncAbortController ( )
75+ const seen : {
76+ target : EventTarget | null
77+ currentTarget : EventTarget | null
78+ context : unknown
79+ } = {
80+ target : null ,
81+ currentTarget : null ,
82+ context : undefined ,
83+ }
84+
85+ controller . signal . addEventListener ( 'abort' , function ( event ) {
86+ seen . target = event . target
87+ seen . currentTarget = event . currentTarget
88+ seen . context = this
89+ } )
90+
91+ await controller . abortAsync ( )
92+
93+ expect ( seen . target ) . toBe ( controller . signal )
94+ expect ( seen . currentTarget ) . toBe ( controller . signal )
95+ expect ( seen . context ) . toBe ( controller . signal )
96+ } )
97+
98+ it ( 'waits for handleEvent listeners before aborting nested groups' , async ( ) => {
99+ const controller = new AsyncAbortController ( )
100+ const childGroup = controller . nextGroup
101+ const order : string [ ] = [ ]
102+ let releaseRootAbort ! : ( ) => void
103+ const rootAbortDone = new Promise < void > ( ( resolve ) => {
104+ releaseRootAbort = resolve
105+ } )
106+ const listener = {
107+ target : null as EventTarget | null ,
108+ async handleEvent ( event : Event ) {
109+ this . target = event . target
110+ order . push ( 'root:start' )
111+ await rootAbortDone
112+ order . push ( 'root:end' )
113+ } ,
114+ }
115+
116+ controller . signal . addEventListener ( 'abort' , listener )
117+ childGroup . signal . addEventListener ( 'abort' , ( ) => {
118+ order . push ( 'child' )
119+ } )
120+
121+ const abortPromise = controller . abortAsync ( )
122+
123+ await Promise . resolve ( )
124+ expect ( order ) . toEqual ( [ 'root:start' ] )
125+
126+ releaseRootAbort ( )
127+ await abortPromise
128+
129+ expect ( listener . target ) . toBe ( controller . signal )
130+ expect ( order ) . toEqual ( [ 'root:start' , 'root:end' , 'child' ] )
131+ } )
132+
133+ it ( 'ignores null abort listeners' , async ( ) => {
134+ const controller = new AsyncAbortController ( )
135+
136+ expect ( ( ) => controller . signal . addEventListener ( 'abort' , null ) ) . not . toThrow ( )
137+ await expect ( controller . abortAsync ( ) ) . resolves . toBeUndefined ( )
138+ } )
72139} )
0 commit comments