@@ -281,6 +281,8 @@ function tracingChannelFrom(nameOrChannels, name) {
281281}
282282
283283class TracingChannel {
284+ #generatorChannel
285+
284286 constructor ( nameOrChannels ) {
285287 for ( let i = 0 ; i < traceEvents . length ; ++ i ) {
286288 const eventName = traceEvents [ i ] ;
@@ -428,6 +430,84 @@ class TracingChannel {
428430 }
429431 } ) ;
430432 }
433+
434+ traceIterator ( fn , context = { } , thisArg , ...args ) {
435+ if ( ! this . hasSubscribers ) {
436+ return ReflectApply ( fn , thisArg , args ) ;
437+ }
438+
439+ const { channel, start, end, asyncStart, asyncEnd, error } = this ;
440+
441+ if ( ! this . #nextChannel) {
442+ this . #nextChannel = this . tracingChannel ( {
443+ start : channel ( start . name . slice ( 0 , - 6 ) + ':next:start' ) ,
444+ end : channel ( end . name . slice ( 0 , - 4 ) + ':next:end' ) ,
445+ asyncStart : channel ( asyncStart . name . slice ( 0 , - 11 ) + ':next:asyncStart' ) ,
446+ asyncEnd : channel ( asyncEnd . name . slice ( 0 , - 9 ) + ':next:asyncEnd' ) ,
447+ error : channel ( error . name . slice ( 0 , - 6 ) + ':next:error' ) ,
448+ } ) ;
449+ }
450+
451+ const iter = this . #traceMaybePromise( fn , context , thisArg , ...args ) ;
452+
453+ return iter instanceof Promise
454+ ? iter . then ( ( iter , method ) => {
455+ const { next : iterNext , return : iterReturn , throw : iterThrow } = iter ;
456+
457+ iter . next = ( ...args ) =>
458+ this . #nextChannel. #traceMaybePromise( iterNext , ctx , iter , ...args ) ;
459+ iter . return = ( ...args ) =>
460+ this . #nextChannel. #traceMaybePromise( iterReturn , ctx , iter , ...args ) ;
461+ iter . throw = ( ...args ) =>
462+ this . #nextChannel. #traceMaybePromise( iterThrow , ctx , iter , ...args ) ;
463+
464+ return iter ;
465+ } )
466+ : iter ;
467+ }
468+
469+ #traceMaybePromise( fn , context = { } , thisArg , ...args ) {
470+ if ( ! this . hasSubscribers ) {
471+ return ReflectApply ( fn , thisArg , args ) ;
472+ }
473+
474+ const { start, end, asyncStart, asyncEnd, error } = this ;
475+
476+ function reject ( err ) {
477+ context . error = err ;
478+ error . publish ( context ) ;
479+ asyncStart . publish ( context ) ;
480+ // TODO: Is there a way to have asyncEnd _after_ the continuation?
481+ asyncEnd . publish ( context ) ;
482+ return PromiseReject ( err ) ;
483+ }
484+
485+ function resolve ( result ) {
486+ context . result = result ;
487+ asyncStart . publish ( context ) ;
488+ // TODO: Is there a way to have asyncEnd _after_ the continuation?
489+ asyncEnd . publish ( context ) ;
490+ return result ;
491+ }
492+
493+ return start . runStores ( context , ( ) => {
494+ try {
495+ const result = ReflectApply ( fn , thisArg , args ) ;
496+ // TODO: Should tracePromise just always do this?
497+ if ( ! ( result instanceof Promise ) ) {
498+ context . result = result
499+ return result
500+ }
501+ return PromisePrototypeThen ( result , resolve , reject ) ;
502+ } catch ( err ) {
503+ context . error = err ;
504+ error . publish ( context ) ;
505+ throw err ;
506+ } finally {
507+ end . publish ( context ) ;
508+ }
509+ } ) ;
510+ }
431511}
432512
433513function tracingChannel ( nameOrChannels ) {
0 commit comments