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 22'use strict'; 23 24const { 25 ArrayIsArray, 26 Date, 27 Error, 28 NumberIsSafeInteger, 29 ObjectDefineProperties, 30 ObjectDefineProperty, 31 ObjectGetOwnPropertyDescriptors, 32 ObjectKeys, 33 ObjectPrototypeToString, 34 ObjectSetPrototypeOf, 35 ReflectApply, 36} = primordials; 37 38const { 39 codes: { 40 ERR_FALSY_VALUE_REJECTION, 41 ERR_INVALID_ARG_TYPE, 42 ERR_OUT_OF_RANGE 43 }, 44 errnoException, 45 exceptionWithHostPort, 46 hideStackFrames 47} = require('internal/errors'); 48const { 49 format, 50 formatWithOptions, 51 inspect 52} = require('internal/util/inspect'); 53const { debuglog } = require('internal/util/debuglog'); 54const { validateNumber } = require('internal/validators'); 55const { TextDecoder, TextEncoder } = require('internal/encoding'); 56const { isBuffer } = require('buffer').Buffer; 57const types = require('internal/util/types'); 58 59const { 60 deprecate, 61 getSystemErrorMap, 62 getSystemErrorName: internalErrorName, 63 promisify, 64 toUSVString, 65} = require('internal/util'); 66 67let internalDeepEqual; 68 69/** 70 * @deprecated since v4.0.0 71 * @param {any} arg 72 * @returns {arg is boolean} 73 */ 74function isBoolean(arg) { 75 return typeof arg === 'boolean'; 76} 77 78/** 79 * @deprecated since v4.0.0 80 * @param {any} arg 81 * @returns {arg is null} 82 */ 83function isNull(arg) { 84 return arg === null; 85} 86 87/** 88 * @deprecated since v4.0.0 89 * @param {any} arg 90 * @returns {arg is (null | undefined)} 91 */ 92function isNullOrUndefined(arg) { 93 return arg === null || arg === undefined; 94} 95 96/** 97 * @deprecated since v4.0.0 98 * @param {any} arg 99 * @returns {arg is number} 100 */ 101function isNumber(arg) { 102 return typeof arg === 'number'; 103} 104 105/** 106 * @param {any} arg 107 * @returns {arg is string} 108 */ 109function isString(arg) { 110 return typeof arg === 'string'; 111} 112 113/** 114 * @deprecated since v4.0.0 115 * @param {any} arg 116 * @returns {arg is symbol} 117 */ 118function isSymbol(arg) { 119 return typeof arg === 'symbol'; 120} 121 122/** 123 * @deprecated since v4.0.0 124 * @param {any} arg 125 * @returns {arg is undefined} 126 */ 127function isUndefined(arg) { 128 return arg === undefined; 129} 130 131/** 132 * @deprecated since v4.0.0 133 * @param {any} arg 134 * @returns {a is NonNullable<object>} 135 */ 136function isObject(arg) { 137 return arg !== null && typeof arg === 'object'; 138} 139 140/** 141 * @deprecated since v4.0.0 142 * @param {any} e 143 * @returns {arg is Error} 144 */ 145function isError(e) { 146 return ObjectPrototypeToString(e) === '[object Error]' || e instanceof Error; 147} 148 149/** 150 * @deprecated since v4.0.0 151 * @param {any} arg 152 * @returns {arg is Function} 153 */ 154function isFunction(arg) { 155 return typeof arg === 'function'; 156} 157 158/** 159 * @deprecated since v4.0.0 160 * @param {any} arg 161 * @returns {arg is (boolean | null | number | string | symbol | undefined)} 162 */ 163function isPrimitive(arg) { 164 return arg === null || 165 (typeof arg !== 'object' && typeof arg !== 'function'); 166} 167 168/** 169 * @param {number} n 170 * @returns {string} 171 */ 172function pad(n) { 173 return n.toString().padStart(2, '0'); 174} 175 176const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 177 'Oct', 'Nov', 'Dec']; 178 179/** 180 * @returns {string} 26 Feb 16:19:34 181 */ 182function timestamp() { 183 const d = new Date(); 184 const time = [pad(d.getHours()), 185 pad(d.getMinutes()), 186 pad(d.getSeconds())].join(':'); 187 return [d.getDate(), months[d.getMonth()], time].join(' '); 188} 189 190let console; 191/** 192 * Log is just a thin wrapper to console.log that prepends a timestamp 193 * @deprecated since v6.0.0 194 * @type {(...args: any[]) => void} 195 */ 196function log(...args) { 197 if (!console) { 198 console = require('internal/console/global'); 199 } 200 console.log('%s - %s', timestamp(), format(...args)); 201} 202 203/** 204 * Inherit the prototype methods from one constructor into another. 205 * 206 * The Function.prototype.inherits from lang.js rewritten as a standalone 207 * function (not on Function.prototype). NOTE: If this file is to be loaded 208 * during bootstrapping this function needs to be rewritten using some native 209 * functions as prototype setup using normal JavaScript does not work as 210 * expected during bootstrapping (see mirror.js in r114903). 211 * 212 * @param {Function} ctor Constructor function which needs to inherit the 213 * prototype. 214 * @param {Function} superCtor Constructor function to inherit prototype from. 215 * @throws {TypeError} Will error if either constructor is null, or if 216 * the super constructor lacks a prototype. 217 */ 218function inherits(ctor, superCtor) { 219 220 if (ctor === undefined || ctor === null) 221 throw new ERR_INVALID_ARG_TYPE('ctor', 'Function', ctor); 222 223 if (superCtor === undefined || superCtor === null) 224 throw new ERR_INVALID_ARG_TYPE('superCtor', 'Function', superCtor); 225 226 if (superCtor.prototype === undefined) { 227 throw new ERR_INVALID_ARG_TYPE('superCtor.prototype', 228 'Object', superCtor.prototype); 229 } 230 ObjectDefineProperty(ctor, 'super_', { 231 value: superCtor, 232 writable: true, 233 configurable: true 234 }); 235 ObjectSetPrototypeOf(ctor.prototype, superCtor.prototype); 236} 237 238/** 239 * @deprecated since v6.0.0 240 * @template T 241 * @template S 242 * @param {T} target 243 * @param {S} source 244 * @returns {S extends null ? T : (T & S)} 245 */ 246function _extend(target, source) { 247 // Don't do anything if source isn't an object 248 if (source === null || typeof source !== 'object') return target; 249 250 const keys = ObjectKeys(source); 251 let i = keys.length; 252 while (i--) { 253 target[keys[i]] = source[keys[i]]; 254 } 255 return target; 256} 257 258const callbackifyOnRejected = hideStackFrames((reason, cb) => { 259 // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). 260 // Because `null` is a special error value in callbacks which means "no error 261 // occurred", we error-wrap so the callback consumer can distinguish between 262 // "the promise rejected with null" or "the promise fulfilled with undefined". 263 if (!reason) { 264 reason = new ERR_FALSY_VALUE_REJECTION(reason); 265 } 266 return cb(reason); 267}); 268 269/** 270 * @template {(...args: any[]) => Promise<any>} T 271 * @param {T} original 272 * @returns {T extends (...args: infer TArgs) => Promise<infer TReturn> ? 273 * ((...params: [...TArgs, ((err: Error, ret: TReturn) => any)]) => void) : 274 * never 275 * } 276 */ 277function callbackify(original) { 278 if (typeof original !== 'function') { 279 throw new ERR_INVALID_ARG_TYPE('original', 'Function', original); 280 } 281 282 // We DO NOT return the promise as it gives the user a false sense that 283 // the promise is actually somehow related to the callback's execution 284 // and that the callback throwing will reject the promise. 285 function callbackified(...args) { 286 const maybeCb = args.pop(); 287 if (typeof maybeCb !== 'function') { 288 throw new ERR_INVALID_ARG_TYPE('last argument', 'Function', maybeCb); 289 } 290 const cb = (...args) => { ReflectApply(maybeCb, this, args); }; 291 // In true node style we process the callback on `nextTick` with all the 292 // implications (stack, `uncaughtException`, `async_hooks`) 293 ReflectApply(original, this, args) 294 .then((ret) => process.nextTick(cb, null, ret), 295 (rej) => process.nextTick(callbackifyOnRejected, rej, cb)); 296 } 297 298 const descriptors = ObjectGetOwnPropertyDescriptors(original); 299 // It is possible to manipulate a functions `length` or `name` property. This 300 // guards against the manipulation. 301 if (typeof descriptors.length.value === 'number') { 302 descriptors.length.value++; 303 } 304 if (typeof descriptors.name.value === 'string') { 305 descriptors.name.value += 'Callbackified'; 306 } 307 ObjectDefineProperties(callbackified, descriptors); 308 return callbackified; 309} 310 311/** 312 * @param {number} err 313 * @returns {string} 314 */ 315function getSystemErrorName(err) { 316 validateNumber(err, 'err'); 317 if (err >= 0 || !NumberIsSafeInteger(err)) { 318 throw new ERR_OUT_OF_RANGE('err', 'a negative integer', err); 319 } 320 return internalErrorName(err); 321} 322 323// Keep the `exports =` so that various functions can still be monkeypatched 324module.exports = { 325 _errnoException: errnoException, 326 _exceptionWithHostPort: exceptionWithHostPort, 327 _extend, 328 callbackify, 329 debug: debuglog, 330 debuglog, 331 deprecate, 332 format, 333 formatWithOptions, 334 getSystemErrorMap, 335 getSystemErrorName, 336 inherits, 337 inspect, 338 isArray: ArrayIsArray, 339 isBoolean, 340 isBuffer, 341 isDeepStrictEqual(a, b) { 342 if (internalDeepEqual === undefined) { 343 internalDeepEqual = require('internal/util/comparisons') 344 .isDeepStrictEqual; 345 } 346 return internalDeepEqual(a, b); 347 }, 348 isNull, 349 isNullOrUndefined, 350 isNumber, 351 isString, 352 isSymbol, 353 isUndefined, 354 isRegExp: types.isRegExp, 355 isObject, 356 isDate: types.isDate, 357 isError, 358 isFunction, 359 isPrimitive, 360 log, 361 promisify, 362 toUSVString, 363 TextDecoder, 364 TextEncoder, 365 types 366}; 367