WIP: bootstrap and partial real Solana watcher implementation

This commit is contained in:
2026-08-16 09:17:45 +00:00
commit dc23412c3f
7232 changed files with 1687637 additions and 0 deletions

View File

@@ -0,0 +1,476 @@
/**
* @fileoverview A utility for retrying failed async method calls.
*/
/* global setTimeout, clearTimeout */
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const MAX_TASK_TIMEOUT = 60000;
const MAX_TASK_DELAY = 100;
const MAX_CONCURRENCY = 1000;
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
/**
* Logs a message to the console if the DEBUG environment variable is set.
* @param {string} message The message to log.
* @returns {void}
*/
function debug(message) {
if (globalThis?.process?.env.DEBUG === "@hwc/retry") {
console.debug(message);
}
}
/*
* The following logic has been extracted from graceful-fs.
*
* The ISC License
*
* Copyright (c) 2011-2023 Isaac Z. Schlueter, Ben Noordhuis, and Contributors
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* Checks if it is time to retry a task based on the timestamp and last attempt time.
* @param {RetryTask} task The task to check.
* @param {number} maxDelay The maximum delay for the queue.
* @returns {boolean} true if it is time to retry, false otherwise.
*/
function isTimeToRetry(task, maxDelay) {
const timeSinceLastAttempt = Date.now() - task.lastAttempt;
const timeSinceStart = Math.max(task.lastAttempt - task.timestamp, 1);
const desiredDelay = Math.min(timeSinceStart * 1.2, maxDelay);
return timeSinceLastAttempt >= desiredDelay;
}
/**
* Checks if it is time to bail out based on the given timestamp.
* @param {RetryTask} task The task to check.
* @param {number} timeout The timeout for the queue.
* @returns {boolean} true if it is time to bail, false otherwise.
*/
function isTimeToBail(task, timeout) {
return task.age > timeout;
}
/**
* Creates a new promise with resolve and reject functions.
* @returns {{promise:Promise<any>, resolve:(value:any) => any, reject: (value:any) => any}} A new promise.
*/
function createPromise() {
if (Promise.withResolvers) {
return Promise.withResolvers();
}
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
if (resolve === undefined || reject === undefined) {
throw new Error("Promise executor did not initialize resolve or reject.");
}
return { promise, resolve, reject };
}
/**
* A class to represent a task in the retry queue.
*/
class RetryTask {
/**
* The unique ID for the task.
* @type {string}
*/
id = Math.random().toString(36).slice(2);
/**
* The function to call.
* @type {Function}
*/
fn;
/**
* The error that was thrown.
* @type {Error}
*/
error;
/**
* The timestamp of the task.
* @type {number}
*/
timestamp = Date.now();
/**
* The timestamp of the last attempt.
* @type {number}
*/
lastAttempt = this.timestamp;
/**
* The resolve function for the promise.
* @type {Function}
*/
resolve;
/**
* The reject function for the promise.
* @type {Function}
*/
reject;
/**
* The AbortSignal to monitor for cancellation.
* @type {AbortSignal|undefined}
*/
signal;
/**
* Creates a new instance.
* @param {Function} fn The function to call.
* @param {Error} error The error that was thrown.
* @param {Function} resolve The resolve function for the promise.
* @param {Function} reject The reject function for the promise.
* @param {AbortSignal|undefined} signal The AbortSignal to monitor for cancellation.
*/
constructor(fn, error, resolve, reject, signal) {
this.fn = fn;
this.error = error;
this.timestamp = Date.now();
this.lastAttempt = Date.now();
this.resolve = resolve;
this.reject = reject;
this.signal = signal;
}
/**
* Gets the age of the task.
* @returns {number} The age of the task in milliseconds.
* @readonly
*/
get age() {
return Date.now() - this.timestamp;
}
}
//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
/**
* A class that manages a queue of retry jobs.
*/
class Retrier {
/**
* Represents the queue for processing tasks.
* @type {Array<RetryTask>}
*/
#retrying = [];
/**
* Represents the queue for pending tasks.
* @type {Array<Function>}
*/
#pending = [];
/**
* The number of tasks currently being processed.
* @type {number}
*/
#working = 0;
/**
* The timeout for the queue.
* @type {number}
*/
#timeout;
/**
* The maximum delay for the queue.
* @type {number}
*/
#maxDelay;
/**
* The setTimeout() timer ID.
* @type {NodeJS.Timeout|undefined}
*/
#timerId;
/**
* The function to call.
* @type {Function}
*/
#check;
/**
* The maximum number of concurrent tasks.
* @type {number}
*/
#concurrency;
/**
* Creates a new instance.
* @param {Function} check The function to call.
* @param {object} [options] The options for the instance.
* @param {number} [options.timeout] The timeout for the queue.
* @param {number} [options.maxDelay] The maximum delay for the queue.
* @param {number} [options.concurrency] The maximum number of concurrent tasks.
*/
constructor(check, { timeout = MAX_TASK_TIMEOUT, maxDelay = MAX_TASK_DELAY, concurrency = MAX_CONCURRENCY } = {}) {
if (typeof check !== "function") {
throw new Error("Missing function to check errors");
}
this.#check = check;
this.#timeout = timeout;
this.#maxDelay = maxDelay;
this.#concurrency = concurrency;
}
/**
* Gets the number of tasks waiting to be retried.
* @returns {number} The number of tasks in the retry queue.
*/
get retrying() {
return this.#retrying.length;
}
/**
* Gets the number of tasks waiting to be processed in the pending queue.
* @returns {number} The number of tasks in the pending queue.
*/
get pending() {
return this.#pending.length;
}
/**
* Gets the number of tasks currently being processed.
* @returns {number} The number of tasks currently being processed.
*/
get working() {
return this.#working;
}
/**
* Calls the function and retries if it fails.
* @param {Function} fn The function to call.
* @param {Object} options The options for the job.
* @param {AbortSignal} [options.signal] The AbortSignal to monitor for cancellation.
* @param {Promise<any>} options.promise The promise to return when the function settles.
* @param {Function} options.resolve The resolve function for the promise.
* @param {Function} options.reject The reject function for the promise.
* @returns {Promise<any>} A promise that resolves when the function is
* called successfully.
*/
#call(fn, { signal, promise, resolve, reject }) {
let result;
try {
result = fn();
} catch (/** @type {any} */ error) {
reject(new Error(`Synchronous error: ${error.message}`, { cause: error }));
return promise;
}
// if the result is not a promise then reject an error
if (!result || typeof result.then !== "function") {
reject(new Error("Result is not a promise."));
return promise;
}
this.#working++;
promise.finally(() => {
this.#working--;
this.#processPending();
})
// `promise.finally` creates a new promise that may be rejected, so it must be handled.
.catch(() => { });
// call the original function and catch any ENFILE or EMFILE errors
Promise.resolve(result)
.then(value => {
debug("Function called successfully without retry.");
resolve(value);
})
.catch(error => {
if (!this.#check(error)) {
reject(error);
return;
}
const task = new RetryTask(fn, error, resolve, reject, signal);
debug(`Function failed, queuing for retry with task ${task.id}.`);
this.#retrying.push(task);
signal?.addEventListener("abort", () => {
debug(`Task ${task.id} was aborted due to AbortSignal.`);
reject(signal.reason);
});
this.#processQueue();
});
return promise;
}
/**
* Adds a new retry job to the queue.
* @template {(...args: unknown[]) => Promise<unknown>} Func
* @template {Awaited<ReturnType<Func>>} RetVal
* @param {Func} fn The function to call.
* @param {object} [options] The options for the job.
* @param {AbortSignal} [options.signal] The AbortSignal to monitor for cancellation.
* @returns {Promise<RetVal>} A promise that resolves when the queue is processed.
*/
retry(fn, { signal } = {}) {
signal?.throwIfAborted();
const { promise, resolve, reject } = createPromise();
this.#pending.push(() => this.#call(fn, { signal, promise, resolve, reject }));
this.#processPending();
return promise;
}
/**
* Processes the pending queue and the retry queue.
* @returns {void}
*/
#processAll() {
if (this.pending) {
this.#processPending();
}
if (this.retrying) {
this.#processQueue();
}
}
/**
* Processes the pending queue to see which tasks can be started.
* @returns {void}
*/
#processPending() {
debug(`Processing pending tasks: ${this.pending} pending, ${this.working} working.`);
const available = this.#concurrency - this.working;
if (available <= 0) {
return;
}
const count = Math.min(this.pending, available);
for (let i = 0; i < count; i++) {
const task = this.#pending.shift();
task?.();
}
debug(`Processed pending tasks: ${this.pending} pending, ${this.working} working.`);
}
/**
* Processes the queue.
* @returns {void}
*/
#processQueue() {
// clear any timer because we're going to check right now
clearTimeout(this.#timerId);
this.#timerId = undefined;
debug(`Processing retry queue: ${this.retrying} retrying, ${this.working} working.`);
const processAgain = () => {
this.#timerId = setTimeout(() => this.#processAll(), 0);
};
// if there's nothing in the queue, we're done
const task = this.#retrying.shift();
if (!task) {
debug("Queue is empty, exiting.");
if (this.pending) {
processAgain();
}
return;
}
// if it's time to bail, then bail
if (isTimeToBail(task, this.#timeout)) {
debug(`Task ${task.id} was abandoned due to timeout.`);
task.reject(task.error);
processAgain();
return;
}
// if it's not time to retry, then wait and try again
if (!isTimeToRetry(task, this.#maxDelay)) {
debug(`Task ${task.id} is not ready to retry, skipping.`);
this.#retrying.push(task);
processAgain();
return;
}
// otherwise, try again
task.lastAttempt = Date.now();
// Promise.resolve needed in case it's a thenable but not a Promise
Promise.resolve(task.fn())
// @ts-ignore because we know it's any
.then(result => {
debug(`Task ${task.id} succeeded after ${task.age}ms.`);
task.resolve(result);
})
// @ts-ignore because we know it's any
.catch(error => {
if (!this.#check(error)) {
debug(`Task ${task.id} failed with non-retryable error: ${error.message}.`);
task.reject(error);
return;
}
// update the task timestamp and push to back of queue to try again
task.lastAttempt = Date.now();
this.#retrying.push(task);
debug(`Task ${task.id} failed, requeueing to try again.`);
})
.finally(() => {
this.#processAll();
});
}
}
export { Retrier };

View File

@@ -0,0 +1,51 @@
/**
* @fileoverview disallow using an async function as a Promise executor
* @author Teddy Katz
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "problem",
docs: {
description:
"Disallow using an async function as a Promise executor",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-async-promise-executor",
},
fixable: null,
schema: [],
messages: {
async: "Promise executor functions should not be async.",
},
},
create(context) {
const sourceCode = context.sourceCode;
return {
"NewExpression[callee.name='Promise'][arguments.0.async=true]"(
node,
) {
if (!sourceCode.isGlobalReference(node.callee)) {
return;
}
context.report({
node: sourceCode.getFirstToken(
node.arguments[0],
token => token.value === "async",
),
messageId: "async",
});
},
};
},
};

View File

@@ -0,0 +1,177 @@
/**
* @fileoverview Rule to disallow unused labels.
* @author Toru Nagashima
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow unused labels",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-unused-labels",
},
schema: [],
fixable: "code",
messages: {
unused: "'{{name}}:' is defined but never used.",
},
},
create(context) {
const sourceCode = context.sourceCode;
let scopeInfo = null;
/**
* Adds a scope info to the stack.
* @param {ASTNode} node A node to add. This is a LabeledStatement.
* @returns {void}
*/
function enterLabeledScope(node) {
scopeInfo = {
label: node.label.name,
used: false,
upper: scopeInfo,
};
}
/**
* Checks if a `LabeledStatement` node is fixable.
* For a node to be fixable, there must be no comments between the label and the body.
* Furthermore, is must be possible to remove the label without turning the body statement into a
* directive after other fixes are applied.
* @param {ASTNode} node The node to evaluate.
* @returns {boolean} Whether or not the node is fixable.
*/
function isFixable(node) {
/*
* Only perform a fix if there are no comments between the label and the body. This will be the case
* when there is exactly one token/comment (the ":") between the label and the body.
*/
if (
sourceCode.getTokenAfter(node.label, {
includeComments: true,
}) !==
sourceCode.getTokenBefore(node.body, { includeComments: true })
) {
return false;
}
// Looking for the node's deepest ancestor which is not a `LabeledStatement`.
let ancestor = node.parent;
while (ancestor.type === "LabeledStatement") {
ancestor = ancestor.parent;
}
if (
ancestor.type === "Program" ||
(ancestor.type === "BlockStatement" &&
astUtils.isFunction(ancestor.parent))
) {
const { body } = node;
if (
body.type === "ExpressionStatement" &&
((body.expression.type === "Literal" &&
typeof body.expression.value === "string") ||
astUtils.isStaticTemplateLiteral(body.expression))
) {
return false; // potential directive
}
}
/*
* Do not fix if removing the label would create an ASI hazard.
* e.g. `foo()\nLABEL: [1].forEach(x => x)` → `foo()\n[1].forEach(x => x)`
* would be parsed as `foo()[1].forEach(x => x)`.
*/
const SAFE_TOKENS_BEFORE = /^[:;{]$/u;
const UNSAFE_FIRST_CHARS = /^[([\-+/`]/u;
const tokenBefore = sourceCode.getTokenBefore(node);
const firstBodyToken = sourceCode.getFirstToken(node.body);
if (
tokenBefore &&
!SAFE_TOKENS_BEFORE.test(tokenBefore.value) &&
UNSAFE_FIRST_CHARS.test(firstBodyToken.value)
) {
return false;
}
return true;
}
/**
* Removes the top of the stack.
* At the same time, this reports the label if it's never used.
* @param {ASTNode} node A node to report. This is a LabeledStatement.
* @returns {void}
*/
function exitLabeledScope(node) {
if (!scopeInfo.used) {
context.report({
node: node.label,
messageId: "unused",
data: node.label,
fix: isFixable(node)
? fixer =>
fixer.removeRange([
node.range[0],
node.body.range[0],
])
: null,
});
}
scopeInfo = scopeInfo.upper;
}
/**
* Marks the label of a given node as used.
* @param {ASTNode} node A node to mark. This is a BreakStatement or
* ContinueStatement.
* @returns {void}
*/
function markAsUsed(node) {
if (!node.label) {
return;
}
const label = node.label.name;
let info = scopeInfo;
while (info) {
if (info.label === label) {
info.used = true;
break;
}
info = info.upper;
}
}
return {
LabeledStatement: enterLabeledScope,
"LabeledStatement:exit": exitLabeledScope,
BreakStatement: markAsUsed,
ContinueStatement: markAsUsed,
};
},
};

View File

@@ -0,0 +1,24 @@
'use strict'
const { register, unregister } = require('../..')
const assert = require('assert')
function setup () {
const obj = { foo: 'bar' }
register(obj, shutdown)
setImmediate(function () {
unregister(obj)
unregister(obj) // twice, this should not throw
})
}
let shutdownCalled = false
function shutdown (obj) {
shutdownCalled = true
}
setup()
process.on('exit', function () {
assert.strictEqual(shutdownCalled, false)
})

View File

@@ -0,0 +1,6 @@
var regenerator = require("./regenerator.js");
var regeneratorAsyncIterator = require("./regeneratorAsyncIterator.js");
function _regeneratorAsyncGen(r, e, t, o, n) {
return new regeneratorAsyncIterator(regenerator().w(r, e, t, o), n || Promise);
}
module.exports = _regeneratorAsyncGen, module.exports.__esModule = true, module.exports["default"] = module.exports;

View File

@@ -0,0 +1,91 @@
/**
* @fileoverview Rule to flag when regex literals are not wrapped in parens
* @author Matt DuVall <http://www.mattduvall.com>
* @deprecated in ESLint v8.53.0
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "wrap-regex",
url: "https://eslint.style/rules/wrap-regex",
},
},
],
},
type: "layout",
docs: {
description: "Require parenthesis around regex literals",
recommended: false,
url: "https://eslint.org/docs/latest/rules/wrap-regex",
},
schema: [],
fixable: "code",
messages: {
requireParens:
"Wrap the regexp literal in parens to disambiguate the slash.",
},
},
create(context) {
const sourceCode = context.sourceCode;
return {
Literal(node) {
const token = sourceCode.getFirstToken(node),
nodeType = token.type;
if (nodeType === "RegularExpression") {
const beforeToken = sourceCode.getTokenBefore(node);
const afterToken = sourceCode.getTokenAfter(node);
const { parent } = node;
if (
parent.type === "MemberExpression" &&
parent.object === node &&
!(
beforeToken &&
beforeToken.value === "(" &&
afterToken &&
afterToken.value === ")"
)
) {
context.report({
node,
messageId: "requireParens",
fix: fixer =>
fixer.replaceText(
node,
`(${sourceCode.getText(node)})`,
),
});
}
}
},
};
},
};

View File

@@ -0,0 +1,807 @@
import { expect, expectTypeOf, test } from "vitest";
import * as z from "zod/v4";
declare const iss: z.core.$ZodIssueCode;
const Test = z.object({
f1: z.number(),
f2: z.string().optional(),
f3: z.string().nullable(),
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
});
// type TestFlattenedErrors = core.inferFlattenedErrors<typeof Test, { message: string; code: number }>;
// type TestFormErrors = core.inferFlattenedErrors<typeof Test>;
const parsed = Test.safeParse({});
test("regular error", () => {
expect(parsed).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"expected": "number",
"code": "invalid_type",
"path": [
"f1"
],
"message": "Invalid input: expected number, received undefined"
},
{
"expected": "string",
"code": "invalid_type",
"path": [
"f3"
],
"message": "Invalid input: expected string, received undefined"
},
{
"expected": "array",
"code": "invalid_type",
"path": [
"f4"
],
"message": "Invalid input: expected array, received undefined"
}
]],
"success": false,
}
`);
});
test(".flatten()", () => {
const flattened = parsed.error!.flatten();
// flattened.
expectTypeOf(flattened).toMatchTypeOf<{
formErrors: string[];
fieldErrors: {
f2?: string[];
f1?: string[];
f3?: string[];
f4?: string[];
};
}>();
expect(flattened).toMatchInlineSnapshot(`
{
"fieldErrors": {
"f1": [
"Invalid input: expected number, received undefined",
],
"f3": [
"Invalid input: expected string, received undefined",
],
"f4": [
"Invalid input: expected array, received undefined",
],
},
"formErrors": [],
}
`);
});
test("custom .flatten()", () => {
type ErrorType = { message: string; code: number };
const flattened = parsed.error!.flatten((iss) => ({
message: iss.message,
code: 1234,
}));
expectTypeOf(flattened).toMatchTypeOf<{
formErrors: ErrorType[];
fieldErrors: {
f2?: ErrorType[];
f1?: ErrorType[];
f3?: ErrorType[];
f4?: ErrorType[];
};
}>();
expect(flattened).toMatchInlineSnapshot(`
{
"fieldErrors": {
"f1": [
{
"code": 1234,
"message": "Invalid input: expected number, received undefined",
},
],
"f3": [
{
"code": 1234,
"message": "Invalid input: expected string, received undefined",
},
],
"f4": [
{
"code": 1234,
"message": "Invalid input: expected array, received undefined",
},
],
},
"formErrors": [],
}
`);
});
test(".format()", () => {
const formatted = parsed.error!.format();
expectTypeOf(formatted).toMatchTypeOf<{
_errors: string[];
f2?: { _errors: string[] };
f1?: { _errors: string[] };
f3?: { _errors: string[] };
f4?: {
[x: number]: {
_errors: string[];
t?: {
_errors: string[];
};
};
_errors: string[];
};
}>();
expect(formatted).toMatchInlineSnapshot(`
{
"_errors": [],
"f1": {
"_errors": [
"Invalid input: expected number, received undefined",
],
},
"f3": {
"_errors": [
"Invalid input: expected string, received undefined",
],
},
"f4": {
"_errors": [
"Invalid input: expected array, received undefined",
],
},
}
`);
});
test("custom .format()", () => {
type ErrorType = { message: string; code: number };
const formatted = parsed.error!.format((iss) => ({
message: iss.message,
code: 1234,
}));
expectTypeOf(formatted).toMatchTypeOf<{
_errors: ErrorType[];
f2?: { _errors: ErrorType[] };
f1?: { _errors: ErrorType[] };
f3?: { _errors: ErrorType[] };
f4?: {
[x: number]: {
_errors: ErrorType[];
t?: {
_errors: ErrorType[];
};
};
_errors: ErrorType[];
};
}>();
expect(formatted).toMatchInlineSnapshot(`
{
"_errors": [],
"f1": {
"_errors": [
{
"code": 1234,
"message": "Invalid input: expected number, received undefined",
},
],
},
"f3": {
"_errors": [
{
"code": 1234,
"message": "Invalid input: expected string, received undefined",
},
],
},
"f4": {
"_errors": [
{
"code": 1234,
"message": "Invalid input: expected array, received undefined",
},
],
},
}
`);
});
test("all errors", () => {
const propertySchema = z.string();
const schema = z
.object({
a: propertySchema,
b: propertySchema,
})
.refine(
(val) => {
return val.a === val.b;
},
{ message: "Must be equal" }
);
const r1 = schema.safeParse({
a: "asdf",
b: "qwer",
});
expect(z.core.flattenError(r1.error!)).toEqual({
formErrors: ["Must be equal"],
fieldErrors: {},
});
const r2 = schema.safeParse({
a: null,
b: null,
});
// const error = _error as z.ZodError;
expect(z.core.flattenError(r2.error!)).toMatchInlineSnapshot(`
{
"fieldErrors": {
"a": [
"Invalid input: expected string, received null",
],
"b": [
"Invalid input: expected string, received null",
],
},
"formErrors": [],
}
`);
expect(z.core.flattenError(r2.error!, (iss) => iss.message.toUpperCase())).toMatchInlineSnapshot(`
{
"fieldErrors": {
"a": [
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
],
"b": [
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
],
},
"formErrors": [],
}
`);
// Test identity
expect(z.core.flattenError(r2.error!, (i: z.ZodIssue) => i)).toMatchInlineSnapshot(`
{
"fieldErrors": {
"a": [
{
"code": "invalid_type",
"expected": "string",
"message": "Invalid input: expected string, received null",
"path": [
"a",
],
},
],
"b": [
{
"code": "invalid_type",
"expected": "string",
"message": "Invalid input: expected string, received null",
"path": [
"b",
],
},
],
},
"formErrors": [],
}
`);
// Test mapping
const f1 = z.core.flattenError(r2.error!, (i: z.ZodIssue) => i.message.length);
expect(f1).toMatchInlineSnapshot(`
{
"fieldErrors": {
"a": [
45,
],
"b": [
45,
],
},
"formErrors": [],
}
`);
// expect(f1.fieldErrors.a![0]).toEqual("Invalid input: expected string".length);
// expect(f1).toMatchObject({
// formErrors: [],
// fieldErrors: {
// a: ["Invalid input: expected string".length],
// b: ["Invalid input: expected string".length],
// },
// });
});
const schema = z.strictObject({
username: z.string().brand<"username">(),
favoriteNumbers: z.array(z.number()),
nesting: z.object({
a: z.string(),
}),
});
const result = schema.safeParse({
username: 1234,
favoriteNumbers: [1234, "4567"],
nesting: {
a: 123,
},
extra: 1234,
});
const tree = z.treeifyError(result.error!);
expectTypeOf(tree).toEqualTypeOf<{
errors: string[];
properties?: {
username?: {
errors: string[];
};
favoriteNumbers?: {
errors: string[];
items?: {
errors: string[];
}[];
};
nesting?: {
errors: string[];
properties?: {
a?: {
errors: string[];
};
};
};
};
}>();
test("z.treeifyError", () => {
expect(tree).toMatchInlineSnapshot(`
{
"errors": [
"Unrecognized key: "extra"",
],
"properties": {
"favoriteNumbers": {
"errors": [],
"items": [
,
{
"errors": [
"Invalid input: expected number, received string",
],
},
],
},
"nesting": {
"errors": [],
"properties": {
"a": {
"errors": [
"Invalid input: expected string, received number",
],
},
},
},
"username": {
"errors": [
"Invalid input: expected string, received number",
],
},
},
}
`);
});
test("z.treeifyError 2", () => {
const schema = z.strictObject({
name: z.string(),
logLevel: z.union([z.string(), z.number()]),
env: z.literal(["production", "development"]),
});
const data = {
name: 1000,
logLevel: false,
extra: 1000,
};
const result = schema.safeParse(data);
const err = z.treeifyError(result.error!);
expect(err).toMatchInlineSnapshot(`
{
"errors": [
"Unrecognized key: "extra"",
],
"properties": {
"env": {
"errors": [
"Invalid option: expected one of "production"|"development"",
],
},
"logLevel": {
"errors": [
"Invalid input: expected string, received boolean",
"Invalid input: expected number, received boolean",
],
},
"name": {
"errors": [
"Invalid input: expected string, received number",
],
},
},
}
`);
});
test("z.prettifyError", () => {
expect(z.prettifyError(result.error!)).toMatchInlineSnapshot(`
"✖ Unrecognized key: "extra"
✖ Invalid input: expected string, received number
→ at username
✖ Invalid input: expected number, received string
→ at favoriteNumbers[1]
✖ Invalid input: expected string, received number
→ at nesting.a"
`);
});
test("z.toDotPath", () => {
expect(z.core.toDotPath(["a", "b", 0, "c"])).toMatchInlineSnapshot(`"a.b[0].c"`);
expect(z.core.toDotPath(["a", Symbol("b"), 0, "c"])).toMatchInlineSnapshot(`"a["Symbol(b)"][0].c"`);
// Test with periods in keys
expect(z.core.toDotPath(["user.name", "first.last"])).toMatchInlineSnapshot(`"["user.name"]["first.last"]"`);
// Test with special characters
expect(z.core.toDotPath(["user", "$special", Symbol("#symbol")])).toMatchInlineSnapshot(
`"user.$special["Symbol(#symbol)"]"`
);
// Test with dots and quotes
expect(z.core.toDotPath(["search", `query("foo.bar"="abc")`])).toMatchInlineSnapshot(
`"search["query(\\"foo.bar\\"=\\"abc\\")"]"`
);
// Test with newlines
expect(z.core.toDotPath(["search", `foo\nbar`])).toMatchInlineSnapshot(`"search["foo\\nbar"]"`);
// Test with empty strings
expect(z.core.toDotPath(["", "empty"])).toMatchInlineSnapshot(`".empty"`);
// Test with array indices
expect(z.core.toDotPath(["items", 0, 1, 2])).toMatchInlineSnapshot(`"items[0][1][2]"`);
// Test with mixed path elements
expect(z.core.toDotPath(["users", "user.config", 0, "settings.theme"])).toMatchInlineSnapshot(
`"users["user.config"][0]["settings.theme"]"`
);
// Test with square brackets in keys
expect(z.core.toDotPath(["data[0]", "value"])).toMatchInlineSnapshot(`"["data[0]"].value"`);
// Test with empty path
expect(z.core.toDotPath([])).toMatchInlineSnapshot(`""`);
});
test("inheritance", () => {
const e1 = new z.ZodError([]);
expect(e1).toBeInstanceOf(z.core.$ZodError);
expect(e1).toBeInstanceOf(z.ZodError);
// expect(e1).not.toBeInstanceOf(Error);
const e2 = new z.ZodRealError([]);
expect(e2).toBeInstanceOf(z.ZodError);
expect(e2).toBeInstanceOf(z.ZodRealError);
expect(e2).toBeInstanceOf(Error);
});
test("disc union treeify/format", () => {
const schema = z.discriminatedUnion(
"foo",
[
z.object({
foo: z.literal("x"),
x: z.string(),
}),
z.object({
foo: z.literal("y"),
y: z.string(),
}),
],
{
error: "Invalid discriminator",
}
);
const error = schema.safeParse({ foo: "invalid" }).error;
expect(z.treeifyError(error!)).toMatchInlineSnapshot(`
{
"errors": [],
"properties": {
"foo": {
"errors": [
"Invalid discriminator",
],
},
},
}
`);
expect(z.prettifyError(error!)).toMatchInlineSnapshot(`
"✖ Invalid discriminator
→ at foo"
`);
expect(z.formatError(error!)).toMatchInlineSnapshot(`
{
"_errors": [],
"foo": {
"_errors": [
"Invalid discriminator",
],
},
}
`);
});
test("update message after adding issues", () => {
const e = new z.ZodError([]);
e.addIssue({
code: "custom",
message: "message",
input: "asdf",
path: [],
});
expect(e.message).toMatchInlineSnapshot(`
"[
{
"code": "custom",
"message": "message",
"input": "asdf",
"path": []
}
]"
`);
e.addIssue({
code: "custom",
message: "message",
input: "asdf",
path: [],
});
expect(e.message).toMatchInlineSnapshot(`
"[
{
"code": "custom",
"message": "message",
"input": "asdf",
"path": []
},
{
"code": "custom",
"message": "message",
"input": "asdf",
"path": []
}
]"
`);
});
test("z.formatError nested union preserves parent path", () => {
const syntheticError = new z.ZodError([
{
code: "invalid_union",
path: ["parent"],
message: "Invalid input",
errors: [
[
{
code: "invalid_type",
expected: "string",
path: [],
message: "Expected string",
input: {},
},
],
[
{
code: "invalid_union",
path: ["child"],
message: "Invalid input",
errors: [
[
{
code: "invalid_type",
expected: "string",
path: [],
message: "Expected string",
input: true,
},
],
[
{
code: "invalid_type",
expected: "number",
path: [],
message: "Expected number",
input: true,
},
],
],
},
],
],
},
] as any);
const formatted: any = z.formatError(syntheticError);
// "child" must be nested under "parent", not at root
expect(formatted).not.toHaveProperty("child");
expect(formatted).toHaveProperty("parent");
expect(formatted.parent).toHaveProperty("child");
expect(formatted.parent.child._errors).toContain("Expected string");
expect(formatted.parent.child._errors).toContain("Expected number");
expect(formatted.parent._errors).toContain("Expected string");
});
test("z.treeifyError nested union preserves parent path", () => {
// When a nested invalid_union appears inside another invalid_union,
// the inner errors must stay nested under their parent path, not flatten to root.
const syntheticError = new z.ZodError([
{
code: "invalid_union",
path: ["parent"],
message: "Invalid input",
errors: [
[
{
code: "invalid_type",
expected: "string",
path: [],
message: "Expected string",
input: {},
},
],
[
{
code: "invalid_union",
path: ["child"],
message: "Invalid input",
errors: [
[
{
code: "invalid_type",
expected: "string",
path: [],
message: "Expected string",
input: true,
},
],
[
{
code: "invalid_type",
expected: "number",
path: [],
message: "Expected number",
input: true,
},
],
],
},
],
],
},
] as any);
const tree: any = z.treeifyError(syntheticError);
// "child" must be nested under "parent", not at root
expect(tree.properties).not.toHaveProperty("child");
expect(tree.properties).toHaveProperty("parent");
expect(tree.properties.parent.properties).toHaveProperty("child");
expect(tree.properties.parent.properties.child.errors).toContain("Expected string");
expect(tree.properties.parent.properties.child.errors).toContain("Expected number");
expect(tree.properties.parent.errors).toContain("Expected string");
});
test("z.treeifyError deeply nested union (4 levels) preserves full path", () => {
// a > b > c > d — each level wrapped in an invalid_union
const syntheticError = new z.ZodError([
{
code: "invalid_union",
path: ["a"],
message: "Invalid input",
errors: [
[
{
code: "invalid_union",
path: ["b"],
message: "Invalid input",
errors: [
[
{
code: "invalid_union",
path: ["c"],
message: "Invalid input",
errors: [
[
{
code: "invalid_type",
expected: "string",
path: ["d"],
message: "Expected string",
input: 123,
},
],
],
},
],
],
},
],
],
},
] as any);
const tree: any = z.treeifyError(syntheticError);
// The full path must be preserved: a.b.c.d
expect(tree.properties).toHaveProperty("a");
expect(tree.properties).not.toHaveProperty("b");
expect(tree.properties).not.toHaveProperty("c");
const lvlA = tree.properties.a;
expect(lvlA.properties).toHaveProperty("b");
const lvlB = lvlA.properties.b;
expect(lvlB.properties).toHaveProperty("c");
const lvlC = lvlB.properties.c;
expect(lvlC.properties).toHaveProperty("d");
expect(lvlC.properties.d.errors).toContain("Expected string");
});
test("z.treeifyError nested union with real schema", () => {
const innerUnion = z.union([
z.object({ type: z.literal("a"), value: z.string() }),
z.object({ type: z.literal("b"), value: z.number() }),
]);
const schema = z.string().or(
z.object({
settings: z.object({ name: z.string() }).and(innerUnion),
})
);
const result = schema.safeParse({
settings: { name: 123, type: "x", value: true },
});
expect(result.success).toBe(false);
if (!result.success) {
const tree: any = z.treeifyError(result.error);
// All settings-related errors should be under "settings", not at root
expect(tree.properties).toHaveProperty("settings");
const settingsProperties = tree.properties.settings.properties ?? {};
for (const key of Object.keys(settingsProperties)) {
// Every sub-property under settings should NOT also appear at root
if (key !== "settings") {
expect(tree.properties).not.toHaveProperty(key);
}
}
}
});

View File

@@ -0,0 +1,239 @@
{
"name": "vitest",
"type": "module",
"version": "4.1.10",
"description": "Next generation testing framework powered by Vite",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
"homepage": "https://vitest.dev",
"repository": {
"type": "git",
"url": "git+https://github.com/vitest-dev/vitest.git",
"directory": "packages/vitest"
},
"bugs": {
"url": "https://github.com/vitest-dev/vitest/issues"
},
"keywords": [
"vite",
"vitest",
"test",
"jest"
],
"sideEffects": false,
"imports": {
"#module-evaluator": {
"types": "./dist/module-evaluator.d.ts",
"default": "./dist/module-evaluator.js"
},
"#nodejs-worker-loader": "./dist/nodejs-worker-loader.js"
},
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./index.d.cts",
"default": "./index.cjs"
}
},
"./browser": {
"types": "./browser/context.d.ts",
"default": "./browser/context.js"
},
"./package.json": "./package.json",
"./optional-types.js": {
"types": "./optional-types.d.ts"
},
"./optional-runtime-types.js": {
"types": "./optional-runtime-types.d.ts"
},
"./src/*": "./src/*",
"./globals": {
"types": "./globals.d.ts"
},
"./jsdom": {
"types": "./jsdom.d.ts"
},
"./importMeta": {
"types": "./importMeta.d.ts"
},
"./import-meta": {
"types": "./import-meta.d.ts"
},
"./node": {
"types": "./dist/node.d.ts",
"default": "./dist/node.js"
},
"./internal/browser": {
"types": "./dist/browser.d.ts",
"default": "./dist/browser.js"
},
"./runners": {
"types": "./dist/runners.d.ts",
"default": "./dist/runners.js"
},
"./suite": {
"types": "./dist/suite.d.ts",
"default": "./dist/suite.js"
},
"./environments": {
"types": "./dist/environments.d.ts",
"default": "./dist/environments.js"
},
"./config": {
"types": "./config.d.ts",
"require": "./dist/config.cjs",
"default": "./dist/config.js"
},
"./coverage": {
"types": "./coverage.d.ts",
"default": "./dist/coverage.js"
},
"./reporters": {
"types": "./dist/reporters.d.ts",
"default": "./dist/reporters.js"
},
"./snapshot": {
"types": "./dist/snapshot.d.ts",
"default": "./dist/snapshot.js"
},
"./runtime": {
"types": "./dist/runtime.d.ts",
"default": "./dist/runtime.js"
},
"./worker": {
"types": "./worker.d.ts",
"default": "./dist/worker.js"
}
},
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"vitest": "./vitest.mjs"
},
"files": [
"*.cjs",
"*.d.cts",
"*.d.ts",
"*.mjs",
"bin",
"browser",
"dist"
],
"engines": {
"node": "^20.0.0 || ^22.0.0 || >=24.0.0"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
"happy-dom": "*",
"jsdom": "*",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"@vitest/browser-preview": "4.1.10",
"@vitest/coverage-istanbul": "4.1.10",
"@vitest/browser-playwright": "4.1.10",
"@vitest/browser-webdriverio": "4.1.10",
"@vitest/coverage-v8": "4.1.10",
"@vitest/ui": "4.1.10"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
"@opentelemetry/api": {
"optional": true
},
"@types/node": {
"optional": true
},
"@vitest/browser-playwright": {
"optional": true
},
"@vitest/browser-preview": {
"optional": true
},
"@vitest/browser-webdriverio": {
"optional": true
},
"@vitest/coverage-istanbul": {
"optional": true
},
"@vitest/coverage-v8": {
"optional": true
},
"@vitest/ui": {
"optional": true
},
"happy-dom": {
"optional": true
},
"jsdom": {
"optional": true
},
"vite": {
"optional": false
}
},
"dependencies": {
"es-module-lexer": "^2.0.0",
"expect-type": "^1.3.0",
"magic-string": "^0.30.21",
"obug": "^2.1.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
"std-env": "^4.0.0-rc.1",
"tinybench": "^2.9.0",
"tinyexec": "^1.0.2",
"tinyglobby": "^0.2.15",
"tinyrainbow": "^3.1.0",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"why-is-node-running": "^2.3.0",
"@vitest/expect": "4.1.10",
"@vitest/mocker": "4.1.10",
"@vitest/pretty-format": "4.1.10",
"@vitest/runner": "4.1.10",
"@vitest/spy": "4.1.10",
"@vitest/snapshot": "4.1.10",
"@vitest/utils": "4.1.10"
},
"devDependencies": {
"@antfu/install-pkg": "^1.1.0",
"@bomb.sh/tab": "^0.0.14",
"@edge-runtime/vm": "^5.0.0",
"@jridgewell/trace-mapping": "0.3.31",
"@opentelemetry/api": "^1.9.0",
"@sinonjs/fake-timers": "15.0.0",
"@types/estree": "^1.0.8",
"@types/istanbul-lib-coverage": "^2.0.6",
"@types/istanbul-reports": "^3.0.4",
"@types/jsdom": "^27.0.0",
"@types/node": "^24.12.0",
"@types/picomatch": "^4.0.2",
"@types/prompts": "^2.4.9",
"@types/sinonjs__fake-timers": "^15.0.1",
"acorn": "8.11.3",
"acorn-walk": "^8.3.5",
"birpc": "^4.0.0",
"cac": "^6.7.14",
"empathic": "^2.0.0",
"flatted": "^3.4.2",
"happy-dom": "^20.8.3",
"jsdom": "^27.4.0",
"local-pkg": "^1.1.2",
"mime": "^4.1.0",
"prompts": "^2.4.2",
"strip-literal": "^3.1.0",
"tinyhighlight": "^0.3.2",
"ws": "^8.19.0"
},
"scripts": {
"build": "premove dist && rollup -c",
"dev": "NODE_OPTIONS=\"--max-old-space-size=8192\" rollup -c --watch -m inline"
}
}

