This commit is contained in:
2025-05-09 05:30:08 +02:00
parent 7bb10e7df4
commit 73367bad9e
5322 changed files with 1266973 additions and 313 deletions

View File

@@ -0,0 +1,68 @@
/**
* @fileoverview Optimized version of the `text-table` npm module to improve performance by replacing inefficient regex-based
* whitespace trimming with a modern built-in method.
*
* This modification addresses a performance issue reported in https://github.com/eslint/eslint/issues/18709
*
* The `text-table` module is published under the MIT License. For the original source, refer to:
* https://www.npmjs.com/package/text-table.
*/
/*
*
* This software is released under the MIT license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
"use strict";
module.exports = function (rows_, opts) {
const hsep = " ";
const align = opts.align;
const stringLength = opts.stringLength;
const sizes = rows_.reduce((acc, row) => {
row.forEach((c, ix) => {
const n = stringLength(c);
if (!acc[ix] || n > acc[ix]) {
acc[ix] = n;
}
});
return acc;
}, []);
return rows_
.map(row =>
row
.map((c, ix) => {
const n = sizes[ix] - stringLength(c) || 0;
const s = Array(Math.max(n + 1, 1)).join(" ");
if (align[ix] === "r") {
return s + c;
}
return c + s;
})
.join(hsep)
.trimEnd(),
)
.join("\n");
};

View File

@@ -0,0 +1 @@
{"version":3,"names":["_toPrimitive","require","toPropertyKey","arg","key","toPrimitive","String"],"sources":["../../src/helpers/toPropertyKey.ts"],"sourcesContent":["/* @minVersion 7.1.5 */\n\n// https://tc39.es/ecma262/#sec-topropertykey\n\nimport toPrimitive from \"./toPrimitive.ts\";\n\nexport default function toPropertyKey(arg: unknown) {\n var key = toPrimitive(arg, \"string\");\n return typeof key === \"symbol\" ? key : String(key);\n}\n"],"mappings":";;;;;;AAIA,IAAAA,YAAA,GAAAC,OAAA;AAEe,SAASC,aAAaA,CAACC,GAAY,EAAE;EAClD,IAAIC,GAAG,GAAG,IAAAC,oBAAW,EAACF,GAAG,EAAE,QAAQ,CAAC;EACpC,OAAO,OAAOC,GAAG,KAAK,QAAQ,GAAGA,GAAG,GAAGE,MAAM,CAACF,GAAG,CAAC;AACpD","ignoreList":[]}

View File

@@ -0,0 +1,8 @@
export { decodeOriginalScopes, encodeOriginalScopes, decodeGeneratedRanges, encodeGeneratedRanges, } from './scopes';
export type { OriginalScope, GeneratedRange, CallSite, BindingExpressionRange } from './scopes';
export declare type SourceMapSegment = [number] | [number, number, number, number] | [number, number, number, number, number];
export declare type SourceMapLine = SourceMapSegment[];
export declare type SourceMapMappings = SourceMapLine[];
export declare function decode(mappings: string): SourceMapMappings;
export declare function encode(decoded: SourceMapMappings): string;
export declare function encode(decoded: Readonly<SourceMapMappings>): string;

View File

@@ -0,0 +1 @@
function r(e){var o,t,f="";if("string"==typeof e||"number"==typeof e)f+=e;else if("object"==typeof e)if(Array.isArray(e)){var n=e.length;for(o=0;o<n;o++)e[o]&&(t=r(e[o]))&&(f&&(f+=" "),f+=t)}else for(t in e)e[t]&&(f&&(f+=" "),f+=t);return f}function e(){for(var e,o,t=0,f="",n=arguments.length;t<n;t++)(e=arguments[t])&&(o=r(e))&&(f&&(f+=" "),f+=o);return f}module.exports=e,module.exports.clsx=e;

View File

