implementation.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. 'use strict';
  2. var isES5 = typeof Object.defineProperty === 'function'
  3. && typeof Object.defineProperties === 'function';
  4. var hasProto = [].__proto__ === Array.prototype; // eslint-disable-line no-proto
  5. if (!isES5 || !hasProto) {
  6. throw new TypeError('util.promisify requires a true ES5 environment, that also supports `__proto__`');
  7. }
  8. var getOwnPropertyDescriptors = require('object.getownpropertydescriptors');
  9. if (typeof Promise !== 'function') {
  10. throw new TypeError('`Promise` must be globally available for util.promisify to work.');
  11. }
  12. var callBound = require('es-abstract/helpers/callBound');
  13. var $slice = callBound('Array.prototype.slice');
  14. var $concat = callBound('Array.prototype.concat');
  15. var $forEach = callBound('Array.prototype.forEach');
  16. var hasSymbols = require('has-symbols')();
  17. var kCustomPromisifiedSymbol = hasSymbols ? Symbol('util.promisify.custom') : null;
  18. var kCustomPromisifyArgsSymbol = hasSymbols ? Symbol('customPromisifyArgs') : null;
  19. module.exports = function promisify(orig) {
  20. if (typeof orig !== 'function') {
  21. var error = new TypeError('The "original" argument must be of type function');
  22. error.name = 'TypeError [ERR_INVALID_ARG_TYPE]';
  23. error.code = 'ERR_INVALID_ARG_TYPE';
  24. throw error;
  25. }
  26. if (hasSymbols && orig[kCustomPromisifiedSymbol]) {
  27. var customFunction = orig[kCustomPromisifiedSymbol];
  28. if (typeof customFunction !== 'function') {
  29. throw new TypeError('The [util.promisify.custom] property must be a function');
  30. }
  31. Object.defineProperty(customFunction, kCustomPromisifiedSymbol, {
  32. configurable: true,
  33. enumerable: false,
  34. value: customFunction,
  35. writable: false
  36. });
  37. return customFunction;
  38. }
  39. // Names to create an object from in case the callback receives multiple
  40. // arguments, e.g. ['stdout', 'stderr'] for child_process.exec.
  41. var argumentNames = orig[kCustomPromisifyArgsSymbol];
  42. var promisified = function fn() {
  43. var args = $slice(arguments);
  44. var self = this; // eslint-disable-line no-invalid-this
  45. return new Promise(function (resolve, reject) {
  46. orig.apply(self, $concat(args, function (err) {
  47. var values = arguments.length > 1 ? $slice(arguments, 1) : [];
  48. if (err) {
  49. reject(err);
  50. } else if (typeof argumentNames !== 'undefined' && values.length > 1) {
  51. var obj = {};
  52. $forEach(argumentNames, function (name, index) {
  53. obj[name] = values[index];
  54. });
  55. resolve(obj);
  56. } else {
  57. resolve(values[0]);
  58. }
  59. }));
  60. });
  61. };
  62. promisified.__proto__ = orig.__proto__; // eslint-disable-line no-proto
  63. Object.defineProperty(promisified, kCustomPromisifiedSymbol, {
  64. configurable: true,
  65. enumerable: false,
  66. value: promisified,
  67. writable: false
  68. });
  69. return Object.defineProperties(promisified, getOwnPropertyDescriptors(orig));
  70. };
  71. module.exports.custom = kCustomPromisifiedSymbol;
  72. module.exports.customPromisifyArgs = kCustomPromisifyArgsSymbol;