View File

@@ -0,0 +1,175 @@
"use strict";
// THIS CODE WAS AUTOMATICALLY GENERATED
// DO NOT EDIT THIS CODE BY HAND
// SEE https://typescript-eslint.io/users/configs
//
// For developers working in the typescript-eslint monorepo:
// You can regenerate it using `pnpm run generate-configs`
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const base_1 = __importDefault(require("./base"));
const eslint_recommended_1 = __importDefault(require("./eslint-recommended"));
/**
* Enables each the rules provided as a part of typescript-eslint. Note that many rules are not applicable in all codebases, or are meant to be configured.
* @see {@link https://typescript-eslint.io/users/configs#all}
*/
exports.default = (plugin, parser) => [
(0, base_1.default)(plugin, parser),
(0, eslint_recommended_1.default)(plugin, parser),
{
name: 'typescript-eslint/all',
rules: {
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/array-type': 'error',
'@typescript-eslint/await-thenable': 'error',
'@typescript-eslint/ban-ts-comment': 'error',
'@typescript-eslint/ban-tslint-comment': 'error',
'@typescript-eslint/class-literal-property-style': 'error',
'class-methods-use-this': 'off',
'@typescript-eslint/class-methods-use-this': 'error',
'@typescript-eslint/consistent-generic-constructors': 'error',
'@typescript-eslint/consistent-indexed-object-style': 'error',
'consistent-return': 'off',
'@typescript-eslint/consistent-return': 'error',
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/consistent-type-definitions': 'error',
'@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
'default-param-last': 'off',
'@typescript-eslint/default-param-last': 'error',
'dot-notation': 'off',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/explicit-member-accessibility': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'error',
'init-declarations': 'off',
'@typescript-eslint/init-declarations': 'error',
'max-params': 'off',
'@typescript-eslint/max-params': 'error',
'@typescript-eslint/member-ordering': 'error',
'@typescript-eslint/method-signature-style': 'error',
'@typescript-eslint/naming-convention': 'error',
'no-array-constructor': 'off',
'@typescript-eslint/no-array-constructor': 'error',
'@typescript-eslint/no-array-delete': 'error',
'@typescript-eslint/no-base-to-string': 'error',
'@typescript-eslint/no-confusing-non-null-assertion': 'error',
'@typescript-eslint/no-confusing-void-expression': 'error',
'@typescript-eslint/no-deprecated': 'error',
'no-dupe-class-members': 'off',
'@typescript-eslint/no-dupe-class-members': 'error',
'@typescript-eslint/no-duplicate-enum-values': 'error',
'@typescript-eslint/no-duplicate-type-constituents': 'error',
'@typescript-eslint/no-dynamic-delete': 'error',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'error',
'@typescript-eslint/no-empty-object-type': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
'@typescript-eslint/no-extraneous-class': 'error',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-for-in-array': 'error',
'no-implied-eval': 'off',
'@typescript-eslint/no-implied-eval': 'error',
'@typescript-eslint/no-import-type-side-effects': 'error',
'@typescript-eslint/no-inferrable-types': 'error',
'no-invalid-this': 'off',
'@typescript-eslint/no-invalid-this': 'error',
'@typescript-eslint/no-invalid-void-type': 'error',
'no-magic-numbers': 'off',
'@typescript-eslint/no-magic-numbers': 'error',
'@typescript-eslint/no-meaningless-void-operator': 'error',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-misused-spread': 'error',
'@typescript-eslint/no-mixed-enums': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-redundant-type-constituents': 'error',
'@typescript-eslint/no-require-imports': 'error',
'@typescript-eslint/no-restricted-types': 'error',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
'@typescript-eslint/no-this-alias': 'error',
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
'@typescript-eslint/no-unnecessary-condition': 'error',
'@typescript-eslint/no-unnecessary-parameter-property-assignment': 'error',
'@typescript-eslint/no-unnecessary-qualifier': 'error',
'@typescript-eslint/no-unnecessary-template-expression': 'error',
'@typescript-eslint/no-unnecessary-type-arguments': 'error',
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
'@typescript-eslint/no-unnecessary-type-constraint': 'error',
'@typescript-eslint/no-unnecessary-type-conversion': 'error',
'@typescript-eslint/no-unnecessary-type-parameters': 'error',
'@typescript-eslint/no-unsafe-argument': 'error',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-declaration-merging': 'error',
'@typescript-eslint/no-unsafe-enum-comparison': 'error',
'@typescript-eslint/no-unsafe-function-type': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
'@typescript-eslint/no-unsafe-type-assertion': 'error',
'@typescript-eslint/no-unsafe-unary-minus': 'error',
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': 'error',
'no-unused-private-class-members': 'off',
'@typescript-eslint/no-unused-private-class-members': 'error',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'error',
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 'error',
'@typescript-eslint/no-useless-default-assignment': 'error',
'@typescript-eslint/no-useless-empty-export': 'error',
'@typescript-eslint/no-wrapper-object-types': 'error',
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
'no-throw-literal': 'off',
'@typescript-eslint/only-throw-error': 'error',
'@typescript-eslint/parameter-properties': 'error',
'@typescript-eslint/prefer-as-const': 'error',
'prefer-destructuring': 'off',
'@typescript-eslint/prefer-destructuring': 'error',
'@typescript-eslint/prefer-enum-initializers': 'error',
'@typescript-eslint/prefer-find': 'error',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-includes': 'error',
'@typescript-eslint/prefer-literal-enum-member': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'prefer-promise-reject-errors': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/prefer-readonly-parameter-types': 'error',
'@typescript-eslint/prefer-reduce-type-parameter': 'error',
'@typescript-eslint/prefer-regexp-exec': 'error',
'@typescript-eslint/prefer-return-this-type': 'error',
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
'@typescript-eslint/promise-function-async': 'error',
'@typescript-eslint/related-getter-setter-pairs': 'error',
'@typescript-eslint/require-array-sort-compare': 'error',
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/restrict-plus-operands': 'error',
'@typescript-eslint/restrict-template-expressions': 'error',
'no-return-await': 'off',
'@typescript-eslint/return-await': 'error',
'@typescript-eslint/strict-boolean-expressions': 'error',
'@typescript-eslint/strict-void-return': 'error',
'@typescript-eslint/switch-exhaustiveness-check': 'error',
'@typescript-eslint/triple-slash-reference': 'error',
'@typescript-eslint/unbound-method': 'error',
'@typescript-eslint/unified-signatures': 'error',
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'error',
},
},
];

