1'use strict'; 2// Flags: --expose-internals 3const common = require('../common'); 4const assert = require('assert'); 5const fs = require('fs'); 6const vm = require('vm'); 7const { promisify } = require('util'); 8const { customPromisifyArgs } = require('internal/util'); 9 10const stat = promisify(fs.stat); 11 12{ 13 const promise = stat(__filename); 14 assert(promise instanceof Promise); 15 promise.then(common.mustCall((value) => { 16 assert.deepStrictEqual(value, fs.statSync(__filename)); 17 })); 18} 19 20{ 21 const promise = stat('/dontexist'); 22 promise.catch(common.mustCall((error) => { 23 assert(error.message.includes('ENOENT: no such file or directory, stat')); 24 })); 25} 26 27{ 28 function fn() {} 29 30 function promisifedFn() {} 31 fn[promisify.custom] = promisifedFn; 32 assert.strictEqual(promisify(fn), promisifedFn); 33 assert.strictEqual(promisify(promisify(fn)), promisifedFn); 34} 35 36{ 37 function fn() {} 38 39 function promisifiedFn() {} 40 41 // util.promisify.custom is a shared symbol which can be accessed 42 // as `Symbol.for("nodejs.util.promisify.custom")`. 43 const kCustomPromisifiedSymbol = Symbol.for('nodejs.util.promisify.custom'); 44 fn[kCustomPromisifiedSymbol] = promisifiedFn; 45 46 assert.strictEqual(kCustomPromisifiedSymbol, promisify.custom); 47 assert.strictEqual(promisify(fn), promisifiedFn); 48 assert.strictEqual(promisify(promisify(fn)), promisifiedFn); 49} 50 51{ 52 function fn() {} 53 fn[promisify.custom] = 42; 54 assert.throws( 55 () => promisify(fn), 56 { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' } 57 ); 58} 59 60{ 61 const firstValue = 5; 62 const secondValue = 17; 63 64 function fn(callback) { 65 callback(null, firstValue, secondValue); 66 } 67 68 fn[customPromisifyArgs] = ['first', 'second']; 69 70 promisify(fn)().then(common.mustCall((obj) => { 71 assert.deepStrictEqual(obj, { first: firstValue, second: secondValue }); 72 })); 73} 74 75{ 76 const fn = vm.runInNewContext('(function() {})'); 77 assert.notStrictEqual(Object.getPrototypeOf(promisify(fn)), 78 Function.prototype); 79} 80 81{ 82 function fn(callback) { 83 callback(null, 'foo', 'bar'); 84 } 85 promisify(fn)().then(common.mustCall((value) => { 86 assert.deepStrictEqual(value, 'foo'); 87 })); 88} 89 90{ 91 function fn(callback) { 92 callback(null); 93 } 94 promisify(fn)().then(common.mustCall((value) => { 95 assert.strictEqual(value, undefined); 96 })); 97} 98 99{ 100 function fn(callback) { 101 callback(); 102 } 103 promisify(fn)().then(common.mustCall((value) => { 104 assert.strictEqual(value, undefined); 105 })); 106} 107 108{ 109 function fn(err, val, callback) { 110 callback(err, val); 111 } 112 promisify(fn)(null, 42).then(common.mustCall((value) => { 113 assert.strictEqual(value, 42); 114 })); 115} 116 117{ 118 function fn(err, val, callback) { 119 callback(err, val); 120 } 121 promisify(fn)(new Error('oops'), null).catch(common.mustCall((err) => { 122 assert.strictEqual(err.message, 'oops'); 123 })); 124} 125 126{ 127 function fn(err, val, callback) { 128 callback(err, val); 129 } 130 131 (async () => { 132 const value = await promisify(fn)(null, 42); 133 assert.strictEqual(value, 42); 134 })().then(common.mustCall()); 135} 136 137{ 138 const o = {}; 139 const fn = promisify(function(cb) { 140 141 cb(null, this === o); 142 }); 143 144 o.fn = fn; 145 146 o.fn().then(common.mustCall((val) => assert(val))); 147} 148 149{ 150 const err = new Error('Should not have called the callback with the error.'); 151 const stack = err.stack; 152 153 const fn = promisify(function(cb) { 154 cb(null); 155 cb(err); 156 }); 157 158 (async () => { 159 await fn(); 160 await Promise.resolve(); 161 return assert.strictEqual(stack, err.stack); 162 })().then(common.mustCall()); 163} 164 165{ 166 function c() { } 167 const a = promisify(function() { }); 168 const b = promisify(a); 169 assert.notStrictEqual(c, a); 170 assert.strictEqual(a, b); 171} 172 173{ 174 let errToThrow; 175 const thrower = promisify(function(a, b, c, cb) { 176 errToThrow = new Error(); 177 throw errToThrow; 178 }); 179 thrower(1, 2, 3) 180 .then(assert.fail) 181 .then(assert.fail, (e) => assert.strictEqual(e, errToThrow)); 182} 183 184{ 185 const err = new Error(); 186 187 const a = promisify((cb) => cb(err))(); 188 const b = promisify(() => { throw err; })(); 189 190 Promise.all([ 191 a.then(assert.fail, function(e) { 192 assert.strictEqual(err, e); 193 }), 194 b.then(assert.fail, function(e) { 195 assert.strictEqual(err, e); 196 }), 197 ]); 198} 199 200[undefined, null, true, 0, 'str', {}, [], Symbol()].forEach((input) => { 201 assert.throws( 202 () => promisify(input), 203 { 204 code: 'ERR_INVALID_ARG_TYPE', 205 name: 'TypeError', 206 message: 'The "original" argument must be of type function.' + 207 common.invalidArgTypeHelper(input) 208 }); 209}); 210