@@ -25,6 +25,7 @@ const uv = process.binding('uv');
25
25
const Buffer = require ( 'buffer' ) . Buffer ;
26
26
const internalUtil = require ( 'internal/util' ) ;
27
27
const binding = process . binding ( 'util' ) ;
28
+ const errors = require ( 'internal/errors' ) ;
28
29
29
30
const isError = internalUtil . isError ;
30
31
@@ -1055,3 +1056,53 @@ process.versions[exports.inspect.custom] =
1055
1056
( depth ) => exports . format ( JSON . parse ( JSON . stringify ( process . versions ) ) ) ;
1056
1057
1057
1058
exports . promisify = internalUtil . promisify ;
1059
+
1060
+ function callbackifyOnRejected ( reason , cb ) {
1061
+ // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
1062
+ // Because `null` is a special error value in callbacks which means "no error
1063
+ // occurred", we error-wrap so the callback consumer can distinguish between
1064
+ // "the promise rejected with null" or "the promise fulfilled with undefined".
1065
+ if ( ! reason ) {
1066
+ const newReason = new errors . Error ( 'FALSY_VALUE_REJECTION' ) ;
1067
+ newReason . reason = reason ;
1068
+ reason = newReason ;
1069
+ Error . captureStackTrace ( reason , callbackifyOnRejected ) ;
1070
+ }
1071
+ return cb ( reason ) ;
1072
+ }
1073
+
1074
+
1075
+ function callbackify ( original ) {
1076
+ if ( typeof original !== 'function' ) {
1077
+ throw new errors . TypeError (
1078
+ 'ERR_INVALID_ARG_TYPE' ,
1079
+ 'original' ,
1080
+ 'function' ) ;
1081
+ }
1082
+
1083
+ // We DO NOT return the promise as it gives the user a false sense that
1084
+ // the promise is actually somehow related to the callback's execution
1085
+ // and that the callback throwing will reject the promise.
1086
+ function callbackified ( ...args ) {
1087
+ const maybeCb = args . pop ( ) ;
1088
+ if ( typeof maybeCb !== 'function' ) {
1089
+ throw new errors . TypeError (
1090
+ 'ERR_INVALID_ARG_TYPE' ,
1091
+ 'last argument' ,
1092
+ 'function' ) ;
1093
+ }
1094
+ const cb = ( ...args ) => { Reflect . apply ( maybeCb , this , args ) ; } ;
1095
+ // In true node style we process the callback on `nextTick` with all the
1096
+ // implications (stack, `uncaughtException`, `async_hooks`)
1097
+ Reflect . apply ( original , this , args )
1098
+ . then ( ( ret ) => process . nextTick ( cb , null , ret ) ,
1099
+ ( rej ) => process . nextTick ( callbackifyOnRejected , rej , cb ) ) ;
1100
+ }
1101
+
1102
+ Object . setPrototypeOf ( callbackified , Object . getPrototypeOf ( original ) ) ;
1103
+ Object . defineProperties ( callbackified ,
1104
+ Object . getOwnPropertyDescriptors ( original ) ) ;
1105
+ return callbackified ;
1106
+ }
1107
+
1108
+ exports . callbackify = callbackify ;
0 commit comments