View File

@@ -0,0 +1,340 @@
/**
* @fileoverview Rule to require function names to match the name of the variable or property to which they are assigned.
* @author Annie Zhang, Pavel Strashkin
*/
"use strict";
//--------------------------------------------------------------------------
// Requirements
//--------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
const esutils = require("esutils");
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
* Determines if a pattern is `module.exports` or `module["exports"]`
* @param {ASTNode} pattern The left side of the AssignmentExpression
* @returns {boolean} True if the pattern is `module.exports` or `module["exports"]`
*/
function isModuleExports(pattern) {
if (
pattern.type === "MemberExpression" &&
pattern.object.type === "Identifier" &&
pattern.object.name === "module"
) {
// module.exports
if (
pattern.property.type === "Identifier" &&
pattern.property.name === "exports"
) {
return true;
}
// module["exports"]
if (
pattern.property.type === "Literal" &&
pattern.property.value === "exports"
) {
return true;
}
}
return false;
}
/**
* Determines if a string name is a valid identifier
* @param {string} name The string to be checked
* @param {number} ecmaVersion The ECMAScript version if specified in the parserOptions config
* @returns {boolean} True if the string is a valid identifier
*/
function isIdentifier(name, ecmaVersion) {
if (ecmaVersion >= 2015) {
return esutils.keyword.isIdentifierES6(name);
}
return esutils.keyword.isIdentifierES5(name);
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const alwaysOrNever = { enum: ["always", "never"] };
const optionsObject = {
type: "object",
properties: {
considerPropertyDescriptor: {
type: "boolean",
},
includeCommonJSModuleExports: {
type: "boolean",
},
},
additionalProperties: false,
};
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Require function names to match the name of the variable or property to which they are assigned",
recommended: false,
frozen: true,
url: "https://eslint.org/docs/latest/rules/func-name-matching",
},
schema: {
anyOf: [
{
type: "array",
additionalItems: false,
items: [alwaysOrNever, optionsObject],
},
{
type: "array",
additionalItems: false,
items: [optionsObject],
},
],
},
defaultOptions: ["always"],
messages: {
matchProperty:
"Function name `{{funcName}}` should match property name `{{name}}`.",
matchVariable:
"Function name `{{funcName}}` should match variable name `{{name}}`.",
notMatchProperty:
"Function name `{{funcName}}` should not match property name `{{name}}`.",
notMatchVariable:
"Function name `{{funcName}}` should not match variable name `{{name}}`.",
},
},
create(context) {
const options =
(typeof context.options[0] === "object"
? context.options[0]
: context.options[1]) || {};
const nameMatches =
typeof context.options[0] === "string"
? context.options[0]
: "always";
const considerPropertyDescriptor = options.considerPropertyDescriptor;
const includeModuleExports = options.includeCommonJSModuleExports;
const ecmaVersion = context.languageOptions.ecmaVersion;
/**
* Check whether node is a certain CallExpression.
* @param {string} objName object name
* @param {string} funcName function name
* @param {ASTNode} node The node to check
* @returns {boolean} `true` if node matches CallExpression
*/
function isPropertyCall(objName, funcName, node) {
if (!node) {
return false;
}
return (
node.type === "CallExpression" &&
astUtils.isSpecificMemberAccess(node.callee, objName, funcName)
);
}
/**
* Compares identifiers based on the nameMatches option
* @param {string} x the first identifier
* @param {string} y the second identifier
* @returns {boolean} whether the two identifiers should warn.
*/
function shouldWarn(x, y) {
return (
(nameMatches === "always" && x !== y) ||
(nameMatches === "never" && x === y)
);
}
/**
* Reports
* @param {ASTNode} node The node to report
* @param {string} name The variable or property name
* @param {string} funcName The function name
* @param {boolean} isProp True if the reported node is a property assignment
* @returns {void}
*/
function report(node, name, funcName, isProp) {
let messageId;
if (nameMatches === "always" && isProp) {
messageId = "matchProperty";
} else if (nameMatches === "always") {
messageId = "matchVariable";
} else if (isProp) {
messageId = "notMatchProperty";
} else {
messageId = "notMatchVariable";
}
context.report({
node,
messageId,
data: {
name,
funcName,
},
});
}
/**
* Determines whether a given node is a string literal
* @param {ASTNode} node The node to check
* @returns {boolean} `true` if the node is a string literal
*/
function isStringLiteral(node) {
return node.type === "Literal" && typeof node.value === "string";
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
VariableDeclarator(node) {
if (
!node.init ||
node.init.type !== "FunctionExpression" ||
node.id.type !== "Identifier"
) {
return;
}
if (
node.init.id &&
shouldWarn(node.id.name, node.init.id.name)
) {
report(node, node.id.name, node.init.id.name, false);
}
},
AssignmentExpression(node) {
if (
node.right.type !== "FunctionExpression" ||
(node.left.computed &&
node.left.property.type !== "Literal") ||
(!includeModuleExports && isModuleExports(node.left)) ||
(node.left.type !== "Identifier" &&
node.left.type !== "MemberExpression")
) {
return;
}
const isProp = node.left.type === "MemberExpression";
const name = isProp
? astUtils.getStaticPropertyName(node.left)
: node.left.name;
if (
node.right.id &&
name &&
isIdentifier(name) &&
shouldWarn(name, node.right.id.name)
) {
report(node, name, node.right.id.name, isProp);
}
},
"Property, PropertyDefinition[value]"(node) {
if (!(
node.value.type === "FunctionExpression" && node.value.id
)) {
return;
}
if (node.key.type === "Identifier" && !node.computed) {
const functionName = node.value.id.name;
let propertyName = node.key.name;
if (
considerPropertyDescriptor &&
propertyName === "value" &&
node.parent.type === "ObjectExpression"
) {
if (
isPropertyCall(
"Object",
"defineProperty",
node.parent.parent,
) ||
isPropertyCall(
"Reflect",
"defineProperty",
node.parent.parent,
)
) {
const property = node.parent.parent.arguments[1];
if (
isStringLiteral(property) &&
shouldWarn(property.value, functionName)
) {
report(
node,
property.value,
functionName,
true,
);
}
} else if (
isPropertyCall(
"Object",
"defineProperties",
node.parent.parent.parent.parent,
)
) {
propertyName = node.parent.parent.key.name;
if (
!node.parent.parent.computed &&
shouldWarn(propertyName, functionName)
) {
report(node, propertyName, functionName, true);
}
} else if (
isPropertyCall(
"Object",
"create",
node.parent.parent.parent.parent,
)
) {
propertyName = node.parent.parent.key.name;
if (
!node.parent.parent.computed &&
shouldWarn(propertyName, functionName)
) {
report(node, propertyName, functionName, true);
}
} else if (shouldWarn(propertyName, functionName)) {
report(node, propertyName, functionName, true);
}
} else if (shouldWarn(propertyName, functionName)) {
report(node, propertyName, functionName, true);
}
return;
}
if (
isStringLiteral(node.key) &&
isIdentifier(node.key.value, ecmaVersion) &&
shouldWarn(node.key.value, node.value.id.name)
) {
report(node, node.key.value, node.value.id.name, true);
}
},
};
},
};

