22
33const {
44 Promise,
5+ PromisePrototypeFinally,
56 PromiseReject,
67} = primordials ;
78
@@ -26,6 +27,13 @@ const lazyDOMException = hideStackFrames((message, name) => {
2627 return new DOMException ( message , name ) ;
2728} ) ;
2829
30+ function cancelListenerHandler ( clear , reject ) {
31+ if ( ! this . _destroyed ) {
32+ clear ( this ) ;
33+ reject ( lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ) ;
34+ }
35+ }
36+
2937function setTimeout ( after , value , options = { } ) {
3038 const args = value !== undefined ? [ value ] : value ;
3139 if ( options == null || typeof options !== 'object' ) {
@@ -55,20 +63,21 @@ function setTimeout(after, value, options = {}) {
5563 return PromiseReject (
5664 lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ) ;
5765 }
58- return new Promise ( ( resolve , reject ) => {
66+ let oncancel ;
67+ const ret = new Promise ( ( resolve , reject ) => {
5968 const timeout = new Timeout ( resolve , after , args , false , true ) ;
6069 if ( ! ref ) timeout . unref ( ) ;
6170 insert ( timeout , timeout . _idleTimeout ) ;
6271 if ( signal ) {
63- signal . addEventListener ( 'abort' , ( ) => {
64- if ( ! timeout . _destroyed ) {
65- // eslint-disable-next-line no-undef
66- clearTimeout ( timeout ) ;
67- reject ( lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ) ;
68- }
69- } , { once : true } ) ;
72+ // eslint-disable-next-line no-undef
73+ oncancel = cancelListenerHandler . bind ( timeout , clearTimeout , reject ) ;
74+ signal . addEventListener ( 'abort' , oncancel ) ;
7075 }
7176 } ) ;
77+ return oncancel !== undefined ?
78+ PromisePrototypeFinally (
79+ ret ,
80+ ( ) => signal . removeEventListener ( 'abort' , oncancel ) ) : ret ;
7281}
7382
7483function setImmediate ( value , options = { } ) {
@@ -99,19 +108,20 @@ function setImmediate(value, options = {}) {
99108 return PromiseReject (
100109 lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ) ;
101110 }
102- return new Promise ( ( resolve , reject ) => {
111+ let oncancel ;
112+ const ret = new Promise ( ( resolve , reject ) => {
103113 const immediate = new Immediate ( resolve , [ value ] ) ;
104114 if ( ! ref ) immediate . unref ( ) ;
105115 if ( signal ) {
106- signal . addEventListener ( 'abort' , ( ) => {
107- if ( ! immediate . _destroyed ) {
108- // eslint-disable-next-line no-undef
109- clearImmediate ( immediate ) ;
110- reject ( lazyDOMException ( 'The operation was aborted' , 'AbortError' ) ) ;
111- }
112- } , { once : true } ) ;
116+ // eslint-disable-next-line no-undef
117+ oncancel = cancelListenerHandler . bind ( immediate , clearImmediate , reject ) ;
118+ signal . addEventListener ( 'abort' , oncancel ) ;
113119 }
114120 } ) ;
121+ return oncancel !== undefined ?
122+ PromisePrototypeFinally (
123+ ret ,
124+ ( ) => signal . removeEventListener ( 'abort' , oncancel ) ) : ret ;
115125}
116126
117127module . exports = {
0 commit comments