@@ -0,0 +1,330 @@
/**
* @license React
* scheduler.native.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
"use strict";
function push(heap, node) {
var index = heap.length;
heap.push(node);
a: for (; 0 < index; ) {
var parentIndex = (index - 1) >>> 1,
parent = heap[parentIndex];
if (0 < compare(parent, node))
(heap[parentIndex] = node), (heap[index] = parent), (index = parentIndex);
else break a;
}
}
function peek(heap) {
return 0 === heap.length ? null : heap[0];
}
function pop(heap) {
if (0 === heap.length) return null;
var first = heap[0],
last = heap.pop();
if (last !== first) {
heap[0] = last;
a: for (
var index = 0, length = heap.length, halfLength = length >>> 1;
index < halfLength;
) {
var leftIndex = 2 * (index + 1) - 1,
left = heap[leftIndex],
rightIndex = leftIndex + 1,
right = heap[rightIndex];
if (0 > compare(left, last))
rightIndex < length && 0 > compare(right, left)
? ((heap[index] = right),
(heap[rightIndex] = last),
(index = rightIndex))
: ((heap[index] = left),
(heap[leftIndex] = last),
(index = leftIndex));
else if (rightIndex < length && 0 > compare(right, last))
(heap[index] = right), (heap[rightIndex] = last), (index = rightIndex);
else break a;
}
}
return first;
}
function compare(a, b) {
var diff = a.sortIndex - b.sortIndex;
return 0 !== diff ? diff : a.id - b.id;
}
var getCurrentTime;
if ("object" === typeof performance && "function" === typeof performance.now) {
var localPerformance = performance;
getCurrentTime = function () {
return localPerformance.now();
};
} else {
var localDate = Date,
initialTime = localDate.now();
getCurrentTime = function () {
return localDate.now() - initialTime;
};
}
var taskQueue = [],
timerQueue = [],
taskIdCounter = 1,
currentTask = null,
currentPriorityLevel = 3,
isPerformingWork = !1,
isHostCallbackScheduled = !1,
isHostTimeoutScheduled = !1,
needsPaint = !1,
localSetTimeout = "function" === typeof setTimeout ? setTimeout : null,
localClearTimeout = "function" === typeof clearTimeout ? clearTimeout : null,
localSetImmediate = "undefined" !== typeof setImmediate ? setImmediate : null;
function advanceTimers(currentTime) {
for (var timer = peek(timerQueue); null !== timer; ) {
if (null === timer.callback) pop(timerQueue);
else if (timer.startTime <= currentTime)
pop(timerQueue),
(timer.sortIndex = timer.expirationTime),
push(taskQueue, timer);
else break;
timer = peek(timerQueue);
}
}
function handleTimeout(currentTime) {
isHostTimeoutScheduled = !1;
advanceTimers(currentTime);
if (!isHostCallbackScheduled)
if (null !== peek(taskQueue))
(isHostCallbackScheduled = !0),
isMessageLoopRunning ||
((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline());
else {
var firstTimer = peek(timerQueue);
null !== firstTimer &&
requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);
}
}
function unstable_scheduleCallback$1(priorityLevel, callback, options) {
var currentTime = getCurrentTime();
"object" === typeof options && null !== options
? ((options = options.delay),
(options =
"number" === typeof options && 0 < options
? currentTime + options
: currentTime))
: (options = currentTime);
switch (priorityLevel) {
case 1:
var timeout = -1;
break;
case 2:
timeout = 250;
break;
case 5:
timeout = 1073741823;
break;
case 4:
timeout = 1e4;
break;
default:
timeout = 5e3;
}
timeout = options + timeout;
priorityLevel = {
id: taskIdCounter++,
callback: callback,
priorityLevel: priorityLevel,
startTime: options,
expirationTime: timeout,
sortIndex: -1
};
options > currentTime
? ((priorityLevel.sortIndex = options),
push(timerQueue, priorityLevel),
null === peek(taskQueue) &&
priorityLevel === peek(timerQueue) &&
(isHostTimeoutScheduled
? (localClearTimeout(taskTimeoutID), (taskTimeoutID = -1))
: (isHostTimeoutScheduled = !0),
requestHostTimeout(handleTimeout, options - currentTime)))
: ((priorityLevel.sortIndex = timeout),
push(taskQueue, priorityLevel),
isHostCallbackScheduled ||
isPerformingWork ||
((isHostCallbackScheduled = !0),
isMessageLoopRunning ||
((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline())));
return priorityLevel;
}
function unstable_cancelCallback$1(task) {
task.callback = null;
}
function unstable_getCurrentPriorityLevel$1() {
return currentPriorityLevel;
}
var isMessageLoopRunning = !1,
taskTimeoutID = -1,
startTime = -1;
function shouldYieldToHost() {
return needsPaint ? !0 : 5 > getCurrentTime() - startTime ? !1 : !0;
}
function requestPaint() {
needsPaint = !0;
}
function performWorkUntilDeadline() {
needsPaint = !1;
if (isMessageLoopRunning) {
var currentTime = getCurrentTime();
startTime = currentTime;
var hasMoreWork = !0;
try {
a: {
isHostCallbackScheduled = !1;
isHostTimeoutScheduled &&
((isHostTimeoutScheduled = !1),
localClearTimeout(taskTimeoutID),
(taskTimeoutID = -1));
isPerformingWork = !0;
var previousPriorityLevel = currentPriorityLevel;
try {
b: {
advanceTimers(currentTime);
for (
currentTask = peek(taskQueue);
null !== currentTask &&
!(
currentTask.expirationTime > currentTime && shouldYieldToHost()
);
) {
var callback = currentTask.callback;
if ("function" === typeof callback) {
currentTask.callback = null;
currentPriorityLevel = currentTask.priorityLevel;
var continuationCallback = callback(
currentTask.expirationTime <= currentTime
);
currentTime = getCurrentTime();
if ("function" === typeof continuationCallback) {
currentTask.callback = continuationCallback;
advanceTimers(currentTime);
hasMoreWork = !0;
break b;
}
currentTask === peek(taskQueue) && pop(taskQueue);
advanceTimers(currentTime);
} else pop(taskQueue);
currentTask = peek(taskQueue);
}
if (null !== currentTask) hasMoreWork = !0;
else {
var firstTimer = peek(timerQueue);
null !== firstTimer &&
requestHostTimeout(
handleTimeout,
firstTimer.startTime - currentTime
);
hasMoreWork = !1;
}
}
break a;
} finally {
(currentTask = null),
(currentPriorityLevel = previousPriorityLevel),
(isPerformingWork = !1);
}
hasMoreWork = void 0;
}
} finally {
hasMoreWork
? schedulePerformWorkUntilDeadline()
: (isMessageLoopRunning = !1);
}
}
}
var schedulePerformWorkUntilDeadline;
if ("function" === typeof localSetImmediate)
schedulePerformWorkUntilDeadline = function () {
localSetImmediate(performWorkUntilDeadline);
};
else if ("undefined" !== typeof MessageChannel) {
var channel = new MessageChannel(),
port = channel.port2;
channel.port1.onmessage = performWorkUntilDeadline;
schedulePerformWorkUntilDeadline = function () {
port.postMessage(null);
};
} else
schedulePerformWorkUntilDeadline = function () {
localSetTimeout(performWorkUntilDeadline, 0);
};
function requestHostTimeout(callback, ms) {
taskTimeoutID = localSetTimeout(function () {
callback(getCurrentTime());
}, ms);
}
var unstable_UserBlockingPriority =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_UserBlockingPriority
: 2,
unstable_NormalPriority =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_NormalPriority
: 3,
unstable_LowPriority =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_LowPriority
: 4,
unstable_ImmediatePriority =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_ImmediatePriority
: 1,
unstable_scheduleCallback =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_scheduleCallback
: unstable_scheduleCallback$1,
unstable_cancelCallback =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_cancelCallback
: unstable_cancelCallback$1,
unstable_getCurrentPriorityLevel =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_getCurrentPriorityLevel
: unstable_getCurrentPriorityLevel$1,
unstable_shouldYield =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_shouldYield
: shouldYieldToHost,
unstable_requestPaint =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_requestPaint
: requestPaint,
unstable_now =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_now
: getCurrentTime;
function throwNotImplemented() {
throw Error("Not implemented.");
}
exports.unstable_IdlePriority =
"undefined" !== typeof nativeRuntimeScheduler
? nativeRuntimeScheduler.unstable_IdlePriority
: 5;
exports.unstable_ImmediatePriority = unstable_ImmediatePriority;
exports.unstable_LowPriority = unstable_LowPriority;
exports.unstable_NormalPriority = unstable_NormalPriority;
exports.unstable_Profiling = null;
exports.unstable_UserBlockingPriority = unstable_UserBlockingPriority;
exports.unstable_cancelCallback = unstable_cancelCallback;
exports.unstable_forceFrameRate = throwNotImplemented;
exports.unstable_getCurrentPriorityLevel = unstable_getCurrentPriorityLevel;
exports.unstable_next = throwNotImplemented;
exports.unstable_now = unstable_now;
exports.unstable_requestPaint = unstable_requestPaint;
exports.unstable_runWithPriority = throwNotImplemented;
exports.unstable_scheduleCallback = unstable_scheduleCallback;
exports.unstable_shouldYield = unstable_shouldYield;
exports.unstable_wrapCallback = throwNotImplemented;

View File

@@ -0,0 +1,192 @@
/**
* @fileoverview Rule to warn when a function expression does not have a name.
* @author Kyle T. Nunery
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
/**
* Checks whether or not a given variable is a function name.
* @param {eslint-scope.Variable} variable A variable to check.
* @returns {boolean} `true` if the variable is a function name.
*/
function isFunctionName(variable) {
return variable && variable.defs[0].type === "FunctionName";
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
defaultOptions: ["always", {}],
docs: {
description: "Require or disallow named `function` expressions",
recommended: false,
url: "https://eslint.org/docs/latest/rules/func-names",
},
schema: {
definitions: {
value: {
enum: ["always", "as-needed", "never"],
},
},
items: [
{
$ref: "#/definitions/value",
},
{
type: "object",
properties: {
generators: {
$ref: "#/definitions/value",
},
},
additionalProperties: false,
},
],
},
messages: {
unnamed: "Unexpected unnamed {{name}}.",
named: "Unexpected named {{name}}.",
},
},
create(context) {
const sourceCode = context.sourceCode;
/**
* Returns the config option for the given node.
* @param {ASTNode} node A node to get the config for.
* @returns {string} The config option.
*/
function getConfigForNode(node) {
if (node.generator && context.options[1].generators) {
return context.options[1].generators;
}
return context.options[0];
}
/**
* Determines whether the current FunctionExpression node is a get, set, or
* shorthand method in an object literal or a class.
* @param {ASTNode} node A node to check.
* @returns {boolean} True if the node is a get, set, or shorthand method.
*/
function isObjectOrClassMethod(node) {
const parent = node.parent;
return (
parent.type === "MethodDefinition" ||
(parent.type === "Property" &&
(parent.method ||
parent.kind === "get" ||
parent.kind === "set"))
);
}
/**
* Determines whether the current FunctionExpression node has a name that would be
* inferred from context in a conforming ES6 environment.
* @param {ASTNode} node A node to check.
* @returns {boolean} True if the node would have a name assigned automatically.
*/
function hasInferredName(node) {
const parent = node.parent;
return (
isObjectOrClassMethod(node) ||
(parent.type === "VariableDeclarator" &&
parent.id.type === "Identifier" &&
parent.init === node) ||
(parent.type === "Property" && parent.value === node) ||
(parent.type === "PropertyDefinition" &&
parent.value === node) ||
(parent.type === "AssignmentExpression" &&
parent.left.type === "Identifier" &&
parent.right === node) ||
(parent.type === "AssignmentPattern" &&
parent.left.type === "Identifier" &&
parent.right === node)
);
}
/**
* Reports that an unnamed function should be named
* @param {ASTNode} node The node to report in the event of an error.
* @returns {void}
*/
function reportUnexpectedUnnamedFunction(node) {
context.report({
node,
messageId: "unnamed",
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
data: { name: astUtils.getFunctionNameWithKind(node) },
});
}
/**
* Reports that a named function should be unnamed
* @param {ASTNode} node The node to report in the event of an error.
* @returns {void}
*/
function reportUnexpectedNamedFunction(node) {
context.report({
node,
messageId: "named",
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
data: { name: astUtils.getFunctionNameWithKind(node) },
});
}
/**
* The listener for function nodes.
* @param {ASTNode} node function node
* @returns {void}
*/
function handleFunction(node) {
// Skip recursive functions.
const nameVar = sourceCode.getDeclaredVariables(node)[0];
if (isFunctionName(nameVar) && nameVar.references.length > 0) {
return;
}
const hasName = Boolean(node.id && node.id.name);
const config = getConfigForNode(node);
if (config === "never") {
if (hasName && node.type !== "FunctionDeclaration") {
reportUnexpectedNamedFunction(node);
}
} else if (config === "as-needed") {
if (!hasName && !hasInferredName(node)) {
reportUnexpectedUnnamedFunction(node);
}
} else {
if (!hasName && !isObjectOrClassMethod(node)) {
reportUnexpectedUnnamedFunction(node);
}
}
}
return {
"FunctionExpression:exit": handleFunction,
"ExportDefaultDeclaration > FunctionDeclaration": handleFunction,
};
},
};