View File

@@ -0,0 +1,86 @@
/**
* HMAC: RFC2104 message authentication code.
* @module
*/
import { abytes, aexists, ahash, clean, Hash, toBytes } from "./utils.js";
export class HMAC extends Hash {
constructor(hash, _key) {
super();
this.finished = false;
this.destroyed = false;
ahash(hash);
const key = toBytes(_key);
this.iHash = hash.create();
if (typeof this.iHash.update !== 'function')
throw new Error('Expected instance of class which extends utils.Hash');
this.blockLen = this.iHash.blockLen;
this.outputLen = this.iHash.outputLen;
const blockLen = this.blockLen;
const pad = new Uint8Array(blockLen);
// blockLen can be bigger than outputLen
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
for (let i = 0; i < pad.length; i++)
pad[i] ^= 0x36;
this.iHash.update(pad);
// By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
this.oHash = hash.create();
// Undo internal XOR && apply outer XOR
for (let i = 0; i < pad.length; i++)
pad[i] ^= 0x36 ^ 0x5c;
this.oHash.update(pad);
clean(pad);
}
update(buf) {
aexists(this);
this.iHash.update(buf);
return this;
}
digestInto(out) {
aexists(this);
abytes(out, this.outputLen);
this.finished = true;
this.iHash.digestInto(out);
this.oHash.update(out);
this.oHash.digestInto(out);
this.destroy();
}
digest() {
const out = new Uint8Array(this.oHash.outputLen);
this.digestInto(out);
return out;
}
_cloneInto(to) {
// Create new instance without calling constructor since key already in state and we don't know it.
to || (to = Object.create(Object.getPrototypeOf(this), {}));
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
to = to;
to.finished = finished;
to.destroyed = destroyed;
to.blockLen = blockLen;
to.outputLen = outputLen;
to.oHash = oHash._cloneInto(to.oHash);
to.iHash = iHash._cloneInto(to.iHash);
return to;
}
clone() {
return this._cloneInto();
}
destroy() {
this.destroyed = true;
this.oHash.destroy();
this.iHash.destroy();
}
}
/**
* HMAC: RFC2104 message authentication code.
* @param hash - function that would be used e.g. sha256
* @param key - message key
* @param message - message data
* @example
* import { hmac } from '@noble/hashes/hmac';
* import { sha256 } from '@noble/hashes/sha2';
* const mac1 = hmac(sha256, 'key', 'message');
*/
export const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
hmac.create = (hash, key) => new HMAC(hash, key);
//# sourceMappingURL=hmac.js.map

