// 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, ArrayPrototypePop, Error, ErrorCaptureStackTrace, FunctionPrototypeBind, NumberIsSafeInteger, ObjectDefineProperties, ObjectDefineProperty, ObjectGetOwnPropertyDescriptors, ObjectKeys, ObjectSetPrototypeOf, ObjectValues, ReflectApply, StringPrototypeToWellFormed, } = primordials; const { ErrnoException, ExceptionWithHostPort, codes: { ERR_FALSY_VALUE_REJECTION, ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE, }, isErrorStackTraceLimitWritable, } = require('internal/errors'); const { format, formatWithOptions, inspect, stripVTControlCharacters, } = require('internal/util/inspect'); const { debuglog } = require('internal/util/debuglog'); const { validateFunction, validateNumber, validateString, validateOneOf, } = require('internal/validators'); const types = require('internal/util/types'); const binding = internalBinding('util'); const { deprecate, getSystemErrorMap, getSystemErrorName: internalErrorName, promisify, defineLazyProperties, } = require('internal/util'); let abortController; function lazyAbortController() { abortController ??= require('internal/abort_controller'); return abortController; } let internalDeepEqual; /** * @param {string} code * @returns {string} */ function escapeStyleCode(code) { return `\u001b[${code}m`; } /** * @param {string | string[]} format * @param {string} text * @returns {string} */ function styleText(format, text) { validateString(text, 'text'); if (ArrayIsArray(format)) { let left = ''; let right = ''; for (const key of format) { const formatCodes = inspect.colors[key]; if (formatCodes == null) { validateOneOf(key, 'format', ObjectKeys(inspect.colors)); } left += escapeStyleCode(formatCodes[0]); right = `${escapeStyleCode(formatCodes[1])}${right}`; } return `${left}${text}${right}`; } const formatCodes = inspect.colors[format]; if (formatCodes == null) { validateOneOf(format, 'format', ObjectKeys(inspect.colors)); } return `${escapeStyleCode(formatCodes[0])}${text}${escapeStyleCode(formatCodes[1])}`; } /** * 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_', { __proto__: null, value: superCtor, writable: true, configurable: true, }); ObjectSetPrototypeOf(ctor.prototype, superCtor.prototype); } const callbackifyOnRejected = (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.HideStackFramesError(reason); ErrorCaptureStackTrace(reason, callbackifyOnRejected); } return cb(reason); }; /** * @template {(...args: any[]) => Promise} T * @param {T} original * @returns {T extends (...args: infer TArgs) => Promise ? * ((...params: [...TArgs, ((err: Error, ret: TReturn) => any)]) => void) : * never * } */ function callbackify(original) { validateFunction(original, '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 = ArrayPrototypePop(args); validateFunction(maybeCb, 'last argument'); const cb = FunctionPrototypeBind(maybeCb, this); // 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'; } const propertiesValues = ObjectValues(descriptors); for (let i = 0; i < propertiesValues.length; i++) { // We want to use null-prototype objects to not rely on globally mutable // %Object.prototype%. ObjectSetPrototypeOf(propertiesValues[i], null); } ObjectDefineProperties(callbackified, descriptors); return callbackified; } /** * @param {number} err * @returns {string} */ 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); } function _errnoException(...args) { if (isErrorStackTraceLimitWritable()) { const limit = Error.stackTraceLimit; Error.stackTraceLimit = 0; const e = new ErrnoException(...args); Error.stackTraceLimit = limit; ErrorCaptureStackTrace(e, _exceptionWithHostPort); return e; } return new ErrnoException(...args); } function _exceptionWithHostPort(...args) { if (isErrorStackTraceLimitWritable()) { const limit = Error.stackTraceLimit; Error.stackTraceLimit = 0; const e = new ExceptionWithHostPort(...args); Error.stackTraceLimit = limit; ErrorCaptureStackTrace(e, _exceptionWithHostPort); return e; } return new ExceptionWithHostPort(...args); } /** * Parses the content of a `.env` file. * @param {string} content * @returns {Record} */ function parseEnv(content) { validateString(content, 'content'); return binding.parseEnv(content); } // Keep the `exports =` so that various functions can still be monkeypatched module.exports = { _errnoException, _exceptionWithHostPort, callbackify, debug: debuglog, debuglog, deprecate, format, styleText, formatWithOptions, getSystemErrorMap, getSystemErrorName, inherits, inspect, isArray: deprecate(ArrayIsArray, 'The `util.isArray` API is deprecated. Please use `Array.isArray()` instead.', 'DEP0044'), isDeepStrictEqual(a, b) { if (internalDeepEqual === undefined) { internalDeepEqual = require('internal/util/comparisons') .isDeepStrictEqual; } return internalDeepEqual(a, b); }, promisify, stripVTControlCharacters, toUSVString(input) { return StringPrototypeToWellFormed(`${input}`); }, get transferableAbortSignal() { return lazyAbortController().transferableAbortSignal; }, get transferableAbortController() { return lazyAbortController().transferableAbortController; }, get aborted() { return lazyAbortController().aborted; }, types, parseEnv, }; defineLazyProperties( module.exports, 'internal/util/parse_args/parse_args', ['parseArgs'], ); defineLazyProperties( module.exports, 'internal/encoding', ['TextDecoder', 'TextEncoder'], ); defineLazyProperties( module.exports, 'internal/mime', ['MIMEType', 'MIMEParams'], );