build: update npm install command to use --legacy-peer-deps
This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
This commit is contained in:
1 parent
20129a1ac7
commit
ac4f232e5e
787 files changed
+82341
-121690
No files matched your search
+261
-295
@@ -23,343 +23,309 @@ const astUtils = require("./utils/ast-utils");
|
||||
* @returns {boolean} `true` if the node is a constructor.
|
||||
*/
|
||||
function isConstructorFunction(node) {
|
||||
return (
|
||||
node.type === "FunctionExpression" &&
|
||||
node.parent.type === "MethodDefinition" &&
|
||||
node.parent.kind === "constructor"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Information for each code path segment.
|
||||
* - superCalled: The flag which shows `super()` called in all code paths.
|
||||
* - invalidNodes: The array of invalid ThisExpression and Super nodes.
|
||||
*/
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class SegmentInfo {
|
||||
/**
|
||||
* Indicates whether `super()` is called in all code paths.
|
||||
* @type {boolean}
|
||||
*/
|
||||
superCalled = false;
|
||||
|
||||
/**
|
||||
* The array of invalid ThisExpression and Super nodes.
|
||||
* @type {ASTNode[]}
|
||||
*/
|
||||
invalidNodes = [];
|
||||
return (
|
||||
node.type === "FunctionExpression" &&
|
||||
node.parent.type === "MethodDefinition" &&
|
||||
node.parent.kind === "constructor"
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow `this`/`super` before calling `super()` in constructors",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-this-before-super",
|
||||
},
|
||||
docs: {
|
||||
description: "Disallow `this`/`super` before calling `super()` in constructors",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-this-before-super"
|
||||
},
|
||||
|
||||
schema: [],
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
noBeforeSuper: "'{{kind}}' is not allowed before 'super()'.",
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
noBeforeSuper: "'{{kind}}' is not allowed before 'super()'."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
/*
|
||||
* Information for each constructor.
|
||||
* - upper: Information of the upper constructor.
|
||||
* - hasExtends: A flag which shows whether the owner class has a valid
|
||||
* `extends` part.
|
||||
* - scope: The scope of the owner class.
|
||||
* - codePath: The code path of this constructor.
|
||||
*/
|
||||
let funcInfo = null;
|
||||
create(context) {
|
||||
|
||||
/** @type {Record<string, SegmentInfo>} */
|
||||
let segInfoMap = Object.create(null);
|
||||
/*
|
||||
* Information for each constructor.
|
||||
* - upper: Information of the upper constructor.
|
||||
* - hasExtends: A flag which shows whether the owner class has a valid
|
||||
* `extends` part.
|
||||
* - scope: The scope of the owner class.
|
||||
* - codePath: The code path of this constructor.
|
||||
*/
|
||||
let funcInfo = null;
|
||||
|
||||
/**
|
||||
* Gets whether or not `super()` is called in a given code path segment.
|
||||
* @param {CodePathSegment} segment A code path segment to get.
|
||||
* @returns {boolean} `true` if `super()` is called.
|
||||
*/
|
||||
function isCalled(segment) {
|
||||
return !segment.reachable || segInfoMap[segment.id]?.superCalled;
|
||||
}
|
||||
/*
|
||||
* Information for each code path segment.
|
||||
* Each key is the id of a code path segment.
|
||||
* Each value is an object:
|
||||
* - superCalled: The flag which shows `super()` called in all code paths.
|
||||
* - invalidNodes: The array of invalid ThisExpression and Super nodes.
|
||||
*/
|
||||
let segInfoMap = Object.create(null);
|
||||
|
||||
/**
|
||||
* Checks whether or not this is in a constructor.
|
||||
* @returns {boolean} `true` if this is in a constructor.
|
||||
*/
|
||||
function isInConstructorOfDerivedClass() {
|
||||
return Boolean(
|
||||
funcInfo && funcInfo.isConstructor && funcInfo.hasExtends,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Gets whether or not `super()` is called in a given code path segment.
|
||||
* @param {CodePathSegment} segment A code path segment to get.
|
||||
* @returns {boolean} `true` if `super()` is called.
|
||||
*/
|
||||
function isCalled(segment) {
|
||||
return !segment.reachable || segInfoMap[segment.id].superCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if every segment in a set has been called.
|
||||
* @param {Set<CodePathSegment>} segments The segments to search.
|
||||
* @returns {boolean} True if every segment has been called; false otherwise.
|
||||
*/
|
||||
function isEverySegmentCalled(segments) {
|
||||
for (const segment of segments) {
|
||||
if (!isCalled(segment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks whether or not this is in a constructor.
|
||||
* @returns {boolean} `true` if this is in a constructor.
|
||||
*/
|
||||
function isInConstructorOfDerivedClass() {
|
||||
return Boolean(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Determines if every segment in a set has been called.
|
||||
* @param {Set<CodePathSegment>} segments The segments to search.
|
||||
* @returns {boolean} True if every segment has been called; false otherwise.
|
||||
*/
|
||||
function isEverySegmentCalled(segments) {
|
||||
for (const segment of segments) {
|
||||
if (!isCalled(segment)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not this is before `super()` is called.
|
||||
* @returns {boolean} `true` if this is before `super()` is called.
|
||||
*/
|
||||
function isBeforeCallOfSuper() {
|
||||
return (
|
||||
isInConstructorOfDerivedClass() &&
|
||||
!isEverySegmentCalled(funcInfo.currentSegments)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a given node as invalid.
|
||||
* @param {ASTNode} node A node to set as invalid. This is one of
|
||||
* a ThisExpression and a Super.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setInvalid(node) {
|
||||
const segments = funcInfo.currentSegments;
|
||||
/**
|
||||
* Checks whether or not this is before `super()` is called.
|
||||
* @returns {boolean} `true` if this is before `super()` is called.
|
||||
*/
|
||||
function isBeforeCallOfSuper() {
|
||||
return (
|
||||
isInConstructorOfDerivedClass() &&
|
||||
!isEverySegmentCalled(funcInfo.currentSegments)
|
||||
);
|
||||
}
|
||||
|
||||
for (const segment of segments) {
|
||||
if (segment.reachable) {
|
||||
segInfoMap[segment.id].invalidNodes.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets a given node as invalid.
|
||||
* @param {ASTNode} node A node to set as invalid. This is one of
|
||||
* a ThisExpression and a Super.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setInvalid(node) {
|
||||
const segments = funcInfo.currentSegments;
|
||||
|
||||
/**
|
||||
* Sets the current segment as `super` was called.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setSuperCalled() {
|
||||
const segments = funcInfo.currentSegments;
|
||||
for (const segment of segments) {
|
||||
if (segment.reachable) {
|
||||
segInfoMap[segment.id].invalidNodes.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const segment of segments) {
|
||||
if (segment.reachable) {
|
||||
segInfoMap[segment.id].superCalled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the current segment as `super` was called.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setSuperCalled() {
|
||||
const segments = funcInfo.currentSegments;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Adds information of a constructor into the stack.
|
||||
* @param {CodePath} codePath A code path which was started.
|
||||
* @param {ASTNode} node The current node.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathStart(codePath, node) {
|
||||
if (isConstructorFunction(node)) {
|
||||
// Class > ClassBody > MethodDefinition > FunctionExpression
|
||||
const classNode = node.parent.parent.parent;
|
||||
for (const segment of segments) {
|
||||
if (segment.reachable) {
|
||||
segInfoMap[segment.id].superCalled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
funcInfo = {
|
||||
upper: funcInfo,
|
||||
isConstructor: true,
|
||||
hasExtends: Boolean(
|
||||
classNode.superClass &&
|
||||
!astUtils.isNullOrUndefined(
|
||||
classNode.superClass,
|
||||
),
|
||||
),
|
||||
codePath,
|
||||
currentSegments: new Set(),
|
||||
};
|
||||
} else {
|
||||
funcInfo = {
|
||||
upper: funcInfo,
|
||||
isConstructor: false,
|
||||
hasExtends: false,
|
||||
codePath,
|
||||
currentSegments: new Set(),
|
||||
};
|
||||
}
|
||||
},
|
||||
return {
|
||||
|
||||
/**
|
||||
* Removes the top of stack item.
|
||||
*
|
||||
* And this traverses all segments of this code path then reports every
|
||||
* invalid node.
|
||||
* @param {CodePath} codePath A code path which was ended.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathEnd(codePath) {
|
||||
const isDerivedClass = funcInfo.hasExtends;
|
||||
/**
|
||||
* Adds information of a constructor into the stack.
|
||||
* @param {CodePath} codePath A code path which was started.
|
||||
* @param {ASTNode} node The current node.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathStart(codePath, node) {
|
||||
if (isConstructorFunction(node)) {
|
||||
|
||||
funcInfo = funcInfo.upper;
|
||||
if (!isDerivedClass) {
|
||||
return;
|
||||
}
|
||||
// Class > ClassBody > MethodDefinition > FunctionExpression
|
||||
const classNode = node.parent.parent.parent;
|
||||
|
||||
/**
|
||||
* A collection of nodes to avoid duplicate reports.
|
||||
* @type {Set<ASTNode>}
|
||||
*/
|
||||
const reported = new Set();
|
||||
funcInfo = {
|
||||
upper: funcInfo,
|
||||
isConstructor: true,
|
||||
hasExtends: Boolean(
|
||||
classNode.superClass &&
|
||||
!astUtils.isNullOrUndefined(classNode.superClass)
|
||||
),
|
||||
codePath,
|
||||
currentSegments: new Set()
|
||||
};
|
||||
} else {
|
||||
funcInfo = {
|
||||
upper: funcInfo,
|
||||
isConstructor: false,
|
||||
hasExtends: false,
|
||||
codePath,
|
||||
currentSegments: new Set()
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
codePath.traverseSegments((segment, controller) => {
|
||||
const info = segInfoMap[segment.id];
|
||||
const invalidNodes = info.invalidNodes.filter(
|
||||
/*
|
||||
* Avoid duplicate reports.
|
||||
* When there is a `finally`, invalidNodes may contain already reported node.
|
||||
*/
|
||||
node => !reported.has(node),
|
||||
);
|
||||
/**
|
||||
* Removes the top of stack item.
|
||||
*
|
||||
* And this traverses all segments of this code path then reports every
|
||||
* invalid node.
|
||||
* @param {CodePath} codePath A code path which was ended.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathEnd(codePath) {
|
||||
const isDerivedClass = funcInfo.hasExtends;
|
||||
|
||||
for (const invalidNode of invalidNodes) {
|
||||
reported.add(invalidNode);
|
||||
funcInfo = funcInfo.upper;
|
||||
if (!isDerivedClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({
|
||||
messageId: "noBeforeSuper",
|
||||
node: invalidNode,
|
||||
data: {
|
||||
kind:
|
||||
invalidNode.type === "Super"
|
||||
? "super"
|
||||
: "this",
|
||||
},
|
||||
});
|
||||
}
|
||||
codePath.traverseSegments((segment, controller) => {
|
||||
const info = segInfoMap[segment.id];
|
||||
|
||||
if (info.superCalled) {
|
||||
controller.skip();
|
||||
}
|
||||
});
|
||||
},
|
||||
for (let i = 0; i < info.invalidNodes.length; ++i) {
|
||||
const invalidNode = info.invalidNodes[i];
|
||||
|
||||
/**
|
||||
* Initialize information of a given code path segment.
|
||||
* @param {CodePathSegment} segment A code path segment to initialize.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathSegmentStart(segment) {
|
||||
funcInfo.currentSegments.add(segment);
|
||||
context.report({
|
||||
messageId: "noBeforeSuper",
|
||||
node: invalidNode,
|
||||
data: {
|
||||
kind: invalidNode.type === "Super" ? "super" : "this"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!isInConstructorOfDerivedClass()) {
|
||||
return;
|
||||
}
|
||||
if (info.superCalled) {
|
||||
controller.skip();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Initialize info.
|
||||
segInfoMap[segment.id] = {
|
||||
superCalled:
|
||||
segment.prevSegments.length > 0 &&
|
||||
segment.prevSegments.every(isCalled),
|
||||
invalidNodes: [],
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Initialize information of a given code path segment.
|
||||
* @param {CodePathSegment} segment A code path segment to initialize.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathSegmentStart(segment) {
|
||||
funcInfo.currentSegments.add(segment);
|
||||
|
||||
onUnreachableCodePathSegmentStart(segment) {
|
||||
funcInfo.currentSegments.add(segment);
|
||||
},
|
||||
if (!isInConstructorOfDerivedClass()) {
|
||||
return;
|
||||
}
|
||||
|
||||
onUnreachableCodePathSegmentEnd(segment) {
|
||||
funcInfo.currentSegments.delete(segment);
|
||||
},
|
||||
// Initialize info.
|
||||
segInfoMap[segment.id] = {
|
||||
superCalled: (
|
||||
segment.prevSegments.length > 0 &&
|
||||
segment.prevSegments.every(isCalled)
|
||||
),
|
||||
invalidNodes: []
|
||||
};
|
||||
},
|
||||
|
||||
onCodePathSegmentEnd(segment) {
|
||||
funcInfo.currentSegments.delete(segment);
|
||||
},
|
||||
onUnreachableCodePathSegmentStart(segment) {
|
||||
funcInfo.currentSegments.add(segment);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update information of the code path segment when a code path was
|
||||
* looped.
|
||||
* @param {CodePathSegment} fromSegment The code path segment of the
|
||||
* end of a loop.
|
||||
* @param {CodePathSegment} toSegment A code path segment of the head
|
||||
* of a loop.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathSegmentLoop(fromSegment, toSegment) {
|
||||
if (!isInConstructorOfDerivedClass()) {
|
||||
return;
|
||||
}
|
||||
onUnreachableCodePathSegmentEnd(segment) {
|
||||
funcInfo.currentSegments.delete(segment);
|
||||
},
|
||||
|
||||
// Update information inside of the loop.
|
||||
funcInfo.codePath.traverseSegments(
|
||||
{ first: toSegment, last: fromSegment },
|
||||
(segment, controller) => {
|
||||
const info =
|
||||
segInfoMap[segment.id] ?? new SegmentInfo();
|
||||
onCodePathSegmentEnd(segment) {
|
||||
funcInfo.currentSegments.delete(segment);
|
||||
},
|
||||
|
||||
if (info.superCalled) {
|
||||
controller.skip();
|
||||
} else if (
|
||||
segment.prevSegments.length > 0 &&
|
||||
segment.prevSegments.every(isCalled)
|
||||
) {
|
||||
info.superCalled = true;
|
||||
}
|
||||
/**
|
||||
* Update information of the code path segment when a code path was
|
||||
* looped.
|
||||
* @param {CodePathSegment} fromSegment The code path segment of the
|
||||
* end of a loop.
|
||||
* @param {CodePathSegment} toSegment A code path segment of the head
|
||||
* of a loop.
|
||||
* @returns {void}
|
||||
*/
|
||||
onCodePathSegmentLoop(fromSegment, toSegment) {
|
||||
if (!isInConstructorOfDerivedClass()) {
|
||||
return;
|
||||
}
|
||||
|
||||
segInfoMap[segment.id] = info;
|
||||
},
|
||||
);
|
||||
},
|
||||
// Update information inside of the loop.
|
||||
funcInfo.codePath.traverseSegments(
|
||||
{ first: toSegment, last: fromSegment },
|
||||
(segment, controller) => {
|
||||
const info = segInfoMap[segment.id];
|
||||
|
||||
/**
|
||||
* Reports if this is before `super()`.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
ThisExpression(node) {
|
||||
if (isBeforeCallOfSuper()) {
|
||||
setInvalid(node);
|
||||
}
|
||||
},
|
||||
if (info.superCalled) {
|
||||
info.invalidNodes = [];
|
||||
controller.skip();
|
||||
} else if (
|
||||
segment.prevSegments.length > 0 &&
|
||||
segment.prevSegments.every(isCalled)
|
||||
) {
|
||||
info.superCalled = true;
|
||||
info.invalidNodes = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reports if this is before `super()`.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
Super(node) {
|
||||
if (!astUtils.isCallee(node) && isBeforeCallOfSuper()) {
|
||||
setInvalid(node);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Reports if this is before `super()`.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
ThisExpression(node) {
|
||||
if (isBeforeCallOfSuper()) {
|
||||
setInvalid(node);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks `super()` called.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
"CallExpression:exit"(node) {
|
||||
if (node.callee.type === "Super" && isBeforeCallOfSuper()) {
|
||||
setSuperCalled();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Reports if this is before `super()`.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
Super(node) {
|
||||
if (!astUtils.isCallee(node) && isBeforeCallOfSuper()) {
|
||||
setInvalid(node);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets state.
|
||||
* @returns {void}
|
||||
*/
|
||||
"Program:exit"() {
|
||||
segInfoMap = Object.create(null);
|
||||
},
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Marks `super()` called.
|
||||
* @param {ASTNode} node A target node.
|
||||
* @returns {void}
|
||||
*/
|
||||
"CallExpression:exit"(node) {
|
||||
if (node.callee.type === "Super" && isBeforeCallOfSuper()) {
|
||||
setSuperCalled();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets state.
|
||||
* @returns {void}
|
||||
*/
|
||||
"Program:exit"() {
|
||||
segInfoMap = Object.create(null);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user