mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 05:32:09 +03:00
337 lines
9.2 KiB
TypeScript
337 lines
9.2 KiB
TypeScript
// Loaded from https://deno.land/std@0.101.0/node/util.ts
|
|
|
|
|
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
|
import { promisify } from "./_util/_util_promisify.ts";
|
|
import { callbackify } from "./_util/_util_callbackify.ts";
|
|
import { ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE, errorMap } from "./_errors.ts";
|
|
import * as types from "./_util/_util_types.ts";
|
|
export { callbackify, promisify, types };
|
|
|
|
const NumberIsSafeInteger = Number.isSafeInteger;
|
|
|
|
const DEFAULT_INSPECT_OPTIONS = {
|
|
showHidden: false,
|
|
depth: 2,
|
|
colors: false,
|
|
customInspect: true,
|
|
showProxy: false,
|
|
maxArrayLength: 100,
|
|
maxStringLength: Infinity,
|
|
breakLength: 80,
|
|
compact: 3,
|
|
sorted: false,
|
|
getters: false,
|
|
};
|
|
|
|
inspect.defaultOptions = DEFAULT_INSPECT_OPTIONS;
|
|
inspect.custom = Deno.customInspect;
|
|
|
|
// TODO(schwarzkopfb): make it in-line with Node's implementation
|
|
// Ref: https://nodejs.org/dist/latest-v14.x/docs/api/util.html#util_util_inspect_object_options
|
|
// deno-lint-ignore no-explicit-any
|
|
export function inspect(object: unknown, ...opts: any): string {
|
|
// In Node.js, strings should be enclosed in single quotes.
|
|
// TODO(uki00a): Strings in objects and arrays should also be enclosed in single quotes.
|
|
if (typeof object === "string" && !object.includes("'")) {
|
|
return `'${object}'`;
|
|
}
|
|
opts = { ...DEFAULT_INSPECT_OPTIONS, ...opts };
|
|
return Deno.inspect(object, {
|
|
depth: opts.depth,
|
|
iterableLimit: opts.maxArrayLength,
|
|
compact: !!opts.compact,
|
|
sorted: !!opts.sorted,
|
|
showProxy: !!opts.showProxy,
|
|
});
|
|
}
|
|
|
|
/** @deprecated - use `Array.isArray()` instead. */
|
|
export function isArray(value: unknown): boolean {
|
|
return Array.isArray(value);
|
|
}
|
|
|
|
/** @deprecated - use `typeof value === "boolean" || value instanceof Boolean` instead. */
|
|
export function isBoolean(value: unknown): boolean {
|
|
return typeof value === "boolean" || value instanceof Boolean;
|
|
}
|
|
|
|
/** @deprecated - use `value === null` instead. */
|
|
export function isNull(value: unknown): boolean {
|
|
return value === null;
|
|
}
|
|
|
|
/** @deprecated - use `value === null || value === undefined` instead. */
|
|
export function isNullOrUndefined(value: unknown): boolean {
|
|
return value === null || value === undefined;
|
|
}
|
|
|
|
/** @deprecated - use `typeof value === "number" || value instanceof Number` instead. */
|
|
export function isNumber(value: unknown): boolean {
|
|
return typeof value === "number" || value instanceof Number;
|
|
}
|
|
|
|
/** @deprecated - use `typeof value === "string" || value instanceof String` instead. */
|
|
export function isString(value: unknown): boolean {
|
|
return typeof value === "string" || value instanceof String;
|
|
}
|
|
|
|
/** @deprecated - use `typeof value === "symbol"` instead. */
|
|
export function isSymbol(value: unknown): boolean {
|
|
return typeof value === "symbol";
|
|
}
|
|
|
|
/** @deprecated - use `value === undefined` instead. */
|
|
export function isUndefined(value: unknown): boolean {
|
|
return value === undefined;
|
|
}
|
|
|
|
/** @deprecated - use `value !== null && typeof value === "object"` instead. */
|
|
export function isObject(value: unknown): boolean {
|
|
return value !== null && typeof value === "object";
|
|
}
|
|
|
|
/** @deprecated - use `e instanceof Error` instead. */
|
|
export function isError(e: unknown): boolean {
|
|
return e instanceof Error;
|
|
}
|
|
|
|
/** @deprecated - use `typeof value === "function"` instead. */
|
|
export function isFunction(value: unknown): boolean {
|
|
return typeof value === "function";
|
|
}
|
|
|
|
/** @deprecated - use `value instanceof RegExp` instead. */
|
|
export function isRegExp(value: unknown): boolean {
|
|
return value instanceof RegExp;
|
|
}
|
|
|
|
/** @deprecated - use `value === null || (typeof value !== "object" && typeof value !== "function")` instead. */
|
|
export function isPrimitive(value: unknown): boolean {
|
|
return (
|
|
value === null || (typeof value !== "object" && typeof value !== "function")
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a system error name from an error code number.
|
|
* @param code error code number
|
|
*/
|
|
export function getSystemErrorName(code: number): string | undefined {
|
|
if (typeof code !== "number") {
|
|
throw new ERR_INVALID_ARG_TYPE("err", "number", code);
|
|
}
|
|
if (code >= 0 || !NumberIsSafeInteger(code)) {
|
|
throw new ERR_OUT_OF_RANGE("err", "a negative integer", code);
|
|
}
|
|
return errorMap.get(code)?.[0];
|
|
}
|
|
|
|
/**
|
|
* https://nodejs.org/api/util.html#util_util_deprecate_fn_msg_code
|
|
* @param _code This implementation of deprecate won't apply the deprecation code
|
|
*/
|
|
// deno-lint-ignore no-explicit-any
|
|
export function deprecate<T extends (...args: any) => any>(
|
|
fn: T,
|
|
msg: string,
|
|
_code?: string,
|
|
): (...args: Parameters<T>) => ReturnType<T> {
|
|
return function (...args) {
|
|
console.warn(msg);
|
|
return fn.apply(undefined, args);
|
|
};
|
|
}
|
|
|
|
function circularRemover(): (key: string, value: unknown) => unknown {
|
|
const seen = new WeakSet();
|
|
return (_key, value) => {
|
|
if (typeof value === "object" && value !== null) {
|
|
if (seen.has(value)) {
|
|
return;
|
|
}
|
|
seen.add(value);
|
|
}
|
|
return value;
|
|
};
|
|
}
|
|
|
|
function formatString(str: string) {
|
|
return `"${str.replace(/\\/, "\\\\").replace(/"/g, '\\"')}"`;
|
|
}
|
|
|
|
function thingToString(
|
|
thing: unknown,
|
|
maxDepth?: number,
|
|
depth = 1,
|
|
): string {
|
|
let result = "";
|
|
if (typeof thing === "bigint") {
|
|
return thing + "n";
|
|
}
|
|
if (
|
|
typeof thing === "undefined" || typeof thing === "number" ||
|
|
typeof thing === "boolean" || typeof thing === "symbol" || thing === null
|
|
) {
|
|
return String(thing);
|
|
}
|
|
if (typeof thing === "function") {
|
|
return `[Function ${thing.name || "(anonymous)"}]`;
|
|
}
|
|
if (typeof thing === "string") {
|
|
return formatString(thing);
|
|
}
|
|
if (Array.isArray(thing)) {
|
|
if (depth === maxDepth) {
|
|
return "[Array]";
|
|
}
|
|
result += "[";
|
|
const en = Object.entries(thing);
|
|
for (let i = 0; i < en.length; i++) {
|
|
const [key, value] = en[i];
|
|
if (isNaN(Number(key))) {
|
|
result += `${key}: `;
|
|
}
|
|
result += thingToString(value, maxDepth, depth + 1);
|
|
if (i !== en.length - 1) {
|
|
result += ", ";
|
|
}
|
|
}
|
|
result += "]";
|
|
return result;
|
|
}
|
|
if (depth === maxDepth) {
|
|
return "[Object]";
|
|
}
|
|
const en = Object.entries(thing as Record<string, unknown>);
|
|
result += "{ ";
|
|
for (let i = 0; i < en.length; i++) {
|
|
const [key, value] = en[i];
|
|
result += `${key}: ${thingToString(value, maxDepth, depth + 1)}`;
|
|
if (i !== en.length - 1) {
|
|
result += ", ";
|
|
}
|
|
}
|
|
result += " }";
|
|
return result;
|
|
}
|
|
|
|
function toReplace(specifier: string, value: unknown): string {
|
|
if (specifier === "%s") {
|
|
return thingToString(value, 2);
|
|
}
|
|
if (specifier === "%d") {
|
|
if (typeof value === "bigint") {
|
|
return value + "n";
|
|
}
|
|
return Number(value).toString();
|
|
}
|
|
if (specifier === "%i") {
|
|
if (typeof value === "bigint") {
|
|
return value + "n";
|
|
}
|
|
return parseInt(value as string).toString();
|
|
}
|
|
if (specifier === "%f") {
|
|
return parseFloat(value as string).toString();
|
|
}
|
|
if (specifier === "%j") {
|
|
return JSON.stringify(value, circularRemover());
|
|
}
|
|
if (specifier === "%o" || specifier === "%O") {
|
|
return thingToString(value);
|
|
}
|
|
if (specifier === "%c") {
|
|
return "";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
export function format(input: string, ...args: unknown[]) {
|
|
const replacement: [number, string][] = [];
|
|
const regex = /%(s|d|i|f|j|o|O|c)/g;
|
|
let i = 0;
|
|
let arr: RegExpExecArray | null = null;
|
|
while ((arr = regex.exec(input)) !== null && i < args.length) {
|
|
replacement.push([arr["index"], toReplace(arr[0], args[i])]);
|
|
i++;
|
|
}
|
|
let result = "";
|
|
let last = 0;
|
|
for (let i = 0; i < replacement.length; i++) {
|
|
const item = replacement[i];
|
|
result += input.slice(last, item[0]);
|
|
result += item[1];
|
|
last = item[0] + 2;
|
|
}
|
|
result += input.slice(last);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* https://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor
|
|
* @param ctor Constructor function which needs to inherit the prototype.
|
|
* @param superCtor Constructor function to inherit prototype from.
|
|
*/
|
|
export function inherits<T, U>(
|
|
ctor: new (...args: unknown[]) => T,
|
|
superCtor: new (...args: unknown[]) => U,
|
|
) {
|
|
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,
|
|
);
|
|
}
|
|
Object.defineProperty(ctor, "super_", {
|
|
value: superCtor,
|
|
writable: true,
|
|
configurable: true,
|
|
});
|
|
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
|
|
}
|
|
|
|
import { _TextDecoder, _TextEncoder } from "./_utils.ts";
|
|
|
|
/** The global TextDecoder */
|
|
export type TextDecoder = import("./_utils.ts")._TextDecoder;
|
|
export const TextDecoder = _TextDecoder;
|
|
|
|
/** The global TextEncoder */
|
|
export type TextEncoder = import("./_utils.ts")._TextEncoder;
|
|
export const TextEncoder = _TextEncoder;
|
|
|
|
export default {
|
|
inspect,
|
|
isArray,
|
|
isBoolean,
|
|
isNull,
|
|
isNullOrUndefined,
|
|
isNumber,
|
|
isString,
|
|
isSymbol,
|
|
isUndefined,
|
|
isObject,
|
|
isError,
|
|
isFunction,
|
|
isRegExp,
|
|
isPrimitive,
|
|
getSystemErrorName,
|
|
deprecate,
|
|
callbackify,
|
|
promisify,
|
|
inherits,
|
|
types,
|
|
TextDecoder,
|
|
TextEncoder,
|
|
};
|