View File

@@ -0,0 +1 @@
export declare function SafeFragment(props: any): import("react/jsx-runtime").JSX.Element;

View File

@@ -0,0 +1,401 @@
/**
* @fileoverview Disallow redundant return statements
* @author Teddy Katz
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils"),
FixTracker = require("./utils/fix-tracker");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Removes the given element from the array.
* @param {Array} array The source array to remove.
* @param {any} element The target item to remove.
* @returns {void}
*/
function remove(array, element) {
const index = array.indexOf(element);
if (index !== -1) {
array.splice(index, 1);
}
}
/**
* Checks whether it can remove the given return statement or not.
* @param {ASTNode} node The return statement node to check.
* @returns {boolean} `true` if the node is removable.
*/
function isRemovable(node) {
return astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type);
}
/**
* Checks whether the given return statement is in a `finally` block or not.
* @param {ASTNode} node The return statement node to check.
* @returns {boolean} `true` if the node is in a `finally` block.
*/
function isInFinally(node) {
for (
let currentNode = node;
currentNode && currentNode.parent && !astUtils.isFunction(currentNode);
currentNode = currentNode.parent
) {
if (
currentNode.parent.type === "TryStatement" &&
currentNode.parent.finalizer === currentNode
) {
return true;
}
}
return false;
}
/**
* Checks all segments in a set and returns true if any are reachable.
* @param {Set<CodePathSegment>} segments The segments to check.
* @returns {boolean} True if any segment is reachable; false otherwise.
*/
function isAnySegmentReachable(segments) {
for (const segment of segments) {
if (segment.reachable) {
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow redundant return statements",
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-useless-return",
},
fixable: "code",
schema: [],
messages: {
unnecessaryReturn: "Unnecessary return statement.",
},
},
create(context) {
const segmentInfoMap = new WeakMap();
const sourceCode = context.sourceCode;
let scopeInfo = null;
/**
* Checks whether the given segment is terminated by a return statement or not.
* @param {CodePathSegment} segment The segment to check.
* @returns {boolean} `true` if the segment is terminated by a return statement, or if it's still a part of unreachable.
*/
function isReturned(segment) {
const info = segmentInfoMap.get(segment);
return !info || info.returned;
}
/**
* Collects useless return statements from the given previous segments.
*
* A previous segment may be an unreachable segment.
* In that case, the information object of the unreachable segment is not
* initialized because `onCodePathSegmentStart` event is not notified for
* unreachable segments.
* This goes to the previous segments of the unreachable segment recursively
* if the unreachable segment was generated by a return statement. Otherwise,
* this ignores the unreachable segment.
*
* This behavior would simulate code paths for the case that the return
* statement does not exist.
* @param {ASTNode[]} uselessReturns The collected return statements.
* @param {CodePathSegment[]} prevSegments The previous segments to traverse.
* @param {WeakSet<CodePathSegment>} [providedTraversedSegments] A set of segments that have already been traversed in this call
* @returns {ASTNode[]} `uselessReturns`.
*/
function getUselessReturns(
uselessReturns,
prevSegments,
providedTraversedSegments,
) {
const traversedSegments =
providedTraversedSegments || new WeakSet();
for (const segment of prevSegments) {
if (!segment.reachable) {
if (!traversedSegments.has(segment)) {
traversedSegments.add(segment);
getUselessReturns(
uselessReturns,
segment.allPrevSegments.filter(isReturned),
traversedSegments,
);
}
continue;
}
if (segmentInfoMap.has(segment)) {
uselessReturns.push(
...segmentInfoMap.get(segment).uselessReturns,
);
}
}
return uselessReturns;
}
/**
* Removes the return statements on the given segment from the useless return
* statement list.
*
* This segment may be an unreachable segment.
* In that case, the information object of the unreachable segment is not
* initialized because `onCodePathSegmentStart` event is not notified for
* unreachable segments.
* This goes to the previous segments of the unreachable segment recursively
* if the unreachable segment was generated by a return statement. Otherwise,
* this ignores the unreachable segment.
*
* This behavior would simulate code paths for the case that the return
* statement does not exist.
* @param {CodePathSegment} segment The segment to get return statements.
* @param {Set<CodePathSegment>} usedUnreachableSegments A set of segments that have already been traversed in this call.
* @returns {void}
*/
function markReturnStatementsOnSegmentAsUsed(
segment,
usedUnreachableSegments,
) {
if (!segment.reachable) {
usedUnreachableSegments.add(segment);
segment.allPrevSegments
.filter(isReturned)
.filter(
prevSegment =>
!usedUnreachableSegments.has(prevSegment),
)
.forEach(prevSegment =>
markReturnStatementsOnSegmentAsUsed(
prevSegment,
usedUnreachableSegments,
),
);
return;
}
const info = segmentInfoMap.get(segment);
if (!info) {
return;
}
info.uselessReturns = info.uselessReturns.filter(node => {
if (
scopeInfo.traversedTryBlockStatements &&
scopeInfo.traversedTryBlockStatements.length > 0
) {
const returnInitialRange = node.range[0];
const returnFinalRange = node.range[1];
const areBlocksInRange =
scopeInfo.traversedTryBlockStatements.some(
tryBlockStatement => {
const blockInitialRange =
tryBlockStatement.range[0];
const blockFinalRange =
tryBlockStatement.range[1];
return (
returnInitialRange >= blockInitialRange &&
returnFinalRange <= blockFinalRange
);
},
);
if (areBlocksInRange) {
return true;
}
}
remove(scopeInfo.uselessReturns, node);
return false;
});
}
/**
* Removes the return statements on the current segments from the useless
* return statement list.
*
* This function will be called at every statement except FunctionDeclaration,
* BlockStatement, and BreakStatement.
*
* - FunctionDeclarations are always executed whether it's returned or not.
* - BlockStatements do nothing.
* - BreakStatements go the next merely.
* @returns {void}
*/
function markReturnStatementsOnCurrentSegmentsAsUsed() {
scopeInfo.currentSegments.forEach(segment =>
markReturnStatementsOnSegmentAsUsed(segment, new Set()),
);
}
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
return {
// Makes and pushes a new scope information.
onCodePathStart(codePath) {
scopeInfo = {
upper: scopeInfo,
uselessReturns: [],
traversedTryBlockStatements: [],
codePath,
currentSegments: new Set(),
};
},
// Reports useless return statements if exist.
onCodePathEnd() {
for (const node of scopeInfo.uselessReturns) {
context.report({
node,
loc: node.loc,
messageId: "unnecessaryReturn",
fix(fixer) {
if (
isRemovable(node) &&
!sourceCode.getCommentsInside(node).length
) {
/*
* Extend the replacement range to include the
* entire function to avoid conflicting with
* no-else-return.
* https://github.com/eslint/eslint/issues/8026
*/
return new FixTracker(fixer, sourceCode)
.retainEnclosingFunction(node)
.remove(node);
}
return null;
},
});
}
scopeInfo = scopeInfo.upper;
},
/*
* Initializes segments.
* NOTE: This event is notified for only reachable segments.
*/
onCodePathSegmentStart(segment) {
scopeInfo.currentSegments.add(segment);
const info = {
uselessReturns: getUselessReturns(
[],
segment.allPrevSegments,
),
returned: false,
};
// Stores the info.
segmentInfoMap.set(segment, info);
},
onUnreachableCodePathSegmentStart(segment) {
scopeInfo.currentSegments.add(segment);
},
onUnreachableCodePathSegmentEnd(segment) {
scopeInfo.currentSegments.delete(segment);
},
onCodePathSegmentEnd(segment) {
scopeInfo.currentSegments.delete(segment);
},
// Adds ReturnStatement node to check whether it's useless or not.
ReturnStatement(node) {
if (node.argument) {
markReturnStatementsOnCurrentSegmentsAsUsed();
}
if (
node.argument ||
astUtils.isInLoop(node) ||
isInFinally(node) ||
// Ignore `return` statements in unreachable places (https://github.com/eslint/eslint/issues/11647).
!isAnySegmentReachable(scopeInfo.currentSegments)
) {
return;
}
for (const segment of scopeInfo.currentSegments) {
const info = segmentInfoMap.get(segment);
if (info) {
info.uselessReturns.push(node);
info.returned = true;
}
}
scopeInfo.uselessReturns.push(node);
},
"TryStatement > BlockStatement.block:exit"(node) {
scopeInfo.traversedTryBlockStatements.push(node);
},
"TryStatement:exit"() {
scopeInfo.traversedTryBlockStatements.pop();
},
/*
* Registers for all statement nodes except FunctionDeclaration, BlockStatement, BreakStatement.
* Removes return statements of the current segments from the useless return statement list.
*/
ClassDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
ContinueStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
DebuggerStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
DoWhileStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
EmptyStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ExpressionStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ForInStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ForOfStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ForStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
IfStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ImportDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
LabeledStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
SwitchStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ThrowStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
TryStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
VariableDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
WhileStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
WithStatement: markReturnStatementsOnCurrentSegmentsAsUsed,
ExportNamedDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
ExportDefaultDeclaration:
markReturnStatementsOnCurrentSegmentsAsUsed,
ExportAllDeclaration: markReturnStatementsOnCurrentSegmentsAsUsed,
};
},
};