View File

@@ -0,0 +1,7 @@
import type { FlatConfig } from '@typescript-eslint/utils/ts-eslint';
export default _default;
/**
* A version of `strict` that only contains type-checked rules and disables of any corresponding core ESLint rules.
* @see {@link https://typescript-eslint.io/users/configs#strict-type-checked-only}
*/
declare function _default(plugin: FlatConfig.Plugin, parser: FlatConfig.Parser): FlatConfig.ConfigArray;

View File

@@ -0,0 +1,4 @@
{
"main": "../../cjs/_ts_param.cjs",
"module": "../../esm/_ts_param.js"
}

View File

@@ -0,0 +1,22 @@
// Generated by LiveScript 1.6.0
(function(){
var parseString, cast, parseType, VERSION, parsedTypeParse, parse;
parseString = require('./parse-string');
cast = require('./cast');
parseType = require('type-check').parseType;
VERSION = '0.4.1';
parsedTypeParse = function(parsedType, string, options){
options == null && (options = {});
options.explicit == null && (options.explicit = false);
options.customTypes == null && (options.customTypes = {});
return cast(parseString(parsedType, string, options), parsedType, options);
};
parse = function(type, string, options){
return parsedTypeParse(parseType(type), string, options);
};
module.exports = {
VERSION: VERSION,
parse: parse,
parsedTypeParse: parsedTypeParse
};
}).call(this);

View File

