| // 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<any>} T |
| * @param {T} original |
| * @returns {T extends (...args: infer TArgs) => Promise<infer TReturn> ? |
| * ((...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<string, string>} |
| */ |
| 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'], |
| ); |