View File

@@ -0,0 +1 @@
module.exports={A:{A:{"2":"mC","8":"K D E F A B"},B:{"1":"0 9 Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I","8":"C L M G N O P"},C:{"1":"0 1 2 3 4 5 6 7 8 9 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC","8":"nC LC qC rC"},D:{"1":"0 1 2 3 4 5 6 7 8 9 PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","4":"J"},E:{"1":"K D E F A B C L M G uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","8":"sC SC","132":"J PB tC"},F:{"1":"0 1 2 3 4 5 6 7 8 F B C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 4C 5C 6C 7C FC kC 8C GC"},G:{"1":"E BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC","132":"SC 9C lC AD"},H:{"2":"WD"},I:{"1":"LC J I aD lC bD cD","2":"XD YD ZD"},J:{"1":"D A"},K:{"1":"A B C H FC kC GC"},L:{"1":"I"},M:{"1":"EC"},N:{"8":"A B"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"qD rD"}},B:2,C:"SVG SMIL animation",D:true};

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
"use strict"
require("../dist/bin.js")

View File

@@ -0,0 +1 @@
{"version":3,"names":["_utils","require","PLACEHOLDERS","exports","PLACEHOLDERS_ALIAS","Declaration","Pattern","type","alias","ALIAS_KEYS","length","PLACEHOLDERS_FLIPPED_ALIAS","Object","keys","forEach","hasOwnProperty","call","push"],"sources":["../../src/definitions/placeholders.ts"],"sourcesContent":["import { ALIAS_KEYS } from \"./utils.ts\";\n\nexport const PLACEHOLDERS = [\n \"Identifier\",\n \"StringLiteral\",\n \"Expression\",\n \"Statement\",\n \"Declaration\",\n \"BlockStatement\",\n \"ClassBody\",\n \"Pattern\",\n] as const;\n\nexport const PLACEHOLDERS_ALIAS: Record<string, string[]> = {\n Declaration: [\"Statement\"],\n Pattern: [\"PatternLike\", \"LVal\"],\n};\n\nfor (const type of PLACEHOLDERS) {\n const alias = ALIAS_KEYS[type];\n if (alias?.length) PLACEHOLDERS_ALIAS[type] = alias;\n}\n\nexport const PLACEHOLDERS_FLIPPED_ALIAS: Record<string, string[]> = {};\n\nObject.keys(PLACEHOLDERS_ALIAS).forEach(type => {\n PLACEHOLDERS_ALIAS[type].forEach(alias => {\n if (!Object.hasOwn(PLACEHOLDERS_FLIPPED_ALIAS, alias)) {\n PLACEHOLDERS_FLIPPED_ALIAS[alias] = [];\n }\n PLACEHOLDERS_FLIPPED_ALIAS[alias].push(type);\n });\n});\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,MAAMC,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG,CAC1B,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,SAAS,CACD;AAEH,MAAME,kBAA4C,GAAAD,OAAA,CAAAC,kBAAA,GAAG;EAC1DC,WAAW,EAAE,CAAC,WAAW,CAAC;EAC1BC,OAAO,EAAE,CAAC,aAAa,EAAE,MAAM;AACjC,CAAC;AAED,KAAK,MAAMC,IAAI,IAAIL,YAAY,EAAE;EAC/B,MAAMM,KAAK,GAAGC,iBAAU,CAACF,IAAI,CAAC;EAC9B,IAAIC,KAAK,YAALA,KAAK,CAAEE,MAAM,EAAEN,kBAAkB,CAACG,IAAI,CAAC,GAAGC,KAAK;AACrD;AAEO,MAAMG,0BAAoD,GAAAR,OAAA,CAAAQ,0BAAA,GAAG,CAAC,CAAC;AAEtEC,MAAM,CAACC,IAAI,CAACT,kBAAkB,CAAC,CAACU,OAAO,CAACP,IAAI,IAAI;EAC9CH,kBAAkB,CAACG,IAAI,CAAC,CAACO,OAAO,CAACN,KAAK,IAAI;IACxC,IAAI,CAACO,cAAA,CAAAC,IAAA,CAAcL,0BAA0B,EAAEH,KAAK,CAAC,EAAE;MACrDG,0BAA0B,CAACH,KAAK,CAAC,GAAG,EAAE;IACxC;IACAG,0BAA0B,CAACH,KAAK,CAAC,CAACS,IAAI,CAACV,IAAI,CAAC;EAC9C,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _wrapRegExp;
var _setPrototypeOf = require("./setPrototypeOf.js");
var _inherits = require("./inherits.js");
function _wrapRegExp() {
exports.default = _wrapRegExp = function (re, groups) {
return new BabelRegExp(re, undefined, groups);
};
var _super = RegExp.prototype;
var _groups = new WeakMap();
function BabelRegExp(re, flags, groups) {
var _this = new RegExp(re, flags);
_groups.set(_this, groups || _groups.get(re));
return (0, _setPrototypeOf.default)(_this, BabelRegExp.prototype);
}
(0, _inherits.default)(BabelRegExp, RegExp);
BabelRegExp.prototype.exec = function (str) {
var result = _super.exec.call(this, str);
if (result) {
result.groups = buildGroups(result, this);
var indices = result.indices;
if (indices) indices.groups = buildGroups(indices, this);
}
return result;
};
BabelRegExp.prototype[Symbol.replace] = function (str, substitution) {
if (typeof substitution === "string") {
var groups = _groups.get(this);
return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)(>|$)/g, function (match, name, end) {
if (end === "") {
return match;
} else {
var group = groups[name];
return Array.isArray(group) ? "$" + group.join("$") : typeof group === "number" ? "$" + group : "";
}
}));
} else if (typeof substitution === "function") {
var _this = this;
return _super[Symbol.replace].call(this, str, function () {
var args = arguments;
if (typeof args[args.length - 1] !== "object") {
args = [].slice.call(args);
args.push(buildGroups(args, _this));
}
return substitution.apply(this, args);
});
} else {
return _super[Symbol.replace].call(this, str, substitution);
}
};
function buildGroups(result, re) {
var g = _groups.get(re);
return Object.keys(g).reduce(function (groups, name) {
var i = g[name];
if (typeof i === "number") groups[name] = result[i];else {
var k = 0;
while (result[i[k]] === undefined && k + 1 < i.length) {
k++;
}
groups[name] = result[i[k]];
}
return groups;
}, Object.create(null));
}
return _wrapRegExp.apply(this, arguments);
}
//# sourceMappingURL=wrapRegExp.js.map