@@ -0,0 +1,222 @@
import _typeof from "./typeof.js";
import checkInRHS from "./checkInRHS.js";
import setFunctionName from "./setFunctionName.js";
import toPropertyKey from "./toPropertyKey.js";
function applyDecs2301Factory() {
function createAddInitializerMethod(e, t) {
return function (r) {
!function (e) {
if (e.v) throw Error("attempted to call addInitializer after decoration was finished");
}(t), assertCallable(r, "An initializer"), e.push(r);
};
}
function assertInstanceIfPrivate(e, t) {
if (!e(t)) throw new TypeError("Attempted to access private element on non-instance");
}
function memberDec(e, t, r, n, a, i, s, o, c) {
var u;
switch (a) {
case 1:
u = "accessor";
break;
case 2:
u = "method";
break;
case 3:
u = "getter";
break;
case 4:
u = "setter";
break;
default:
u = "field";
}
var l,
f,
p = {
kind: u,
name: s ? "#" + t : toPropertyKey(t),
"static": i,
"private": s
},
d = {
v: !1
};
if (0 !== a && (p.addInitializer = createAddInitializerMethod(n, d)), s || 0 !== a && 2 !== a) {
if (2 === a) l = function l(e) {
return assertInstanceIfPrivate(c, e), r.value;
};else {
var h = 0 === a || 1 === a;
(h || 3 === a) && (l = s ? function (e) {
return assertInstanceIfPrivate(c, e), r.get.call(e);
} : function (e) {
return r.get.call(e);
}), (h || 4 === a) && (f = s ? function (e, t) {
assertInstanceIfPrivate(c, e), r.set.call(e, t);
} : function (e, t) {
r.set.call(e, t);
});
}
} else l = function l(e) {
return e[t];
}, 0 === a && (f = function f(e, r) {
e[t] = r;
});
var v = s ? c.bind() : function (e) {
return t in e;
};
p.access = l && f ? {
get: l,
set: f,
has: v
} : l ? {
get: l,
has: v
} : {
set: f,
has: v
};
try {
return e(o, p);
} finally {
d.v = !0;
}
}
function assertCallable(e, t) {
if ("function" != typeof e) throw new TypeError(t + " must be a function");
}
function assertValidReturnValue(e, t) {
var r = _typeof(t);
if (1 === e) {
if ("object" !== r || null === t) throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
void 0 !== t.get && assertCallable(t.get, "accessor.get"), void 0 !== t.set && assertCallable(t.set, "accessor.set"), void 0 !== t.init && assertCallable(t.init, "accessor.init");
} else if ("function" !== r) throw new TypeError((0 === e ? "field" : 10 === e ? "class" : "method") + " decorators must return a function or void 0");
}
function curryThis2(e) {
return function (t) {
e(this, t);
};
}
function applyMemberDec(e, t, r, n, a, i, s, o, c) {
var u,
l,
f,
p,
d,
h,
v,
y,
g = r[0];
if (s ? (0 === a || 1 === a ? (u = {
get: (d = r[3], function () {
return d(this);
}),
set: curryThis2(r[4])
}, f = "get") : 3 === a ? (u = {
get: r[3]
}, f = "get") : 4 === a ? (u = {
set: r[3]
}, f = "set") : u = {
value: r[3]
}, 0 !== a && (1 === a && setFunctionName(u.set, "#" + n, "set"), setFunctionName(u[f || "value"], "#" + n, f))) : 0 !== a && (u = Object.getOwnPropertyDescriptor(t, n)), 1 === a ? p = {
get: u.get,
set: u.set
} : 2 === a ? p = u.value : 3 === a ? p = u.get : 4 === a && (p = u.set), "function" == typeof g) void 0 !== (h = memberDec(g, n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? l = h : 1 === a ? (l = h.init, v = h.get || p.get, y = h.set || p.set, p = {
get: v,
set: y
}) : p = h);else for (var m = g.length - 1; m >= 0; m--) {
var b;
void 0 !== (h = memberDec(g[m], n, u, o, a, i, s, p, c)) && (assertValidReturnValue(a, h), 0 === a ? b = h : 1 === a ? (b = h.init, v = h.get || p.get, y = h.set || p.set, p = {
get: v,
set: y
}) : p = h, void 0 !== b && (void 0 === l ? l = b : "function" == typeof l ? l = [l, b] : l.push(b)));
}
if (0 === a || 1 === a) {
if (void 0 === l) l = function l(e, t) {
return t;
};else if ("function" != typeof l) {
var I = l;
l = function l(e, t) {
for (var r = t, n = 0; n < I.length; n++) r = I[n].call(e, r);
return r;
};
} else {
var w = l;
l = function l(e, t) {
return w.call(e, t);
};
}
e.push(l);
}
0 !== a && (1 === a ? (u.get = p.get, u.set = p.set) : 2 === a ? u.value = p : 3 === a ? u.get = p : 4 === a && (u.set = p), s ? 1 === a ? (e.push(function (e, t) {
return p.get.call(e, t);
}), e.push(function (e, t) {
return p.set.call(e, t);
})) : 2 === a ? e.push(p) : e.push(function (e, t) {
return p.call(e, t);
}) : Object.defineProperty(t, n, u));
}
function applyMemberDecs(e, t, r) {
for (var n, a, i, s = [], o = new Map(), c = new Map(), u = 0; u < t.length; u++) {
var l = t[u];
if (Array.isArray(l)) {
var f,
p,
d = l[1],
h = l[2],
v = l.length > 3,
y = d >= 5,
g = r;
if (y ? (f = e, 0 != (d -= 5) && (p = a = a || []), v && !i && (i = function i(t) {
return checkInRHS(t) === e;
}), g = i) : (f = e.prototype, 0 !== d && (p = n = n || [])), 0 !== d && !v) {
var m = y ? c : o,
b = m.get(h) || 0;
if (!0 === b || 3 === b && 4 !== d || 4 === b && 3 !== d) throw Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + h);
!b && d > 2 ? m.set(h, d) : m.set(h, !0);
}
applyMemberDec(s, f, l, h, d, y, v, p, g);
}
}
return pushInitializers(s, n), pushInitializers(s, a), s;
}
function pushInitializers(e, t) {
t && e.push(function (e) {
for (var r = 0; r < t.length; r++) t[r].call(e);
return e;
});
}
return function (e, t, r, n) {
return {
e: applyMemberDecs(e, t, n),
get c() {
return function (e, t) {
if (t.length > 0) {
for (var r = [], n = e, a = e.name, i = t.length - 1; i >= 0; i--) {
var s = {
v: !1
};
try {
var o = t[i](n, {
kind: "class",
name: a,
addInitializer: createAddInitializerMethod(r, s)
});
} finally {
s.v = !0;
}
void 0 !== o && (assertValidReturnValue(10, o), n = o);
}
return [n, function () {
for (var e = 0; e < r.length; e++) r[e].call(n);
}];
}
}(e, r);
}
};
};
}
function applyDecs2301(e, t, r, n) {
return (applyDecs2301 = applyDecs2301Factory())(e, t, r, n);
}
export { applyDecs2301 as default };

View File

@@ -0,0 +1,16 @@
'use strict'
const { join } = require('path')
const ThreadStream = require('..')
const stream = new ThreadStream({
filename: join(__dirname, 'to-file.js'),
workerData: { dest: process.argv[2] },
sync: true
})
stream.write('hello')
stream.write(' ')
stream.write('world\n')
stream.flushSync()
stream.unref()

View File

@@ -0,0 +1,50 @@
{
"name": "@vitest/pretty-format",
"type": "module",
"version": "4.1.10",
"description": "Fork of pretty-format with support for ESM",
"license": "MIT",
"funding": "https://opencollective.com/vitest",
"homepage": "https://github.com/vitest-dev/vitest/tree/main/packages/pretty-format",
"repository": {
"type": "git",
"url": "git+https://github.com/vitest-dev/vitest.git",
"directory": "packages/pretty-format"
},
"bugs": {
"url": "https://github.com/vitest-dev/vitest/issues"
},
"keywords": [
"vitest",
"test",
"pretty",
"pretty-format"
],
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./*": "./*"
},
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"*.d.ts",
"dist"
],
"dependencies": {
"tinyrainbow": "^3.1.0"
},
"devDependencies": {
"@types/react-is": "^19.2.0",
"react-is": "^19.2.4",
"react-is-18": "npm:react-is@18.3.1"
},
"scripts": {
"build": "premove dist && rollup -c",
"dev": "rollup -c --watch"
}
}

View File

@@ -0,0 +1,6 @@
import type { JSDOM } from 'jsdom'
declare global {
const jsdom: JSDOM
}
export {}

View File

@@ -0,0 +1,595 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
*/
"use strict";
const {
CALL,
CONSTRUCT,
ReferenceTracker,
getStaticValue,
getStringIfConstant,
} = require("@eslint-community/eslint-utils");
const { RegExpParser, visitRegExpAST } = require("@eslint-community/regexpp");
const {
isCombiningCharacter,
isEmojiModifier,
isRegionalIndicatorSymbol,
isSurrogatePair,
} = require("./utils/unicode");
const astUtils = require("./utils/ast-utils.js");
const { isValidWithUnicodeFlag } = require("./utils/regular-expressions");
const {
parseStringLiteral,
parseTemplateToken,
} = require("./utils/char-source");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* @typedef {import('@eslint-community/regexpp').AST.Character} Character
* @typedef {import('@eslint-community/regexpp').AST.CharacterClassElement} CharacterClassElement
*/
/**
* Iterate character sequences of a given nodes.
*
* CharacterClassRange syntax can steal a part of character sequence,
* so this function reverts CharacterClassRange syntax and restore the sequence.
* @param {CharacterClassElement[]} nodes The node list to iterate character sequences.
* @returns {IterableIterator<Character[]>} The list of character sequences.
*/
function* iterateCharacterSequence(nodes) {
/** @type {Character[]} */
let seq = [];
for (const node of nodes) {
switch (node.type) {
case "Character":
seq.push(node);
break;
case "CharacterClassRange":
seq.push(node.min);
yield seq;
seq = [node.max];
break;
case "CharacterSet":
case "CharacterClass": // [[]] nesting character class
case "ClassStringDisjunction": // \q{...}
case "ExpressionCharacterClass": // [A--B]
if (seq.length > 0) {
yield seq;
seq = [];
}
break;
// no default
}
}
if (seq.length > 0) {
yield seq;
}
}
/**
* Checks whether the given character node is a Unicode code point escape or not.
* @param {Character} char the character node to check.
* @returns {boolean} `true` if the character node is a Unicode code point escape.
*/
function isUnicodeCodePointEscape(char) {
return /^\\u\{[\da-f]+\}$/iu.test(char.raw);
}
/**
* Each function returns matched characters if it detects that kind of problem.
* @type {Record<string, (chars: Character[]) => IterableIterator<Character[]>>}
*/
const findCharacterSequences = {
*surrogatePairWithoutUFlag(chars) {
for (const [index, char] of chars.entries()) {
const previous = chars[index - 1];
if (
previous &&
char &&
isSurrogatePair(previous.value, char.value) &&
!isUnicodeCodePointEscape(previous) &&
!isUnicodeCodePointEscape(char)
) {
yield [previous, char];
}
}
},
*surrogatePair(chars) {
for (const [index, char] of chars.entries()) {
const previous = chars[index - 1];
if (
previous &&
char &&
isSurrogatePair(previous.value, char.value) &&
(isUnicodeCodePointEscape(previous) ||
isUnicodeCodePointEscape(char))
) {
yield [previous, char];
}
}
},
*combiningClass(chars, unfilteredChars) {
/*
* When `allowEscape` is `true`, a combined character should only be allowed if the combining mark appears as an escape sequence.
* This means that the base character should be considered even if it's escaped.
*/
for (const [index, char] of chars.entries()) {
const previous = unfilteredChars[index - 1];
if (
previous &&
char &&
isCombiningCharacter(char.value) &&
!isCombiningCharacter(previous.value)
) {
yield [previous, char];
}
}
},
*emojiModifier(chars) {
for (const [index, char] of chars.entries()) {
const previous = chars[index - 1];
if (
previous &&
char &&
isEmojiModifier(char.value) &&
!isEmojiModifier(previous.value)
) {
yield [previous, char];
}
}
},
*regionalIndicatorSymbol(chars) {
for (const [index, char] of chars.entries()) {
const previous = chars[index - 1];
if (
previous &&
char &&
isRegionalIndicatorSymbol(char.value) &&
isRegionalIndicatorSymbol(previous.value)
) {
yield [previous, char];
}
}
},
*zwj(chars) {
let sequence = null;
for (const [index, char] of chars.entries()) {
const previous = chars[index - 1];
const next = chars[index + 1];
if (
previous &&
char &&
next &&
char.value === 0x200d &&
previous.value !== 0x200d &&
next.value !== 0x200d
) {
if (sequence) {
if (sequence.at(-1) === previous) {
sequence.push(char, next); // append to the sequence
} else {
yield sequence;
sequence = chars.slice(index - 1, index + 2);
}
} else {
sequence = chars.slice(index - 1, index + 2);
}
}
}
if (sequence) {
yield sequence;
}
},
};
const kinds = Object.keys(findCharacterSequences);
/**
* Gets the value of the given node if it's a static value other than a regular expression object,
* or the node's `regex` property.
* The purpose of this method is to provide a replacement for `getStaticValue` in environments where certain regular expressions cannot be evaluated.
* A known example is Node.js 18 which does not support the `v` flag.
* Calling `getStaticValue` on a regular expression node with the `v` flag on Node.js 18 always returns `null`.
* A limitation of this method is that it can only detect a regular expression if the specified node is itself a regular expression literal node.
* @param {ASTNode | undefined} node The node to be inspected.
* @param {Scope} initialScope Scope to start finding variables. This function tries to resolve identifier references which are in the given scope.
* @returns {{ value: any } | { regex: { pattern: string, flags: string } } | null} The static value of the node, or `null`.
*/
function getStaticValueOrRegex(node, initialScope) {
if (!node) {
return null;
}
if (node.type === "Literal" && node.regex) {
return { regex: node.regex };
}
const staticValue = getStaticValue(node, initialScope);
if (staticValue?.value instanceof RegExp) {
return null;
}
return staticValue;
}
/**
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
* This function requires the source text of the character to be known.
* @param {Character} char Character to check.
* @param {string} charSource Source text of the character to check.
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
*/
function checkForAcceptableEscape(char, charSource) {
if (!charSource.startsWith("\\")) {
return false;
}
const match = /(?<=^\\+).$/su.exec(charSource);
return match?.[0] !== String.fromCodePoint(char.value);
}
/**
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
* This function works with characters that are produced by a string or template literal.
* It requires the source text and the CodeUnit list of the literal to be known.
* @param {Character} char Character to check.
* @param {string} nodeSource Source text of the string or template literal that produces the character.
* @param {CodeUnit[]} codeUnits List of CodeUnit objects of the literal that produces the character.
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
*/
function checkForAcceptableEscapeInString(char, nodeSource, codeUnits) {
const firstIndex = char.start;
const lastIndex = char.end - 1;
const start = codeUnits[firstIndex].start;
const end = codeUnits[lastIndex].end;
const charSource = nodeSource.slice(start, end);
return checkForAcceptableEscape(char, charSource);
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "problem",
defaultOptions: [
{
allowEscape: false,
},
],
docs: {
description:
"Disallow characters which are made with multiple code points in character class syntax",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-misleading-character-class",
},
hasSuggestions: true,
schema: [
{
type: "object",
properties: {
allowEscape: {
type: "boolean",
},
},
additionalProperties: false,
},
],
messages: {
surrogatePairWithoutUFlag:
"Unexpected surrogate pair in character class. Use 'u' flag.",
surrogatePair: "Unexpected surrogate pair in character class.",
combiningClass: "Unexpected combined character in character class.",
emojiModifier: "Unexpected modified Emoji in character class.",
regionalIndicatorSymbol:
"Unexpected national flag in character class.",
zwj: "Unexpected joined character sequence in character class.",
suggestUnicodeFlag: "Add unicode 'u' flag to regex.",
},
},
create(context) {
const [{ allowEscape }] = context.options;
const sourceCode = context.sourceCode;
const parser = new RegExpParser();
const checkedPatternNodes = new Set();
/**
* Verify a given regular expression.
* @param {Node} node The node to report.
* @param {string} pattern The regular expression pattern to verify.
* @param {string} flags The flags of the regular expression.
* @param {Function} unicodeFixer Fixer for missing "u" flag.
* @returns {void}
*/
function verify(node, pattern, flags, unicodeFixer) {
let patternNode;
try {
patternNode = parser.parsePattern(pattern, 0, pattern.length, {
unicode: flags.includes("u"),
unicodeSets: flags.includes("v"),
});
} catch {
// Ignore regular expressions with syntax errors
return;
}
let codeUnits = null;
/**
* Checks whether a specified regexpp character is represented as an acceptable escape sequence.
* For the purposes of this rule, an escape sequence is considered acceptable if it consists of one or more backslashes followed by the character being escaped.
* @param {Character} char Character to check.
* @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
*/
function isAcceptableEscapeSequence(char) {
if (node.type === "Literal" && node.regex) {
return checkForAcceptableEscape(char, char.raw);
}
if (node.type === "Literal" && typeof node.value === "string") {
const nodeSource = node.raw;
codeUnits ??= parseStringLiteral(nodeSource);
return checkForAcceptableEscapeInString(
char,
nodeSource,
codeUnits,
);
}
if (astUtils.isStaticTemplateLiteral(node)) {
const nodeSource = sourceCode.getText(node);
codeUnits ??= parseTemplateToken(nodeSource);
return checkForAcceptableEscapeInString(
char,
nodeSource,
codeUnits,
);
}
return false;
}
const foundKindMatches = new Map();
visitRegExpAST(patternNode, {
onCharacterClassEnter(ccNode) {
for (const unfilteredChars of iterateCharacterSequence(
ccNode.elements,
)) {
let chars;
if (allowEscape) {
// Replace escape sequences with null to avoid having them flagged.
chars = unfilteredChars.map(char =>
isAcceptableEscapeSequence(char) ? null : char,
);
} else {
chars = unfilteredChars;
}
for (const kind of kinds) {
const matches = findCharacterSequences[kind](
chars,
unfilteredChars,
);
if (foundKindMatches.has(kind)) {
foundKindMatches.get(kind).push(...matches);
} else {
foundKindMatches.set(kind, [...matches]);
}
}
}
},
});
/**
* Finds the report loc(s) for a range of matches.
* Only literals and expression-less templates generate granular errors.
* @param {Character[][]} matches Lists of individual characters being reported on.
* @returns {Location[]} locs for context.report.
* @see https://github.com/eslint/eslint/pull/17515
*/
function getNodeReportLocations(matches) {
if (
!astUtils.isStaticTemplateLiteral(node) &&
node.type !== "Literal"
) {
return matches.length ? [node.loc] : [];
}
return matches.map(chars => {
const firstIndex = chars[0].start;
const lastIndex = chars.at(-1).end - 1;
let start;
let end;
if (node.type === "TemplateLiteral") {
const source = sourceCode.getText(node);
const offset = node.range[0];
codeUnits ??= parseTemplateToken(source);
start = offset + codeUnits[firstIndex].start;
end = offset + codeUnits[lastIndex].end;
} else if (typeof node.value === "string") {
// String Literal
const source = node.raw;
const offset = node.range[0];
codeUnits ??= parseStringLiteral(source);
start = offset + codeUnits[firstIndex].start;
end = offset + codeUnits[lastIndex].end;
} else {
// RegExp Literal
const offset = node.range[0] + 1; // Add 1 to skip the leading slash.
start = offset + firstIndex;
end = offset + lastIndex + 1;
}
return {
start: sourceCode.getLocFromIndex(start),
end: sourceCode.getLocFromIndex(end),
};
});
}
for (const [kind, matches] of foundKindMatches) {
let suggest;
if (kind === "surrogatePairWithoutUFlag") {
suggest = [
{
messageId: "suggestUnicodeFlag",
fix: unicodeFixer,
},
];
}
const locs = getNodeReportLocations(matches);
for (const loc of locs) {
context.report({
node,
loc,
messageId: kind,
suggest,
});
}
}
}
return {
"Literal[regex]"(node) {
if (checkedPatternNodes.has(node)) {
return;
}
verify(node, node.regex.pattern, node.regex.flags, fixer => {
if (
!isValidWithUnicodeFlag(
context.languageOptions.ecmaVersion,
node.regex.pattern,
)
) {
return null;
}
return fixer.insertTextAfter(node, "u");
});
},
Program(node) {
const scope = sourceCode.getScope(node);
const tracker = new ReferenceTracker(scope);
/*
* Iterate calls of RegExp.
* E.g., `new RegExp()`, `RegExp()`, `new window.RegExp()`,
* `const {RegExp: a} = window; new a()`, etc...
*/
for (const { node: refNode } of tracker.iterateGlobalReferences(
{
RegExp: { [CALL]: true, [CONSTRUCT]: true },
},
)) {
let pattern, flags;
const [patternNode, flagsNode] = refNode.arguments;
const evaluatedPattern = getStaticValueOrRegex(
patternNode,
scope,
);
if (!evaluatedPattern) {
continue;
}
if (flagsNode) {
if (evaluatedPattern.regex) {
pattern = evaluatedPattern.regex.pattern;
checkedPatternNodes.add(patternNode);
} else {
pattern = String(evaluatedPattern.value);
}
flags = getStringIfConstant(flagsNode, scope);
} else {
if (evaluatedPattern.regex) {
continue;
}
pattern = String(evaluatedPattern.value);
flags = "";
}
if (typeof flags === "string") {
verify(patternNode, pattern, flags, fixer => {
if (
!isValidWithUnicodeFlag(
context.languageOptions.ecmaVersion,
pattern,
)
) {
return null;
}
if (refNode.arguments.length === 1) {
const penultimateToken =
sourceCode.getLastToken(refNode, {
skip: 1,
}); // skip closing parenthesis
return fixer.insertTextAfter(
penultimateToken,
astUtils.isCommaToken(penultimateToken)
? ' "u",'
: ', "u"',
);
}
if (
(flagsNode.type === "Literal" &&
typeof flagsNode.value === "string") ||
flagsNode.type === "TemplateLiteral"
) {
const range = [
flagsNode.range[0],
flagsNode.range[1] - 1,
];
return fixer.insertTextAfterRange(range, "u");
}
return null;
});
}
}
},
};
},
};

