implementation.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. 'use strict';
  2. var forEach = require('for-each');
  3. var $Object = require('es-object-atoms');
  4. var isES5 = typeof $Object.defineProperty === 'function';
  5. var gPO = $Object.getPrototypeOf;
  6. var sPO = $Object.setPrototypeOf;
  7. // eslint-disable-next-line global-require
  8. var hasProto = require('has-proto')() || (typeof gPO === 'function' && gPO([]) === Array.prototype);
  9. if (!isES5 || !hasProto) {
  10. throw new TypeError('util.promisify requires a true ES5+ environment, that also supports `__proto__` and/or `Object.getPrototypeOf`');
  11. }
  12. var getOwnPropertyDescriptors = require('object.getownpropertydescriptors');
  13. if (typeof Promise !== 'function') {
  14. throw new TypeError('`Promise` must be globally available for util.promisify to work.');
  15. }
  16. var GetIntrinsic = require('get-intrinsic');
  17. var oDP = $Object.defineProperty;
  18. var $Promise = GetIntrinsic('%Promise%');
  19. var $TypeError = TypeError;
  20. var safeConcat = require('safe-array-concat');
  21. var callBind = require('call-bind');
  22. var callBound = require('call-bound');
  23. var defineDataProperty = require('define-data-property');
  24. var $slice = callBound('Array.prototype.slice');
  25. var hasSymbols = require('has-symbols/shams')();
  26. // eslint-disable-next-line no-restricted-properties
  27. var kCustomPromisifiedSymbol = hasSymbols ? Symbol['for']('nodejs.util.promisify.custom') : null;
  28. var kCustomPromisifyArgsSymbol = hasSymbols ? Symbol('customPromisifyArgs') : null;
  29. module.exports = function promisify(orig) {
  30. if (typeof orig !== 'function') {
  31. var error = new $TypeError('The "original" argument must be of type function');
  32. error.code = 'ERR_INVALID_ARG_TYPE';
  33. error.toString = function value() {
  34. return this.name + '[' + this.code + ']: ' + this.message;
  35. };
  36. throw error;
  37. }
  38. if (hasSymbols && orig[kCustomPromisifiedSymbol]) {
  39. var customFunction = orig[kCustomPromisifiedSymbol];
  40. if (typeof customFunction !== 'function') {
  41. var customError = $TypeError('The [util.promisify.custom] property must be of type function.');
  42. customError.code = 'ERR_INVALID_ARG_TYPE';
  43. customError.toString = function value() {
  44. return this.name + '[' + this.code + ']: ' + this.message;
  45. };
  46. throw customError;
  47. }
  48. defineDataProperty(
  49. customFunction,
  50. kCustomPromisifiedSymbol,
  51. customFunction,
  52. true,
  53. true,
  54. null,
  55. true
  56. );
  57. return customFunction;
  58. }
  59. // Names to create an object from in case the callback receives multiple
  60. // arguments, e.g. ['stdout', 'stderr'] for child_process.exec.
  61. var argumentNames = orig[kCustomPromisifyArgsSymbol];
  62. var origApply = callBind.apply(orig);
  63. var promisified = function fn() {
  64. var args = $slice(arguments);
  65. var self = this; // eslint-disable-line no-invalid-this
  66. return new $Promise(function (resolve, reject) {
  67. origApply(self, safeConcat(args, function (err) {
  68. var values = arguments.length > 1 ? $slice(arguments, 1) : [];
  69. if (err) {
  70. reject(err);
  71. } else if (typeof argumentNames !== 'undefined' && values.length > 1) {
  72. var obj = {};
  73. forEach(argumentNames, function (name, index) {
  74. obj[name] = values[index];
  75. });
  76. resolve(obj);
  77. } else {
  78. resolve(values[0]);
  79. }
  80. }));
  81. });
  82. };
  83. if (typeof sPO === 'function' && typeof gPO === 'function') {
  84. sPO(promisified, gPO(orig));
  85. } else {
  86. promisified.__proto__ = orig.__proto__; // eslint-disable-line no-proto
  87. }
  88. defineDataProperty(promisified, kCustomPromisifiedSymbol, promisified, true, true, null, true);
  89. var descriptors = getOwnPropertyDescriptors(orig);
  90. forEach(descriptors, function (k, v) {
  91. try {
  92. oDP(promisified, k, v);
  93. } catch (e) {
  94. // handle nonconfigurable function properties
  95. }
  96. });
  97. return promisified;
  98. };
  99. module.exports.custom = kCustomPromisifiedSymbol;
  100. module.exports.customPromisifyArgs = kCustomPromisifyArgsSymbol;