View File

@@ -0,0 +1,6 @@
import type { StringReader, StringWriter } from './strings';
export declare const comma: number;
export declare const semicolon: number;
export declare function decodeInteger(reader: StringReader, relative: number): number;
export declare function encodeInteger(builder: StringWriter, num: number, relative: number): number;
export declare function hasMoreVlq(reader: StringReader, max: number): boolean;

View File

@@ -0,0 +1,664 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const nextTick = require("process").nextTick;
/** @typedef {import("./Resolver").FileSystem} FileSystem */
/** @typedef {import("./Resolver").PathLike} PathLike */
/** @typedef {import("./Resolver").PathOrFileDescriptor} PathOrFileDescriptor */
/** @typedef {import("./Resolver").SyncFileSystem} SyncFileSystem */
/** @typedef {FileSystem & SyncFileSystem} BaseFileSystem */
/**
* @template T
* @typedef {import("./Resolver").FileSystemCallback<T>} FileSystemCallback<T>
*/
/**
* @param {string} path path
* @returns {string} dirname
*/
const dirname = path => {
let idx = path.length - 1;
while (idx >= 0) {
const c = path.charCodeAt(idx);
// slash or backslash
if (c === 47 || c === 92) break;
idx--;
}
if (idx < 0) return "";
return path.slice(0, idx);
};
/**
* @template T
* @param {FileSystemCallback<T>[]} callbacks callbacks
* @param {Error | null} err error
* @param {T} result result
*/
const runCallbacks = (callbacks, err, result) => {
if (callbacks.length === 1) {
callbacks[0](err, result);
callbacks.length = 0;
return;
}
let error;
for (const callback of callbacks) {
try {
callback(err, result);
} catch (e) {
if (!error) error = e;
}
}
callbacks.length = 0;
if (error) throw error;
};
class OperationMergerBackend {
/**
* @param {Function | undefined} provider async method in filesystem
* @param {Function | undefined} syncProvider sync method in filesystem
* @param {BaseFileSystem} providerContext call context for the provider methods
*/
constructor(provider, syncProvider, providerContext) {
this._provider = provider;
this._syncProvider = syncProvider;
this._providerContext = providerContext;
this._activeAsyncOperations = new Map();
this.provide = this._provider
? /**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {object | FileSystemCallback<any> | undefined} options options
* @param {FileSystemCallback<any>=} callback callback
* @returns {any} result
*/
(path, options, callback) => {
if (typeof options === "function") {
callback = /** @type {FileSystemCallback<any>} */ (options);
options = undefined;
}
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
/** @type {Function} */
(callback)(
new TypeError("path must be a string, Buffer, URL or number")
);
return;
}
if (options) {
return /** @type {Function} */ (this._provider).call(
this._providerContext,
path,
options,
callback
);
}
let callbacks = this._activeAsyncOperations.get(path);
if (callbacks) {
callbacks.push(callback);
return;
}
this._activeAsyncOperations.set(path, (callbacks = [callback]));
/** @type {Function} */
(provider)(
path,
/**
* @param {Error} err error
* @param {any} result result
*/
(err, result) => {
this._activeAsyncOperations.delete(path);
runCallbacks(callbacks, err, result);
}
);
}
: null;
this.provideSync = this._syncProvider
? /**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {object=} options options
* @returns {any} result
*/
(path, options) => {
return /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path,
options
);
}
: null;
}
purge() {}
purgeParent() {}
}
/*
IDLE:
insert data: goto SYNC
SYNC:
before provide: run ticks
event loop tick: goto ASYNC_ACTIVE
ASYNC:
timeout: run tick, goto ASYNC_PASSIVE
ASYNC_PASSIVE:
before provide: run ticks
IDLE --[insert data]--> SYNC --[event loop tick]--> ASYNC_ACTIVE --[interval tick]-> ASYNC_PASSIVE
^ |
+---------[insert data]-------+
*/
const STORAGE_MODE_IDLE = 0;
const STORAGE_MODE_SYNC = 1;
const STORAGE_MODE_ASYNC = 2;
/**
* @callback Provide
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @param {FileSystemCallback<any>} callback callback
* @returns {void}
*/
class CacheBackend {
/**
* @param {number} duration max cache duration of items
* @param {function | undefined} provider async method
* @param {function | undefined} syncProvider sync method
* @param {BaseFileSystem} providerContext call context for the provider methods
*/
constructor(duration, provider, syncProvider, providerContext) {
this._duration = duration;
this._provider = provider;
this._syncProvider = syncProvider;
this._providerContext = providerContext;
/** @type {Map<string, FileSystemCallback<any>[]>} */
this._activeAsyncOperations = new Map();
/** @type {Map<string, { err: Error | null, result?: any, level: Set<string> }>} */
this._data = new Map();
/** @type {Set<string>[]} */
this._levels = [];
for (let i = 0; i < 10; i++) this._levels.push(new Set());
for (let i = 5000; i < duration; i += 500) this._levels.push(new Set());
this._currentLevel = 0;
this._tickInterval = Math.floor(duration / this._levels.length);
/** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC} */
this._mode = STORAGE_MODE_IDLE;
/** @type {NodeJS.Timeout | undefined} */
this._timeout = undefined;
/** @type {number | undefined} */
this._nextDecay = undefined;
// @ts-ignore
this.provide = provider ? this.provide.bind(this) : null;
// @ts-ignore
this.provideSync = syncProvider ? this.provideSync.bind(this) : null;
}
/**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @param {FileSystemCallback<any>} callback callback
* @returns {void}
*/
provide(path, options, callback) {
if (typeof options === "function") {
callback = options;
options = undefined;
}
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
callback(new TypeError("path must be a string, Buffer, URL or number"));
return;
}
const strPath = typeof path !== "string" ? path.toString() : path;
if (options) {
return /** @type {Function} */ (this._provider).call(
this._providerContext,
path,
options,
callback
);
}
// When in sync mode we can move to async mode
if (this._mode === STORAGE_MODE_SYNC) {
this._enterAsyncMode();
}
// Check in cache
let cacheEntry = this._data.get(strPath);
if (cacheEntry !== undefined) {
if (cacheEntry.err) return nextTick(callback, cacheEntry.err);
return nextTick(callback, null, cacheEntry.result);
}
// Check if there is already the same operation running
let callbacks = this._activeAsyncOperations.get(strPath);
if (callbacks !== undefined) {
callbacks.push(callback);
return;
}
this._activeAsyncOperations.set(strPath, (callbacks = [callback]));
// Run the operation
/** @type {Function} */
(this._provider).call(
this._providerContext,
path,
/**
* @param {Error | null} err error
* @param {any} [result] result
*/
(err, result) => {
this._activeAsyncOperations.delete(strPath);
this._storeResult(strPath, err, result);
// Enter async mode if not yet done
this._enterAsyncMode();
runCallbacks(
/** @type {FileSystemCallback<any>[]} */ (callbacks),
err,
result
);
}
);
}
/**
* @param {PathLike | PathOrFileDescriptor} path path
* @param {any} options options
* @returns {any} result
*/
provideSync(path, options) {
if (
typeof path !== "string" &&
!Buffer.isBuffer(path) &&
!(path instanceof URL) &&
typeof path !== "number"
) {
throw new TypeError("path must be a string");
}
const strPath = typeof path !== "string" ? path.toString() : path;
if (options) {
return /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path,
options
);
}
// In sync mode we may have to decay some cache items
if (this._mode === STORAGE_MODE_SYNC) {
this._runDecays();
}
// Check in cache
let cacheEntry = this._data.get(strPath);
if (cacheEntry !== undefined) {
if (cacheEntry.err) throw cacheEntry.err;
return cacheEntry.result;
}
// Get all active async operations
// This sync operation will also complete them
const callbacks = this._activeAsyncOperations.get(strPath);
this._activeAsyncOperations.delete(strPath);
// Run the operation
// When in idle mode, we will enter sync mode
let result;
try {
result = /** @type {Function} */ (this._syncProvider).call(
this._providerContext,
path
);
} catch (err) {
this._storeResult(strPath, /** @type {Error} */ (err), undefined);
this._enterSyncModeWhenIdle();
if (callbacks) {
runCallbacks(callbacks, /** @type {Error} */ (err), undefined);
}
throw err;
}
this._storeResult(strPath, null, result);
this._enterSyncModeWhenIdle();
if (callbacks) {
runCallbacks(callbacks, null, result);
}
return result;
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purge(what) {
if (!what) {
if (this._mode !== STORAGE_MODE_IDLE) {
this._data.clear();
for (const level of this._levels) {
level.clear();
}
this._enterIdleMode();
}
} else if (
typeof what === "string" ||
Buffer.isBuffer(what) ||
what instanceof URL ||
typeof what === "number"
) {
const strWhat = typeof what !== "string" ? what.toString() : what;
for (let [key, data] of this._data) {
if (key.startsWith(strWhat)) {
this._data.delete(key);
data.level.delete(key);
}
}
if (this._data.size === 0) {
this._enterIdleMode();
}
} else {
for (let [key, data] of this._data) {
for (const item of what) {
const strItem = typeof item !== "string" ? item.toString() : item;
if (key.startsWith(strItem)) {
this._data.delete(key);
data.level.delete(key);
break;
}
}
}
if (this._data.size === 0) {
this._enterIdleMode();
}
}
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purgeParent(what) {
if (!what) {
this.purge();
} else if (
typeof what === "string" ||
Buffer.isBuffer(what) ||
what instanceof URL ||
typeof what === "number"
) {
const strWhat = typeof what !== "string" ? what.toString() : what;
this.purge(dirname(strWhat));
} else {
const set = new Set();
for (const item of what) {
const strItem = typeof item !== "string" ? item.toString() : item;
set.add(dirname(strItem));
}
this.purge(set);
}
}
/**
* @param {string} path path
* @param {Error | null} err error
* @param {any} result result
*/
_storeResult(path, err, result) {
if (this._data.has(path)) return;
const level = this._levels[this._currentLevel];
this._data.set(path, { err, result, level });
level.add(path);
}
_decayLevel() {
const nextLevel = (this._currentLevel + 1) % this._levels.length;
const decay = this._levels[nextLevel];
this._currentLevel = nextLevel;
for (let item of decay) {
this._data.delete(item);
}
decay.clear();
if (this._data.size === 0) {
this._enterIdleMode();
} else {
/** @type {number} */
(this._nextDecay) += this._tickInterval;
}
}
_runDecays() {
while (
/** @type {number} */ (this._nextDecay) <= Date.now() &&
this._mode !== STORAGE_MODE_IDLE
) {
this._decayLevel();
}
}
_enterAsyncMode() {
let timeout = 0;
switch (this._mode) {
case STORAGE_MODE_ASYNC:
return;
case STORAGE_MODE_IDLE:
this._nextDecay = Date.now() + this._tickInterval;
timeout = this._tickInterval;
break;
case STORAGE_MODE_SYNC:
this._runDecays();
// _runDecays may change the mode
if (
/** @type {STORAGE_MODE_IDLE | STORAGE_MODE_SYNC | STORAGE_MODE_ASYNC}*/
(this._mode) === STORAGE_MODE_IDLE
)
return;
timeout = Math.max(
0,
/** @type {number} */ (this._nextDecay) - Date.now()
);
break;
}
this._mode = STORAGE_MODE_ASYNC;
const ref = setTimeout(() => {
this._mode = STORAGE_MODE_SYNC;
this._runDecays();
}, timeout);
if (ref.unref) ref.unref();
this._timeout = ref;
}
_enterSyncModeWhenIdle() {
if (this._mode === STORAGE_MODE_IDLE) {
this._mode = STORAGE_MODE_SYNC;
this._nextDecay = Date.now() + this._tickInterval;
}
}
_enterIdleMode() {
this._mode = STORAGE_MODE_IDLE;
this._nextDecay = undefined;
if (this._timeout) clearTimeout(this._timeout);
}
}
/**
* @template {function} Provider
* @template {function} AsyncProvider
* @template FileSystem
* @param {number} duration duration in ms files are cached
* @param {Provider | undefined} provider provider
* @param {AsyncProvider | undefined} syncProvider sync provider
* @param {BaseFileSystem} providerContext provider context
* @returns {OperationMergerBackend | CacheBackend} backend
*/
const createBackend = (duration, provider, syncProvider, providerContext) => {
if (duration > 0) {
return new CacheBackend(duration, provider, syncProvider, providerContext);
}
return new OperationMergerBackend(provider, syncProvider, providerContext);
};
module.exports = class CachedInputFileSystem {
/**
* @param {BaseFileSystem} fileSystem file system
* @param {number} duration duration in ms files are cached
*/
constructor(fileSystem, duration) {
this.fileSystem = fileSystem;
this._lstatBackend = createBackend(
duration,
this.fileSystem.lstat,
this.fileSystem.lstatSync,
this.fileSystem
);
const lstat = this._lstatBackend.provide;
this.lstat = /** @type {FileSystem["lstat"]} */ (lstat);
const lstatSync = this._lstatBackend.provideSync;
this.lstatSync = /** @type {SyncFileSystem["lstatSync"]} */ (lstatSync);
this._statBackend = createBackend(
duration,
this.fileSystem.stat,
this.fileSystem.statSync,
this.fileSystem
);
const stat = this._statBackend.provide;
this.stat = /** @type {FileSystem["stat"]} */ (stat);
const statSync = this._statBackend.provideSync;
this.statSync = /** @type {SyncFileSystem["statSync"]} */ (statSync);
this._readdirBackend = createBackend(
duration,
this.fileSystem.readdir,
this.fileSystem.readdirSync,
this.fileSystem
);
const readdir = this._readdirBackend.provide;
this.readdir = /** @type {FileSystem["readdir"]} */ (readdir);
const readdirSync = this._readdirBackend.provideSync;
this.readdirSync = /** @type {SyncFileSystem["readdirSync"]} */ (
readdirSync
);
this._readFileBackend = createBackend(
duration,
this.fileSystem.readFile,
this.fileSystem.readFileSync,
this.fileSystem
);
const readFile = this._readFileBackend.provide;
this.readFile = /** @type {FileSystem["readFile"]} */ (readFile);
const readFileSync = this._readFileBackend.provideSync;
this.readFileSync = /** @type {SyncFileSystem["readFileSync"]} */ (
readFileSync
);
this._readJsonBackend = createBackend(
duration,
// prettier-ignore
this.fileSystem.readJson ||
(this.readFile &&
(
/**
* @param {string} path path
* @param {FileSystemCallback<any>} callback
*/
(path, callback) => {
this.readFile(path, (err, buffer) => {
if (err) return callback(err);
if (!buffer || buffer.length === 0)
return callback(new Error("No file content"));
let data;
try {
data = JSON.parse(buffer.toString("utf-8"));
} catch (e) {
return callback(/** @type {Error} */ (e));
}
callback(null, data);
});
})
),
// prettier-ignore
this.fileSystem.readJsonSync ||
(this.readFileSync &&
(
/**
* @param {string} path path
* @returns {any} result
*/
(path) => {
const buffer = this.readFileSync(path);
const data = JSON.parse(buffer.toString("utf-8"));
return data;
}
)),
this.fileSystem
);
const readJson = this._readJsonBackend.provide;
this.readJson = /** @type {FileSystem["readJson"]} */ (readJson);
const readJsonSync = this._readJsonBackend.provideSync;
this.readJsonSync = /** @type {SyncFileSystem["readJsonSync"]} */ (
readJsonSync
);
this._readlinkBackend = createBackend(
duration,
this.fileSystem.readlink,
this.fileSystem.readlinkSync,
this.fileSystem
);
const readlink = this._readlinkBackend.provide;
this.readlink = /** @type {FileSystem["readlink"]} */ (readlink);
const readlinkSync = this._readlinkBackend.provideSync;
this.readlinkSync = /** @type {SyncFileSystem["readlinkSync"]} */ (
readlinkSync
);
this._realpathBackend = createBackend(
duration,
this.fileSystem.realpath,
this.fileSystem.realpathSync,
this.fileSystem
);
const realpath = this._realpathBackend.provide;
this.realpath = /** @type {FileSystem["realpath"]} */ (realpath);
const realpathSync = this._realpathBackend.provideSync;
this.realpathSync = /** @type {SyncFileSystem["realpathSync"]} */ (
realpathSync
);
}
/**
* @param {string | Buffer | URL | number | (string | URL | Buffer | number)[] | Set<string | URL | Buffer | number>} [what] what to purge
*/
purge(what) {
this._statBackend.purge(what);
this._lstatBackend.purge(what);
this._readdirBackend.purgeParent(what);
this._readFileBackend.purge(what);
this._readlinkBackend.purge(what);
this._readJsonBackend.purge(what);
this._realpathBackend.purge(what);
}
};