View File

@@ -0,0 +1,255 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const ignore_1 = __importDefault(require("ignore"));
const util_1 = require("../util");
const getESLintCoreRule_1 = require("../util/getESLintCoreRule");
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-restricted-imports');
// In some versions of eslint, the base rule has a completely incompatible schema
// This helper function is to safely try to get parts of the schema. If it's not
// possible, we'll fallback to less strict checks.
const tryAccess = (getter, fallback) => {
try {
return getter();
}
catch {
return fallback;
}
};
const baseSchema = baseRule.meta.schema;
const allowTypeImportsOptionSchema = {
allowTypeImports: {
type: 'boolean',
description: 'Whether to allow type-only imports for a path.',
},
};
const arrayOfStringsOrObjects = {
type: 'array',
items: {
anyOf: [
{ type: 'string' },
{
type: 'object',
additionalProperties: false,
properties: {
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1]
.properties, undefined),
...allowTypeImportsOptionSchema,
},
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1]
.required, undefined),
},
],
},
uniqueItems: true,
};
const arrayOfStringsOrObjectPatterns = {
anyOf: [
{
type: 'array',
items: {
type: 'string',
},
uniqueItems: true,
},
{
type: 'array',
items: {
type: 'object',
additionalProperties: false,
properties: {
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items
.properties, undefined),
...allowTypeImportsOptionSchema,
},
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items
.required, []),
},
uniqueItems: true,
},
],
};
const schema = {
anyOf: [
arrayOfStringsOrObjects,
{
type: 'array',
additionalItems: false,
items: [
{
type: 'object',
additionalProperties: false,
properties: {
paths: arrayOfStringsOrObjects,
patterns: arrayOfStringsOrObjectPatterns,
},
},
],
},
],
};
function isObjectOfPaths(obj) {
return !!obj && Object.hasOwn(obj, 'paths');
}
function isObjectOfPatterns(obj) {
return !!obj && Object.hasOwn(obj, 'patterns');
}
function isOptionsArrayOfStringOrObject(options) {
if (isObjectOfPaths(options[0])) {
return false;
}
if (isObjectOfPatterns(options[0])) {
return false;
}
return true;
}
function getRestrictedPaths(options) {
if (isOptionsArrayOfStringOrObject(options)) {
return options;
}
if (isObjectOfPaths(options[0])) {
return options[0].paths;
}
return [];
}
function getRestrictedPatterns(options) {
if (isObjectOfPatterns(options[0])) {
return options[0].patterns;
}
return [];
}
function shouldCreateRule(baseRules, options) {
if (Object.keys(baseRules).length === 0 || options.length === 0) {
return false;
}
if (!isOptionsArrayOfStringOrObject(options)) {
return !!(options[0].paths?.length || options[0].patterns?.length);
}
return true;
}
exports.default = (0, util_1.createRule)({
name: 'no-restricted-imports',
meta: {
type: 'suggestion',
// defaultOptions, -- base rule does not use defaultOptions
deprecated: {
deprecatedSince: '8.64.0',
replacedBy: [
{
rule: {
name: 'no-restricted-imports',
url: 'https://eslint.org/docs/latest/rules/no-restricted-imports',
},
},
],
url: 'https://github.com/typescript-eslint/typescript-eslint/pull/12527',
},
docs: {
description: 'Disallow specified modules when loaded by `import`',
extendsBaseRule: true,
},
fixable: baseRule.meta.fixable,
messages: baseRule.meta.messages,
schema,
},
defaultOptions: [],
create(context) {
const rules = baseRule.create(context);
const { options } = context;
if (!shouldCreateRule(rules, options)) {
return {};
}
const restrictedPaths = getRestrictedPaths(options);
const allowedTypeImportPathNameSet = new Set();
for (const restrictedPath of restrictedPaths) {
if (typeof restrictedPath === 'object' &&
restrictedPath.allowTypeImports) {
allowedTypeImportPathNameSet.add(restrictedPath.name);
}
}
function isAllowedTypeImportPath(importSource) {
return allowedTypeImportPathNameSet.has(importSource);
}
const restrictedPatterns = getRestrictedPatterns(options);
const allowedImportTypeMatchers = [];
const allowedImportTypeRegexMatchers = [];
for (const restrictedPattern of restrictedPatterns) {
if (typeof restrictedPattern === 'object' &&
restrictedPattern.allowTypeImports) {
// Following how ignore is configured in the base rule
if (restrictedPattern.group) {
allowedImportTypeMatchers.push((0, ignore_1.default)({
allowRelativePaths: true,
ignoreCase: !restrictedPattern.caseSensitive,
}).add(restrictedPattern.group));
}
if (restrictedPattern.regex) {
allowedImportTypeRegexMatchers.push(new RegExp(restrictedPattern.regex, restrictedPattern.caseSensitive ? 'u' : 'iu'));
}
}
}
function isAllowedTypeImportPattern(importSource) {
return (
// As long as there's one matching pattern that allows type import
allowedImportTypeMatchers.some(matcher => matcher.ignores(importSource)) ||
allowedImportTypeRegexMatchers.some(regex => regex.test(importSource)));
}
function checkImportNode(node) {
if (node.importKind === 'type' ||
(node.specifiers.length > 0 &&
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
specifier.importKind === 'type'))) {
const importSource = node.source.value.trim();
if (!isAllowedTypeImportPath(importSource) &&
!isAllowedTypeImportPattern(importSource)) {
return rules.ImportDeclaration(node);
}
}
else {
return rules.ImportDeclaration(node);
}
}
return {
ExportAllDeclaration: rules.ExportAllDeclaration,
'ExportNamedDeclaration[source]'(node) {
if (node.exportKind === 'type' ||
(node.specifiers.length > 0 &&
node.specifiers.every(specifier => specifier.exportKind === 'type'))) {
const importSource = node.source.value.trim();
if (!isAllowedTypeImportPath(importSource) &&
!isAllowedTypeImportPattern(importSource)) {
return rules.ExportNamedDeclaration(node);
}
}
else {
return rules.ExportNamedDeclaration(node);
}
},
ImportDeclaration: checkImportNode,
TSImportEqualsDeclaration(node) {
if (node.moduleReference.type === utils_1.AST_NODE_TYPES.TSExternalModuleReference) {
const synthesizedImport = {
...node,
type: utils_1.AST_NODE_TYPES.ImportDeclaration,
assertions: [],
attributes: [],
source: node.moduleReference.expression,
specifiers: [
{
...node.id,
type: utils_1.AST_NODE_TYPES.ImportDefaultSpecifier,
local: node.id,
// @ts-expect-error -- parent types are incompatible but it's fine for the purposes of this extension
parent: node.id.parent,
},
],
};
return checkImportNode(synthesizedImport);
}
},
};
},
});

