@@ -10,8 +10,8 @@ const {
1010 ObjectDefineProperty,
1111 ObjectGetPrototypeOf,
1212 ObjectSetPrototypeOf,
13+ PromisePrototype,
1314 PromisePrototypeThen,
14- PromiseReject,
1515 ReflectApply,
1616 SafeFinalizationRegistry,
1717 SafeMap,
@@ -29,12 +29,12 @@ const {
2929} = require ( 'internal/validators' ) ;
3030
3131const { triggerUncaughtException } = internalBinding ( 'errors' ) ;
32+ const { isPromise } = require ( 'internal/util/types' ) ;
3233
3334const dc_binding = internalBinding ( 'diagnostics_channel' ) ;
3435const { subscribers : subscriberCounts } = dc_binding ;
3536
3637const { WeakReference } = require ( 'internal/util' ) ;
37- const { isPromise } = require ( 'internal/util/types' ) ;
3838
3939// Can't delete when weakref count reaches 0 as it could increment again.
4040// Only GC can be used as a valid time to clean up the channels map.
@@ -546,17 +546,21 @@ class TracingChannel {
546546 const { error } = this ;
547547 const continuationWindow = this . #continuationWindow;
548548
549- function reject ( err ) {
549+ function onReject ( err ) {
550550 context . error = err ;
551551 error . publish ( context ) ;
552552 // Use continuation window for asyncStart/asyncEnd
553553 // eslint-disable-next-line no-unused-vars
554554 using scope = continuationWindow . withScope ( context ) ;
555555 // TODO: Is there a way to have asyncEnd _after_ the continuation?
556- return PromiseReject ( err ) ;
557556 }
558557
559- function resolve ( result ) {
558+ function onRejectWithRethrow ( err ) {
559+ onReject ( err ) ;
560+ throw err ;
561+ }
562+
563+ function onResolve ( result ) {
560564 context . result = result ;
561565 // Use continuation window for asyncStart/asyncEnd
562566 // eslint-disable-next-line no-unused-vars
@@ -576,12 +580,17 @@ class TracingChannel {
576580 context . result = result ;
577581 return result ;
578582 }
579- // For native Promises use PromisePrototypeThen to avoid user overrides.
580- if ( isPromise ( result ) ) {
581- return PromisePrototypeThen ( result , resolve , reject ) ;
583+ // isPromise() matches sub-classes, but we need to match only direct
584+ // instances of the native Promise type to safely use PromisePrototypeThen.
585+ if ( isPromise ( result ) && ObjectGetPrototypeOf ( result ) === PromisePrototype ) {
586+ return PromisePrototypeThen ( result , onResolve , onRejectWithRethrow ) ;
582587 }
583- // For custom thenables, call .then() directly to preserve the thenable type.
584- return result . then ( resolve , reject ) ;
588+ // For non-native thenables, subscribe to the result but return the
589+ // original thenable so the consumer can continue handling it directly.
590+ // Non-native thenables don't have unhandledRejection tracking, so
591+ // swallowing the rejection here doesn't change existing behaviour.
592+ result . then ( onResolve , onReject ) ;
593+ return result ;
585594 } catch ( err ) {
586595 context . error = err ;
587596 error . publish ( context ) ;
0 commit comments