• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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