View File

@@ -0,0 +1,59 @@
function _usingCtx() {
var r = "function" == typeof SuppressedError ? SuppressedError : function (r, e) {
var n = Error();
return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
},
e = {},
n = [];
function using(r, e) {
if (null != e) {
if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
t && (o = function o() {
try {
t.call(e);
} catch (r) {
return Promise.reject(r);
}
}), n.push({
v: e,
d: o,
a: r
});
} else r && n.push({
d: e,
a: r
});
return e;
}
return {
e: e,
u: using.bind(null, !1),
a: using.bind(null, !0),
d: function d() {
var o,
t = this.e,
s = 0;
function next() {
for (; o = n.pop();) try {
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
if (o.d) {
var r = o.d.call(o.v);
if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
} else s |= 1;
} catch (r) {
return err(r);
}
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
if (t !== e) throw t;
}
function err(n) {
return t = t !== e ? new r(n, t) : n, next();
}
return next();
}
};
}
export { _usingCtx as default };

View File

@@ -0,0 +1,12 @@
/**
* @preserve
* JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013)
*
* @author <a href="mailto:jensyt@gmail.com">Jens Taylor</a>
* @see http://github.com/homebrewing/brauhaus-diff
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*/
!function(){function t(h,r){var s=this instanceof t?this:e;return s.reset(r),"string"==typeof h&&h.length>0&&s.hash(h),s!==this?s:void 0}var e;t.prototype.hash=function(t){var e,h,r,s,i;switch(i=t.length,this.len+=i,h=this.k1,r=0,this.rem){case 0:h^=i>r?65535&t.charCodeAt(r++):0;case 1:h^=i>r?(65535&t.charCodeAt(r++))<<8:0;case 2:h^=i>r?(65535&t.charCodeAt(r++))<<16:0;case 3:h^=i>r?(255&t.charCodeAt(r))<<24:0,h^=i>r?(65280&t.charCodeAt(r++))>>8:0}if(this.rem=3&i+this.rem,i-=this.rem,i>0){for(e=this.h1;;){if(h=4294967295&11601*h+3432906752*(65535&h),h=h<<15|h>>>17,h=4294967295&13715*h+461832192*(65535&h),e^=h,e=e<<13|e>>>19,e=4294967295&5*e+3864292196,r>=i)break;h=65535&t.charCodeAt(r++)^(65535&t.charCodeAt(r++))<<8^(65535&t.charCodeAt(r++))<<16,s=t.charCodeAt(r++),h^=(255&s)<<24^(65280&s)>>8}switch(h=0,this.rem){case 3:h^=(65535&t.charCodeAt(r+2))<<16;case 2:h^=(65535&t.charCodeAt(r+1))<<8;case 1:h^=65535&t.charCodeAt(r)}this.h1=e}return this.k1=h,this},t.prototype.result=function(){var t,e;return t=this.k1,e=this.h1,t>0&&(t=4294967295&11601*t+3432906752*(65535&t),t=t<<15|t>>>17,t=4294967295&13715*t+461832192*(65535&t),e^=t),e^=this.len,e^=e>>>16,e=4294967295&51819*e+2246770688*(65535&e),e^=e>>>13,e=4294967295&44597*e+3266445312*(65535&e),e^=e>>>16,e>>>0},t.prototype.reset=function(t){return this.h1="number"==typeof t?t:0,this.rem=this.k1=this.len=0,this},e=new t,"undefined"!=typeof module?module.exports=t:this.MurmurHash3=t}();

View File

@@ -0,0 +1,16 @@
'use strict';
const pathKey = (options = {}) => {
const environment = options.env || process.env;
const platform = options.platform || process.platform;
if (platform !== 'win32') {
return 'PATH';
}
return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path';
};
module.exports = pathKey;
// TODO: Remove this for the next major release
module.exports.default = pathKey;

View File

@@ -0,0 +1,202 @@
/**
* @fileoverview A rule to disallow or enforce spaces inside of single line blocks.
* @author Toru Nagashima
* @deprecated in ESLint v8.53.0
*/
"use strict";
const util = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "block-spacing",
url: "https://eslint.style/rules/block-spacing",
},
},
],
},
type: "layout",
docs: {
description:
"Disallow or enforce spaces inside of blocks after opening block and before closing block",
recommended: false,
url: "https://eslint.org/docs/latest/rules/block-spacing",
},
fixable: "whitespace",
schema: [{ enum: ["always", "never"] }],
messages: {
missing: "Requires a space {{location}} '{{token}}'.",
extra: "Unexpected space(s) {{location}} '{{token}}'.",
},
},
create(context) {
const always = context.options[0] !== "never",
messageId = always ? "missing" : "extra",
sourceCode = context.sourceCode;
/**
* Gets the open brace token from a given node.
* @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to get.
* @returns {Token} The token of the open brace.
*/
function getOpenBrace(node) {
if (node.type === "SwitchStatement") {
if (node.cases.length > 0) {
return sourceCode.getTokenBefore(node.cases[0]);
}
return sourceCode.getLastToken(node, 1);
}
if (node.type === "StaticBlock") {
return sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
}
// "BlockStatement"
return sourceCode.getFirstToken(node);
}
/**
* Checks whether or not:
* - given tokens are on same line.
* - there is/isn't a space between given tokens.
* @param {Token} left A token to check.
* @param {Token} right The token which is next to `left`.
* @returns {boolean}
* When the option is `"always"`, `true` if there are one or more spaces between given tokens.
* When the option is `"never"`, `true` if there are not any spaces between given tokens.
* If given tokens are not on same line, it's always `true`.
*/
function isValid(left, right) {
return (
!util.isTokenOnSameLine(left, right) ||
sourceCode.isSpaceBetween(left, right) === always
);
}
/**
* Checks and reports invalid spacing style inside braces.
* @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check.
* @returns {void}
*/
function checkSpacingInsideBraces(node) {
// Gets braces and the first/last token of content.
const openBrace = getOpenBrace(node);
const closeBrace = sourceCode.getLastToken(node);
const firstToken = sourceCode.getTokenAfter(openBrace, {
includeComments: true,
});
const lastToken = sourceCode.getTokenBefore(closeBrace, {
includeComments: true,
});
// Skip if the node is invalid or empty.
if (
openBrace.type !== "Punctuator" ||
openBrace.value !== "{" ||
closeBrace.type !== "Punctuator" ||
closeBrace.value !== "}" ||
firstToken === closeBrace
) {
return;
}
// Skip line comments for option never
if (!always && firstToken.type === "Line") {
return;
}
// Check.
if (!isValid(openBrace, firstToken)) {
let loc = openBrace.loc;
if (messageId === "extra") {
loc = {
start: openBrace.loc.end,
end: firstToken.loc.start,
};
}
context.report({
node,
loc,
messageId,
data: {
location: "after",
token: openBrace.value,
},
fix(fixer) {
if (always) {
return fixer.insertTextBefore(firstToken, " ");
}
return fixer.removeRange([
openBrace.range[1],
firstToken.range[0],
]);
},
});
}
if (!isValid(lastToken, closeBrace)) {
let loc = closeBrace.loc;
if (messageId === "extra") {
loc = {
start: lastToken.loc.end,
end: closeBrace.loc.start,
};
}
context.report({
node,
loc,
messageId,
data: {
location: "before",
token: closeBrace.value,
},
fix(fixer) {
if (always) {
return fixer.insertTextAfter(lastToken, " ");
}
return fixer.removeRange([
lastToken.range[1],
closeBrace.range[0],
]);
},
});
}
}
return {
BlockStatement: checkSpacingInsideBraces,
StaticBlock: checkSpacingInsideBraces,
SwitchStatement: checkSpacingInsideBraces,
};
},
};

View File

@@ -0,0 +1,23 @@
Copyright 2013 Thorsten Lorenz.
All rights reserved.
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.

View File

@@ -0,0 +1,70 @@
/**
* Deprecated module: moved from curves/abstract/utils.js to curves/utils.js
* @module
*/
import * as u from "../utils.js";
/** @deprecated moved to `@noble/curves/utils.js` */
export const abytes = u.abytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const anumber = u.anumber;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bytesToHex = u.bytesToHex;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bytesToUtf8 = u.bytesToUtf8;
/** @deprecated moved to `@noble/curves/utils.js` */
export const concatBytes = u.concatBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const hexToBytes = u.hexToBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const isBytes = u.isBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const randomBytes = u.randomBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const utf8ToBytes = u.utf8ToBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const abool = u.abool;
/** @deprecated moved to `@noble/curves/utils.js` */
export const numberToHexUnpadded = u.numberToHexUnpadded;
/** @deprecated moved to `@noble/curves/utils.js` */
export const hexToNumber = u.hexToNumber;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bytesToNumberBE = u.bytesToNumberBE;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bytesToNumberLE = u.bytesToNumberLE;
/** @deprecated moved to `@noble/curves/utils.js` */
export const numberToBytesBE = u.numberToBytesBE;
/** @deprecated moved to `@noble/curves/utils.js` */
export const numberToBytesLE = u.numberToBytesLE;
/** @deprecated moved to `@noble/curves/utils.js` */
export const numberToVarBytesBE = u.numberToVarBytesBE;
/** @deprecated moved to `@noble/curves/utils.js` */
export const ensureBytes = u.ensureBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const equalBytes = u.equalBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const copyBytes = u.copyBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const asciiToBytes = u.asciiToBytes;
/** @deprecated moved to `@noble/curves/utils.js` */
export const inRange = u.inRange;
/** @deprecated moved to `@noble/curves/utils.js` */
export const aInRange = u.aInRange;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bitLen = u.bitLen;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bitGet = u.bitGet;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bitSet = u.bitSet;
/** @deprecated moved to `@noble/curves/utils.js` */
export const bitMask = u.bitMask;
/** @deprecated moved to `@noble/curves/utils.js` */
export const createHmacDrbg = u.createHmacDrbg;
/** @deprecated moved to `@noble/curves/utils.js` */
export const notImplemented = u.notImplemented;
/** @deprecated moved to `@noble/curves/utils.js` */
export const memoized = u.memoized;
/** @deprecated moved to `@noble/curves/utils.js` */
export const validateObject = u.validateObject;
/** @deprecated moved to `@noble/curves/utils.js` */
export const isHash = u.isHash;
//# sourceMappingURL=utils.js.map