util.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // Copyright Joyent, Inc. and other Node contributors.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a
  4. // copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to permit
  8. // persons to whom the Software is furnished to do so, subject to the
  9. // following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  17. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  18. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
  22. function getOwnPropertyDescriptors(obj) {
  23. var keys = Object.keys(obj);
  24. var descriptors = {};
  25. for (var i = 0; i < keys.length; i++) {
  26. descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
  27. }
  28. return descriptors;
  29. };
  30. var formatRegExp = /%[sdj%]/g;
  31. exports.format = function(f) {
  32. if (!isString(f)) {
  33. var objects = [];
  34. for (var i = 0; i < arguments.length; i++) {
  35. objects.push(inspect(arguments[i]));
  36. }
  37. return objects.join(' ');
  38. }
  39. var i = 1;
  40. var args = arguments;
  41. var len = args.length;
  42. var str = String(f).replace(formatRegExp, function(x) {
  43. if (x === '%%') return '%';
  44. if (i >= len) return x;
  45. switch (x) {
  46. case '%s': return String(args[i++]);
  47. case '%d': return Number(args[i++]);
  48. case '%j':
  49. try {
  50. return JSON.stringify(args[i++]);
  51. } catch (_) {
  52. return '[Circular]';
  53. }
  54. default:
  55. return x;
  56. }
  57. });
  58. for (var x = args[i]; i < len; x = args[++i]) {
  59. if (isNull(x) || !isObject(x)) {
  60. str += ' ' + x;
  61. } else {
  62. str += ' ' + inspect(x);
  63. }
  64. }
  65. return str;
  66. };
  67. // Mark that a method should not be used.
  68. // Returns a modified function which warns once by default.
  69. // If --no-deprecation is set, then it is a no-op.
  70. exports.deprecate = function(fn, msg) {
  71. if (typeof process !== 'undefined' && process.noDeprecation === true) {
  72. return fn;
  73. }
  74. // Allow for deprecating things in the process of starting up.
  75. if (typeof process === 'undefined') {
  76. return function() {
  77. return exports.deprecate(fn, msg).apply(this, arguments);
  78. };
  79. }
  80. var warned = false;
  81. function deprecated() {
  82. if (!warned) {
  83. if (process.throwDeprecation) {
  84. throw new Error(msg);
  85. } else if (process.traceDeprecation) {
  86. console.trace(msg);
  87. } else {
  88. console.error(msg);
  89. }
  90. warned = true;
  91. }
  92. return fn.apply(this, arguments);
  93. }
  94. return deprecated;
  95. };
  96. var debugs = {};
  97. var debugEnvRegex = /^$/;
  98. if (process.env.NODE_DEBUG) {
  99. var debugEnv = process.env.NODE_DEBUG;
  100. debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
  101. .replace(/\*/g, '.*')
  102. .replace(/,/g, '$|^')
  103. .toUpperCase();
  104. debugEnvRegex = new RegExp('^' + debugEnv + '$', 'i');
  105. }
  106. exports.debuglog = function(set) {
  107. set = set.toUpperCase();
  108. if (!debugs[set]) {
  109. if (debugEnvRegex.test(set)) {
  110. var pid = process.pid;
  111. debugs[set] = function() {
  112. var msg = exports.format.apply(exports, arguments);
  113. console.error('%s %d: %s', set, pid, msg);
  114. };
  115. } else {
  116. debugs[set] = function() {};
  117. }
  118. }
  119. return debugs[set];
  120. };
  121. /**
  122. * Echos the value of a value. Trys to print the value out
  123. * in the best way possible given the different types.
  124. *
  125. * @param {Object} obj The object to print out.
  126. * @param {Object} opts Optional options object that alters the output.
  127. */
  128. /* legacy: obj, showHidden, depth, colors*/
  129. function inspect(obj, opts) {
  130. // default options
  131. var ctx = {
  132. seen: [],
  133. stylize: stylizeNoColor
  134. };
  135. // legacy...
  136. if (arguments.length >= 3) ctx.depth = arguments[2];
  137. if (arguments.length >= 4) ctx.colors = arguments[3];
  138. if (isBoolean(opts)) {
  139. // legacy...
  140. ctx.showHidden = opts;
  141. } else if (opts) {
  142. // got an "options" object
  143. exports._extend(ctx, opts);
  144. }
  145. // set default options
  146. if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
  147. if (isUndefined(ctx.depth)) ctx.depth = 2;
  148. if (isUndefined(ctx.colors)) ctx.colors = false;
  149. if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
  150. if (ctx.colors) ctx.stylize = stylizeWithColor;
  151. return formatValue(ctx, obj, ctx.depth);
  152. }
  153. exports.inspect = inspect;
  154. // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  155. inspect.colors = {
  156. 'bold' : [1, 22],
  157. 'italic' : [3, 23],
  158. 'underline' : [4, 24],
  159. 'inverse' : [7, 27],
  160. 'white' : [37, 39],
  161. 'grey' : [90, 39],
  162. 'black' : [30, 39],
  163. 'blue' : [34, 39],
  164. 'cyan' : [36, 39],
  165. 'green' : [32, 39],
  166. 'magenta' : [35, 39],
  167. 'red' : [31, 39],
  168. 'yellow' : [33, 39]
  169. };
  170. // Don't use 'blue' not visible on cmd.exe
  171. inspect.styles = {
  172. 'special': 'cyan',
  173. 'number': 'yellow',
  174. 'boolean': 'yellow',
  175. 'undefined': 'grey',
  176. 'null': 'bold',
  177. 'string': 'green',
  178. 'date': 'magenta',
  179. // "name": intentionally not styling
  180. 'regexp': 'red'
  181. };
  182. function stylizeWithColor(str, styleType) {
  183. var style = inspect.styles[styleType];
  184. if (style) {
  185. return '\u001b[' + inspect.colors[style][0] + 'm' + str +
  186. '\u001b[' + inspect.colors[style][1] + 'm';
  187. } else {
  188. return str;
  189. }
  190. }
  191. function stylizeNoColor(str, styleType) {
  192. return str;
  193. }
  194. function arrayToHash(array) {
  195. var hash = {};
  196. array.forEach(function(val, idx) {
  197. hash[val] = true;
  198. });
  199. return hash;
  200. }
  201. function formatValue(ctx, value, recurseTimes) {
  202. // Provide a hook for user-specified inspect functions.
  203. // Check that value is an object with an inspect function on it
  204. if (ctx.customInspect &&
  205. value &&
  206. isFunction(value.inspect) &&
  207. // Filter out the util module, it's inspect function is special
  208. value.inspect !== exports.inspect &&
  209. // Also filter out any prototype objects using the circular check.
  210. !(value.constructor && value.constructor.prototype === value)) {
  211. var ret = value.inspect(recurseTimes, ctx);
  212. if (!isString(ret)) {
  213. ret = formatValue(ctx, ret, recurseTimes);
  214. }
  215. return ret;
  216. }
  217. // Primitive types cannot have properties
  218. var primitive = formatPrimitive(ctx, value);
  219. if (primitive) {
  220. return primitive;
  221. }
  222. // Look up the keys of the object.
  223. var keys = Object.keys(value);
  224. var visibleKeys = arrayToHash(keys);
  225. if (ctx.showHidden) {
  226. keys = Object.getOwnPropertyNames(value);
  227. }
  228. // IE doesn't make error fields non-enumerable
  229. // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
  230. if (isError(value)
  231. && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
  232. return formatError(value);
  233. }
  234. // Some type of object without properties can be shortcutted.
  235. if (keys.length === 0) {
  236. if (isFunction(value)) {
  237. var name = value.name ? ': ' + value.name : '';
  238. return ctx.stylize('[Function' + name + ']', 'special');
  239. }
  240. if (isRegExp(value)) {
  241. return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
  242. }
  243. if (isDate(value)) {
  244. return ctx.stylize(Date.prototype.toString.call(value), 'date');
  245. }
  246. if (isError(value)) {
  247. return formatError(value);
  248. }
  249. }
  250. var base = '', array = false, braces = ['{', '}'];
  251. // Make Array say that they are Array
  252. if (isArray(value)) {
  253. array = true;
  254. braces = ['[', ']'];
  255. }
  256. // Make functions say that they are functions
  257. if (isFunction(value)) {
  258. var n = value.name ? ': ' + value.name : '';
  259. base = ' [Function' + n + ']';
  260. }
  261. // Make RegExps say that they are RegExps
  262. if (isRegExp(value)) {
  263. base = ' ' + RegExp.prototype.toString.call(value);
  264. }
  265. // Make dates with properties first say the date
  266. if (isDate(value)) {
  267. base = ' ' + Date.prototype.toUTCString.call(value);
  268. }
  269. // Make error with message first say the error
  270. if (isError(value)) {
  271. base = ' ' + formatError(value);
  272. }
  273. if (keys.length === 0 && (!array || value.length == 0)) {
  274. return braces[0] + base + braces[1];
  275. }
  276. if (recurseTimes < 0) {
  277. if (isRegExp(value)) {
  278. return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
  279. } else {
  280. return ctx.stylize('[Object]', 'special');
  281. }
  282. }
  283. ctx.seen.push(value);
  284. var output;
  285. if (array) {
  286. output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
  287. } else {
  288. output = keys.map(function(key) {
  289. return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
  290. });
  291. }
  292. ctx.seen.pop();
  293. return reduceToSingleString(output, base, braces);
  294. }
  295. function formatPrimitive(ctx, value) {
  296. if (isUndefined(value))
  297. return ctx.stylize('undefined', 'undefined');
  298. if (isString(value)) {
  299. var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
  300. .replace(/'/g, "\\'")
  301. .replace(/\\"/g, '"') + '\'';
  302. return ctx.stylize(simple, 'string');
  303. }
  304. if (isNumber(value))
  305. return ctx.stylize('' + value, 'number');
  306. if (isBoolean(value))
  307. return ctx.stylize('' + value, 'boolean');
  308. // For some reason typeof null is "object", so special case here.
  309. if (isNull(value))
  310. return ctx.stylize('null', 'null');
  311. }
  312. function formatError(value) {
  313. return '[' + Error.prototype.toString.call(value) + ']';
  314. }
  315. function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
  316. var output = [];
  317. for (var i = 0, l = value.length; i < l; ++i) {
  318. if (hasOwnProperty(value, String(i))) {
  319. output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
  320. String(i), true));
  321. } else {
  322. output.push('');
  323. }
  324. }
  325. keys.forEach(function(key) {
  326. if (!key.match(/^\d+$/)) {
  327. output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
  328. key, true));
  329. }
  330. });
  331. return output;
  332. }
  333. function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
  334. var name, str, desc;
  335. desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
  336. if (desc.get) {
  337. if (desc.set) {
  338. str = ctx.stylize('[Getter/Setter]', 'special');
  339. } else {
  340. str = ctx.stylize('[Getter]', 'special');
  341. }
  342. } else {
  343. if (desc.set) {
  344. str = ctx.stylize('[Setter]', 'special');
  345. }
  346. }
  347. if (!hasOwnProperty(visibleKeys, key)) {
  348. name = '[' + key + ']';
  349. }
  350. if (!str) {
  351. if (ctx.seen.indexOf(desc.value) < 0) {
  352. if (isNull(recurseTimes)) {
  353. str = formatValue(ctx, desc.value, null);
  354. } else {
  355. str = formatValue(ctx, desc.value, recurseTimes - 1);
  356. }
  357. if (str.indexOf('\n') > -1) {
  358. if (array) {
  359. str = str.split('\n').map(function(line) {
  360. return ' ' + line;
  361. }).join('\n').substr(2);
  362. } else {
  363. str = '\n' + str.split('\n').map(function(line) {
  364. return ' ' + line;
  365. }).join('\n');
  366. }
  367. }
  368. } else {
  369. str = ctx.stylize('[Circular]', 'special');
  370. }
  371. }
  372. if (isUndefined(name)) {
  373. if (array && key.match(/^\d+$/)) {
  374. return str;
  375. }
  376. name = JSON.stringify('' + key);
  377. if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
  378. name = name.substr(1, name.length - 2);
  379. name = ctx.stylize(name, 'name');
  380. } else {
  381. name = name.replace(/'/g, "\\'")
  382. .replace(/\\"/g, '"')
  383. .replace(/(^"|"$)/g, "'");
  384. name = ctx.stylize(name, 'string');
  385. }
  386. }
  387. return name + ': ' + str;
  388. }
  389. function reduceToSingleString(output, base, braces) {
  390. var numLinesEst = 0;
  391. var length = output.reduce(function(prev, cur) {
  392. numLinesEst++;
  393. if (cur.indexOf('\n') >= 0) numLinesEst++;
  394. return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
  395. }, 0);
  396. if (length > 60) {
  397. return braces[0] +
  398. (base === '' ? '' : base + '\n ') +
  399. ' ' +
  400. output.join(',\n ') +
  401. ' ' +
  402. braces[1];
  403. }
  404. return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  405. }
  406. // NOTE: These type checking functions intentionally don't use `instanceof`
  407. // because it is fragile and can be easily faked with `Object.create()`.
  408. exports.types = require('./support/types');
  409. function isArray(ar) {
  410. return Array.isArray(ar);
  411. }
  412. exports.isArray = isArray;
  413. function isBoolean(arg) {
  414. return typeof arg === 'boolean';
  415. }
  416. exports.isBoolean = isBoolean;
  417. function isNull(arg) {
  418. return arg === null;
  419. }
  420. exports.isNull = isNull;
  421. function isNullOrUndefined(arg) {
  422. return arg == null;
  423. }
  424. exports.isNullOrUndefined = isNullOrUndefined;
  425. function isNumber(arg) {
  426. return typeof arg === 'number';
  427. }
  428. exports.isNumber = isNumber;
  429. function isString(arg) {
  430. return typeof arg === 'string';
  431. }
  432. exports.isString = isString;
  433. function isSymbol(arg) {
  434. return typeof arg === 'symbol';
  435. }
  436. exports.isSymbol = isSymbol;
  437. function isUndefined(arg) {
  438. return arg === void 0;
  439. }
  440. exports.isUndefined = isUndefined;
  441. function isRegExp(re) {
  442. return isObject(re) && objectToString(re) === '[object RegExp]';
  443. }
  444. exports.isRegExp = isRegExp;
  445. exports.types.isRegExp = isRegExp;
  446. function isObject(arg) {
  447. return typeof arg === 'object' && arg !== null;
  448. }
  449. exports.isObject = isObject;
  450. function isDate(d) {
  451. return isObject(d) && objectToString(d) === '[object Date]';
  452. }
  453. exports.isDate = isDate;
  454. exports.types.isDate = isDate;
  455. function isError(e) {
  456. return isObject(e) &&
  457. (objectToString(e) === '[object Error]' || e instanceof Error);
  458. }
  459. exports.isError = isError;
  460. exports.types.isNativeError = isError;
  461. function isFunction(arg) {
  462. return typeof arg === 'function';
  463. }
  464. exports.isFunction = isFunction;
  465. function isPrimitive(arg) {
  466. return arg === null ||
  467. typeof arg === 'boolean' ||
  468. typeof arg === 'number' ||
  469. typeof arg === 'string' ||
  470. typeof arg === 'symbol' || // ES6 symbol
  471. typeof arg === 'undefined';
  472. }
  473. exports.isPrimitive = isPrimitive;
  474. exports.isBuffer = require('./support/isBuffer');
  475. function objectToString(o) {
  476. return Object.prototype.toString.call(o);
  477. }
  478. function pad(n) {
  479. return n < 10 ? '0' + n.toString(10) : n.toString(10);
  480. }
  481. var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
  482. 'Oct', 'Nov', 'Dec'];
  483. // 26 Feb 16:19:34
  484. function timestamp() {
  485. var d = new Date();
  486. var time = [pad(d.getHours()),
  487. pad(d.getMinutes()),
  488. pad(d.getSeconds())].join(':');
  489. return [d.getDate(), months[d.getMonth()], time].join(' ');
  490. }
  491. // log is just a thin wrapper to console.log that prepends a timestamp
  492. exports.log = function() {
  493. console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  494. };
  495. /**
  496. * Inherit the prototype methods from one constructor into another.
  497. *
  498. * The Function.prototype.inherits from lang.js rewritten as a standalone
  499. * function (not on Function.prototype). NOTE: If this file is to be loaded
  500. * during bootstrapping this function needs to be rewritten using some native
  501. * functions as prototype setup using normal JavaScript does not work as
  502. * expected during bootstrapping (see mirror.js in r114903).
  503. *
  504. * @param {function} ctor Constructor function which needs to inherit the
  505. * prototype.
  506. * @param {function} superCtor Constructor function to inherit prototype from.
  507. */
  508. exports.inherits = require('inherits');
  509. exports._extend = function(origin, add) {
  510. // Don't do anything if add isn't an object
  511. if (!add || !isObject(add)) return origin;
  512. var keys = Object.keys(add);
  513. var i = keys.length;
  514. while (i--) {
  515. origin[keys[i]] = add[keys[i]];
  516. }
  517. return origin;
  518. };
  519. function hasOwnProperty(obj, prop) {
  520. return Object.prototype.hasOwnProperty.call(obj, prop);
  521. }
  522. var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;
  523. exports.promisify = function promisify(original) {
  524. if (typeof original !== 'function')
  525. throw new TypeError('The "original" argument must be of type Function');
  526. if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {
  527. var fn = original[kCustomPromisifiedSymbol];
  528. if (typeof fn !== 'function') {
  529. throw new TypeError('The "util.promisify.custom" argument must be of type Function');
  530. }
  531. Object.defineProperty(fn, kCustomPromisifiedSymbol, {
  532. value: fn, enumerable: false, writable: false, configurable: true
  533. });
  534. return fn;
  535. }
  536. function fn() {
  537. var promiseResolve, promiseReject;
  538. var promise = new Promise(function (resolve, reject) {
  539. promiseResolve = resolve;
  540. promiseReject = reject;
  541. });
  542. var args = [];
  543. for (var i = 0; i < arguments.length; i++) {
  544. args.push(arguments[i]);
  545. }
  546. args.push(function (err, value) {
  547. if (err) {
  548. promiseReject(err);
  549. } else {
  550. promiseResolve(value);
  551. }
  552. });
  553. try {
  554. original.apply(this, args);
  555. } catch (err) {
  556. promiseReject(err);
  557. }
  558. return promise;
  559. }
  560. Object.setPrototypeOf(fn, Object.getPrototypeOf(original));
  561. if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {
  562. value: fn, enumerable: false, writable: false, configurable: true
  563. });
  564. return Object.defineProperties(
  565. fn,
  566. getOwnPropertyDescriptors(original)
  567. );
  568. }
  569. exports.promisify.custom = kCustomPromisifiedSymbol
  570. function callbackifyOnRejected(reason, cb) {
  571. // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
  572. // Because `null` is a special error value in callbacks which means "no error
  573. // occurred", we error-wrap so the callback consumer can distinguish between
  574. // "the promise rejected with null" or "the promise fulfilled with undefined".
  575. if (!reason) {
  576. var newReason = new Error('Promise was rejected with a falsy value');
  577. newReason.reason = reason;
  578. reason = newReason;
  579. }
  580. return cb(reason);
  581. }
  582. function callbackify(original) {
  583. if (typeof original !== 'function') {
  584. throw new TypeError('The "original" argument must be of type Function');
  585. }
  586. // We DO NOT return the promise as it gives the user a false sense that
  587. // the promise is actually somehow related to the callback's execution
  588. // and that the callback throwing will reject the promise.
  589. function callbackified() {
  590. var args = [];
  591. for (var i = 0; i < arguments.length; i++) {
  592. args.push(arguments[i]);
  593. }
  594. var maybeCb = args.pop();
  595. if (typeof maybeCb !== 'function') {
  596. throw new TypeError('The last argument must be of type Function');
  597. }
  598. var self = this;
  599. var cb = function() {
  600. return maybeCb.apply(self, arguments);
  601. };
  602. // In true node style we process the callback on `nextTick` with all the
  603. // implications (stack, `uncaughtException`, `async_hooks`)
  604. original.apply(this, args)
  605. .then(function(ret) { process.nextTick(cb.bind(null, null, ret)) },
  606. function(rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) });
  607. }
  608. Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
  609. Object.defineProperties(callbackified,
  610. getOwnPropertyDescriptors(original));
  611. return callbackified;
  612. }
  613. exports.callbackify = callbackify;