text: 'use strict';
  
  var isES5 = typeof Object.defineProperty === 'function'
  	&& typeof Object.defineProperties === 'function'
  	&& typeof Object.getPrototypeOf === 'function'
  	&& typeof Object.setPrototypeOf === 'function';
  
  if (!isES5) {
  	throw new TypeError('util.promisify requires a true ES5 environment');
  }
  
  var getOwnPropertyDescriptors = require('object.getownpropertydescriptors');
  
  if (typeof Promise !== 'function') {
  	throw new TypeError('`Promise` must be globally available for util.promisify to work.');
  }
  
  var slice = Function.call.bind(Array.prototype.slice);
  var concat = Function.call.bind(Array.prototype.concat);
  var forEach = Function.call.bind(Array.prototype.forEach);
  
  var hasSymbols = typeof Symbol === 'function' && typeof Symbol('') === 'symbol';
  
  var kCustomPromisifiedSymbol = hasSymbols ? Symbol('util.promisify.custom') : null;
  var kCustomPromisifyArgsSymbol = hasSymbols ? Symbol('customPromisifyArgs') : null;
  
  module.exports = function promisify(orig) {
  	if (typeof orig !== 'function') {
  		var error = new TypeError('The "original" argument must be of type function');
  		error.name = 'TypeError [ERR_INVALID_ARG_TYPE]';
  		error.code = 'ERR_INVALID_ARG_TYPE';
  		throw error;
  	}
  
  	if (hasSymbols && orig[kCustomPromisifiedSymbol]) {
  		var customFunction = orig[kCustomPromisifiedSymbol];
  		if (typeof customFunction !== 'function') {
  			throw new TypeError('The [util.promisify.custom] property must be a function');
  		}
  		Object.defineProperty(customFunction, kCustomPromisifiedSymbol, {
  			configurable: true,
  			enumerable: false,
  			value: customFunction,
  			writable: false
  		});
  		return customFunction;
  	}
  
  	// Names to create an object from in case the callback receives multiple
  	// arguments, e.g. ['stdout', 'stderr'] for child_process.exec.
  	var argumentNames = orig[kCustomPromisifyArgsSymbol];
  
  	var promisified = function fn() {
  		var args = slice(arguments);
  		var self = this; // eslint-disable-line no-invalid-this
  		return new Promise(function (resolve, reject) {
  			orig.apply(self, concat(args, function (err) {
  				var values = arguments.length > 1 ? slice(arguments, 1) : [];
  				if (err) {
  					reject(err);
  				} else if (typeof argumentNames !== 'undefined' && values.length > 1) {
  					var obj = {};
  					forEach(argumentNames, function (name, index) {
  						obj[name] = values[index];
  					});
  					resolve(obj);
  				} else {
  					resolve(values[0]);
  				}
  			}));
  		});
  	};
  
  	Object.setPrototypeOf(promisified, Object.getPrototypeOf(orig));
  
  	Object.defineProperty(promisified, kCustomPromisifiedSymbol, {
  		configurable: true,
  		enumerable: false,
  		value: promisified,
  		writable: false
  	});
  	return Object.defineProperties(promisified, getOwnPropertyDescriptors(orig));
  };
  
  module.exports.custom = kCustomPromisifiedSymbol;
  module.exports.customPromisifyArgs = kCustomPromisifyArgsSymbol;
  