View File

@@ -0,0 +1,175 @@
/**
* @fileoverview Rule to flag assignment in a conditional statement's test expression
* @author Stephen Murray <spmurrayzzz>
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const TEST_CONDITION_PARENT_TYPES = new Set([
"IfStatement",
"WhileStatement",
"DoWhileStatement",
"ForStatement",
"ConditionalExpression",
]);
const NODE_DESCRIPTIONS = {
DoWhileStatement: "a 'do...while' statement",
ForStatement: "a 'for' statement",
IfStatement: "an 'if' statement",
WhileStatement: "a 'while' statement",
};
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
type: "problem",
defaultOptions: ["except-parens"],
docs: {
description:
"Disallow assignment operators in conditional expressions",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-cond-assign",
},
schema: [
{
enum: ["except-parens", "always"],
},
],
messages: {
unexpected: "Unexpected assignment within {{type}}.",
// must match JSHint's error message
missing:
"Expected a conditional expression and instead saw an assignment.",
},
},
create(context) {
const [prohibitAssign] = context.options;
const sourceCode = context.sourceCode;
/**
* Check whether an AST node is the test expression for a conditional statement.
* @param {!Object} node The node to test.
* @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`.
*/
function isConditionalTestExpression(node) {
return (
node.parent &&
TEST_CONDITION_PARENT_TYPES.has(node.parent.type) &&
node === node.parent.test
);
}
/**
* Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement.
* @param {!Object} node The node to use at the start of the search.
* @returns {?Object} The closest ancestor node that represents a conditional statement.
*/
function findConditionalAncestor(node) {
let currentAncestor = node;
do {
if (isConditionalTestExpression(currentAncestor)) {
return currentAncestor.parent;
}
} while (
(currentAncestor = currentAncestor.parent) &&
!astUtils.isFunction(currentAncestor)
);
return null;
}
/**
* Check whether the code represented by an AST node is enclosed in two sets of parentheses.
* @param {!Object} node The node to test.
* @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`.
*/
function isParenthesisedTwice(node) {
const previousToken = sourceCode.getTokenBefore(node, 1),
nextToken = sourceCode.getTokenAfter(node, 1);
return (
astUtils.isParenthesised(sourceCode, node) &&
previousToken &&
astUtils.isOpeningParenToken(previousToken) &&
previousToken.range[1] <= node.range[0] &&
astUtils.isClosingParenToken(nextToken) &&
nextToken.range[0] >= node.range[1]
);
}
/**
* Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses.
* @param {!Object} node The node for the conditional statement.
* @returns {void}
*/
function testForAssign(node) {
if (
node.test &&
node.test.type === "AssignmentExpression" &&
(node.type === "ForStatement"
? !astUtils.isParenthesised(sourceCode, node.test)
: !isParenthesisedTwice(node.test))
) {
context.report({
node: node.test,
messageId: "missing",
});
}
}
/**
* Check whether an assignment expression is descended from a conditional statement's test expression.
* @param {!Object} node The node for the assignment expression.
* @returns {void}
*/
function testForConditionalAncestor(node) {
const ancestor = findConditionalAncestor(node);
if (ancestor) {
context.report({
node,
messageId: "unexpected",
data: {
type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type,
},
});
}
}
if (prohibitAssign === "always") {
return {
AssignmentExpression: testForConditionalAncestor,
};
}
return {
DoWhileStatement: testForAssign,
ForStatement: testForAssign,
IfStatement: testForAssign,
WhileStatement: testForAssign,
ConditionalExpression: testForAssign,
};
},
};