| // Copyright Joyent, Inc. and other Node contributors. |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a |
| // copy of this software and associated documentation files (the |
| // "Software"), to deal in the Software without restriction, including |
| // without limitation the rights to use, copy, modify, merge, publish, |
| // distribute, sublicense, and/or sell copies of the Software, and to permit |
| // persons to whom the Software is furnished to do so, subject to the |
| // following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included |
| // in all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| 'use strict'; |
| |
| const { |
| ArrayIsArray, |
| Error, |
| NumberIsSafeInteger, |
| ObjectDefineProperties, |
| ObjectDefineProperty, |
| ObjectGetOwnPropertyDescriptors, |
| ObjectKeys, |
| ObjectPrototypeToString, |
| ObjectSetPrototypeOf, |
| ReflectApply, |
| } = primordials; |
| |
| const { |
| codes: { |
| ERR_FALSY_VALUE_REJECTION, |
| ERR_INVALID_ARG_TYPE, |
| ERR_OUT_OF_RANGE |
| }, |
| errnoException, |
| exceptionWithHostPort, |
| hideStackFrames |
| } = require('internal/errors'); |
| const { |
| format, |
| formatWithOptions, |
| inspect |
| } = require('internal/util/inspect'); |
| const { debuglog } = require('internal/util/debuglog'); |
| const { validateNumber } = require('internal/validators'); |
| const { TextDecoder, TextEncoder } = require('internal/encoding'); |
| const { isBuffer } = require('buffer').Buffer; |
| const types = require('internal/util/types'); |
| |
| const { |
| deprecate, |
| getSystemErrorName: internalErrorName, |
| promisify |
| } = require('internal/util'); |
| |
| let internalDeepEqual; |
| |
| function isBoolean(arg) { |
| return typeof arg === 'boolean'; |
| } |
| |
| function isNull(arg) { |
| return arg === null; |
| } |
| |
| function isNullOrUndefined(arg) { |
| return arg === null || arg === undefined; |
| } |
| |
| function isNumber(arg) { |
| return typeof arg === 'number'; |
| } |
| |
| function isString(arg) { |
| return typeof arg === 'string'; |
| } |
| |
| function isSymbol(arg) { |
| return typeof arg === 'symbol'; |
| } |
| |
| function isUndefined(arg) { |
| return arg === undefined; |
| } |
| |
| function isObject(arg) { |
| return arg !== null && typeof arg === 'object'; |
| } |
| |
| function isError(e) { |
| return ObjectPrototypeToString(e) === '[object Error]' || e instanceof Error; |
| } |
| |
| function isFunction(arg) { |
| return typeof arg === 'function'; |
| } |
| |
| function isPrimitive(arg) { |
| return arg === null || |
| (typeof arg !== 'object' && typeof arg !== 'function'); |
| } |
| |
| function pad(n) { |
| return n.toString().padStart(2, '0'); |
| } |
| |
| const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', |
| 'Oct', 'Nov', 'Dec']; |
| |
| // 26 Feb 16:19:34 |
| function timestamp() { |
| const d = new Date(); |
| const time = [pad(d.getHours()), |
| pad(d.getMinutes()), |
| pad(d.getSeconds())].join(':'); |
| return [d.getDate(), months[d.getMonth()], time].join(' '); |
| } |
| |
| let console; |
| // Log is just a thin wrapper to console.log that prepends a timestamp |
| function log(...args) { |
| if (!console) { |
| console = require('internal/console/global'); |
| } |
| console.log('%s - %s', timestamp(), format(...args)); |
| } |
| |
| /** |
| * Inherit the prototype methods from one constructor into another. |
| * |
| * The Function.prototype.inherits from lang.js rewritten as a standalone |
| * function (not on Function.prototype). NOTE: If this file is to be loaded |
| * during bootstrapping this function needs to be rewritten using some native |
| * functions as prototype setup using normal JavaScript does not work as |
| * expected during bootstrapping (see mirror.js in r114903). |
| * |
| * @param {function} ctor Constructor function which needs to inherit the |
| * prototype. |
| * @param {function} superCtor Constructor function to inherit prototype from. |
| * @throws {TypeError} Will error if either constructor is null, or if |
| * the super constructor lacks a prototype. |
| */ |
| function inherits(ctor, superCtor) { |
| |
| if (ctor === undefined || ctor === null) |
| throw new ERR_INVALID_ARG_TYPE('ctor', 'Function', ctor); |
| |
| if (superCtor === undefined || superCtor === null) |
| throw new ERR_INVALID_ARG_TYPE('superCtor', 'Function', superCtor); |
| |
| if (superCtor.prototype === undefined) { |
| throw new ERR_INVALID_ARG_TYPE('superCtor.prototype', |
| 'Object', superCtor.prototype); |
| } |
| ObjectDefineProperty(ctor, 'super_', { |
| value: superCtor, |
| writable: true, |
| configurable: true |
| }); |
| ObjectSetPrototypeOf(ctor.prototype, superCtor.prototype); |
| } |
| |
| function _extend(target, source) { |
| // Don't do anything if source isn't an object |
| if (source === null || typeof source !== 'object') return target; |
| |
| const keys = ObjectKeys(source); |
| let i = keys.length; |
| while (i--) { |
| target[keys[i]] = source[keys[i]]; |
| } |
| return target; |
| } |
| |
| const callbackifyOnRejected = hideStackFrames((reason, cb) => { |
| // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). |
| // Because `null` is a special error value in callbacks which means "no error |
| // occurred", we error-wrap so the callback consumer can distinguish between |
| // "the promise rejected with null" or "the promise fulfilled with undefined". |
| if (!reason) { |
| reason = new ERR_FALSY_VALUE_REJECTION(reason); |
| } |
| return cb(reason); |
| }); |
| |
| function callbackify(original) { |
| if (typeof original !== 'function') { |
| throw new ERR_INVALID_ARG_TYPE('original', 'Function', original); |
| } |
| |
| // We DO NOT return the promise as it gives the user a false sense that |
| // the promise is actually somehow related to the callback's execution |
| // and that the callback throwing will reject the promise. |
| function callbackified(...args) { |
| const maybeCb = args.pop(); |
| if (typeof maybeCb !== 'function') { |
| throw new ERR_INVALID_ARG_TYPE('last argument', 'Function', maybeCb); |
| } |
| const cb = (...args) => { ReflectApply(maybeCb, this, args); }; |
| // In true node style we process the callback on `nextTick` with all the |
| // implications (stack, `uncaughtException`, `async_hooks`) |
| ReflectApply(original, this, args) |
| .then((ret) => process.nextTick(cb, null, ret), |
| (rej) => process.nextTick(callbackifyOnRejected, rej, cb)); |
| } |
| |
| const descriptors = ObjectGetOwnPropertyDescriptors(original); |
| // It is possible to manipulate a functions `length` or `name` property. This |
| // guards against the manipulation. |
| if (typeof descriptors.length.value === 'number') { |
| descriptors.length.value++; |
| } |
| if (typeof descriptors.name.value === 'string') { |
| descriptors.name.value += 'Callbackified'; |
| } |
| ObjectDefineProperties(callbackified, descriptors); |
| return callbackified; |
| } |
| |
| function getSystemErrorName(err) { |
| validateNumber(err, 'err'); |
| if (err >= 0 || !NumberIsSafeInteger(err)) { |
| throw new ERR_OUT_OF_RANGE('err', 'a negative integer', err); |
| } |
| return internalErrorName(err); |
| } |
| |
| // Keep the `exports =` so that various functions can still be monkeypatched |
| module.exports = { |
| _errnoException: errnoException, |
| _exceptionWithHostPort: exceptionWithHostPort, |
| _extend, |
| callbackify, |
| debuglog, |
| deprecate, |
| format, |
| formatWithOptions, |
| getSystemErrorName, |
| inherits, |
| inspect, |
| isArray: ArrayIsArray, |
| isBoolean, |
| isBuffer, |
| isDeepStrictEqual(a, b) { |
| if (internalDeepEqual === undefined) { |
| internalDeepEqual = require('internal/util/comparisons') |
| .isDeepStrictEqual; |
| } |
| return internalDeepEqual(a, b); |
| }, |
| isNull, |
| isNullOrUndefined, |
| isNumber, |
| isString, |
| isSymbol, |
| isUndefined, |
| isRegExp: types.isRegExp, |
| isObject, |
| isDate: types.isDate, |
| isError, |
| isFunction, |
| isPrimitive, |
| log, |
| promisify, |
| TextDecoder, |
| TextEncoder, |
| types |
| }; |