@@ -154,4 +154,88 @@ describe('copyEventEmitter()', function() {
154154
155155 expect ( target . listenerCount ( eventName ) ) . to . be . equal ( 1 ) ;
156156 } ) ;
157+
158+ it ( 'should handle onceWrapper-like listener with undefined listener property' , ( ) => {
159+ const source = new EventEmitter ( ) ;
160+ const target = new EventEmitter ( ) ;
161+
162+ const mockListener : any = function ( ) { } ;
163+ mockListener . listener = undefined ; // explicitly undefined
164+ const originalInspect = require ( 'util' ) . inspect ;
165+ require ( 'util' ) . inspect = ( obj : any ) => {
166+ if ( obj === mockListener ) {
167+ return 'function onceWrapper() { ... }' ;
168+ }
169+ return originalInspect ( obj ) ;
170+ } ;
171+
172+ source . on ( eventName , mockListener as any ) ;
173+ copyEventEmitter ( source , target ) ;
174+
175+ // Restore original inspect
176+ require ( 'util' ) . inspect = originalInspect ;
177+
178+ expect ( target . listenerCount ( eventName ) ) . to . be . equal ( 1 ) ;
179+ } ) ;
180+
181+ it ( 'should handle onceWrapper-like listener with truthy listener property' , ( ) => {
182+ const source = new EventEmitter ( ) ;
183+ const target = new EventEmitter ( ) ;
184+
185+ // Create a mock listener that looks like onceWrapper and has a truthy listener property
186+ let called = 0 ;
187+ const realListener = ( ) => { called ++ ; } ;
188+ const mockListener : any = function ( ) { } ;
189+ mockListener . listener = realListener ; // truthy function
190+
191+ const originalInspect = require ( 'util' ) . inspect ;
192+ require ( 'util' ) . inspect = ( obj : any ) => {
193+ if ( obj === mockListener ) {
194+ return 'function onceWrapper() { ... }' ;
195+ }
196+ return originalInspect ( obj ) ;
197+ } ;
198+
199+ source . on ( eventName , mockListener as any ) ;
200+ copyEventEmitter ( source , target ) ;
201+
202+ // Restore original inspect
203+ require ( 'util' ) . inspect = originalInspect ;
204+
205+ // Ensure the listener was attached via once() and is callable exactly once
206+ expect ( target . listenerCount ( eventName ) ) . to . be . equal ( 1 ) ;
207+ target . emit ( eventName ) ;
208+ target . emit ( eventName ) ;
209+ expect ( called ) . to . equal ( 1 ) ;
210+ } ) ;
211+
212+ it ( 'should handle onceWrapper path when originalListener is undefined' , ( ) => {
213+ const source : any = {
214+ eventNames : ( ) => [ eventName ] ,
215+ rawListeners : ( ) => [ undefined ] ,
216+ getMaxListeners : ( ) => 0 ,
217+ setMaxListeners : ( ) => { } ,
218+ } ;
219+ const onceCalls : any [ ] = [ ] ;
220+ const target : any = {
221+ once : ( ev : any , listener : any ) => { onceCalls . push ( [ ev , listener ] ) ; } ,
222+ on : ( ) => { } ,
223+ } ;
224+ const originalInspect = require ( 'util' ) . inspect ;
225+ require ( 'util' ) . inspect = ( obj : any ) => {
226+ if ( typeof obj === 'undefined' ) {
227+ return 'function onceWrapper() { ... }' ;
228+ }
229+ return originalInspect ( obj ) ;
230+ } ;
231+
232+ copyEventEmitter ( source as any , target as any ) ;
233+
234+ // Restore original inspect
235+ require ( 'util' ) . inspect = originalInspect ;
236+
237+ expect ( onceCalls . length ) . to . equal ( 1 ) ;
238+ expect ( onceCalls [ 0 ] [ 0 ] ) . to . equal ( eventName ) ;
239+ expect ( onceCalls [ 0 ] [ 1 ] ) . to . equal ( undefined ) ;
240+ } ) ;
157241} ) ;
0 commit comments