oxlint-plugin-react-doctor 0.7.5-dev.bc49aaa → 0.7.5-dev.dbd4067
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +97 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23108,61 +23108,73 @@ const PURE_GLOBAL_CALLEE_NAMES = new Set([
|
|
|
23108
23108
|
"Array",
|
|
23109
23109
|
"BigInt",
|
|
23110
23110
|
"Boolean",
|
|
23111
|
+
"encodeURIComponent",
|
|
23111
23112
|
"Number",
|
|
23112
23113
|
"Object",
|
|
23113
23114
|
"String",
|
|
23114
23115
|
"parseFloat",
|
|
23115
|
-
"parseInt"
|
|
23116
|
+
"parseInt",
|
|
23117
|
+
"structuredClone"
|
|
23118
|
+
]);
|
|
23119
|
+
const PURE_GLOBAL_CONSTRUCTOR_NAMES = new Set(["Date", "Set"]);
|
|
23120
|
+
const PURE_HELPER_NAMESPACE_MEMBER_NAMES = new Map([
|
|
23121
|
+
["Array", new Set(["from"])],
|
|
23122
|
+
["JSON", new Set([
|
|
23123
|
+
"isRawJSON",
|
|
23124
|
+
"parse",
|
|
23125
|
+
"rawJSON",
|
|
23126
|
+
"stringify"
|
|
23127
|
+
])],
|
|
23128
|
+
["Math", new Set([
|
|
23129
|
+
"abs",
|
|
23130
|
+
"acos",
|
|
23131
|
+
"acosh",
|
|
23132
|
+
"asin",
|
|
23133
|
+
"asinh",
|
|
23134
|
+
"atan",
|
|
23135
|
+
"atan2",
|
|
23136
|
+
"atanh",
|
|
23137
|
+
"cbrt",
|
|
23138
|
+
"ceil",
|
|
23139
|
+
"clz32",
|
|
23140
|
+
"cos",
|
|
23141
|
+
"cosh",
|
|
23142
|
+
"exp",
|
|
23143
|
+
"floor",
|
|
23144
|
+
"fround",
|
|
23145
|
+
"hypot",
|
|
23146
|
+
"imul",
|
|
23147
|
+
"log",
|
|
23148
|
+
"log10",
|
|
23149
|
+
"log1p",
|
|
23150
|
+
"log2",
|
|
23151
|
+
"max",
|
|
23152
|
+
"min",
|
|
23153
|
+
"pow",
|
|
23154
|
+
"round",
|
|
23155
|
+
"sign",
|
|
23156
|
+
"sin",
|
|
23157
|
+
"sinh",
|
|
23158
|
+
"sqrt",
|
|
23159
|
+
"tan",
|
|
23160
|
+
"tanh",
|
|
23161
|
+
"trunc"
|
|
23162
|
+
])],
|
|
23163
|
+
["Object", new Set(["assign"])]
|
|
23116
23164
|
]);
|
|
23117
|
-
const PURE_GLOBAL_NAMESPACE_NAMES = new Set(["JSON", "Math"]);
|
|
23118
|
-
const PURE_HELPER_NAMESPACE_MEMBER_NAMES = new Map([["JSON", new Set([
|
|
23119
|
-
"isRawJSON",
|
|
23120
|
-
"parse",
|
|
23121
|
-
"rawJSON",
|
|
23122
|
-
"stringify"
|
|
23123
|
-
])], ["Math", new Set([
|
|
23124
|
-
"abs",
|
|
23125
|
-
"acos",
|
|
23126
|
-
"acosh",
|
|
23127
|
-
"asin",
|
|
23128
|
-
"asinh",
|
|
23129
|
-
"atan",
|
|
23130
|
-
"atan2",
|
|
23131
|
-
"atanh",
|
|
23132
|
-
"cbrt",
|
|
23133
|
-
"ceil",
|
|
23134
|
-
"clz32",
|
|
23135
|
-
"cos",
|
|
23136
|
-
"cosh",
|
|
23137
|
-
"exp",
|
|
23138
|
-
"floor",
|
|
23139
|
-
"fround",
|
|
23140
|
-
"hypot",
|
|
23141
|
-
"imul",
|
|
23142
|
-
"log",
|
|
23143
|
-
"log10",
|
|
23144
|
-
"log1p",
|
|
23145
|
-
"log2",
|
|
23146
|
-
"max",
|
|
23147
|
-
"min",
|
|
23148
|
-
"pow",
|
|
23149
|
-
"round",
|
|
23150
|
-
"sign",
|
|
23151
|
-
"sin",
|
|
23152
|
-
"sinh",
|
|
23153
|
-
"sqrt",
|
|
23154
|
-
"tan",
|
|
23155
|
-
"tanh",
|
|
23156
|
-
"trunc"
|
|
23157
|
-
])]]);
|
|
23158
23165
|
const PURE_MEMBER_TRANSFORM_NAMES = new Set([
|
|
23159
23166
|
"concat",
|
|
23160
23167
|
"filter",
|
|
23168
|
+
"flatMap",
|
|
23161
23169
|
"join",
|
|
23162
23170
|
"map",
|
|
23171
|
+
"reduce",
|
|
23172
|
+
"replace",
|
|
23173
|
+
"slice",
|
|
23163
23174
|
"split",
|
|
23164
23175
|
"toLowerCase",
|
|
23165
23176
|
"toString",
|
|
23177
|
+
"toSorted",
|
|
23166
23178
|
"toUpperCase",
|
|
23167
23179
|
"trim"
|
|
23168
23180
|
]);
|
|
@@ -23544,6 +23556,11 @@ const analyzeHelperExpression = (expression, environment, usedParameterIndices)
|
|
|
23544
23556
|
const callbackSummary = analyzeHelperStatements(node.body.body ?? [], callbackEnvironment, usedParameterIndices, analyzeHelperExpression);
|
|
23545
23557
|
return callbackSummary.isValid && !callbackSummary.canContinue;
|
|
23546
23558
|
}
|
|
23559
|
+
if (isNodeOfType(node, "NewExpression")) {
|
|
23560
|
+
const callee = stripParenExpression(node.callee);
|
|
23561
|
+
if (!isNodeOfType(callee, "Identifier") || !PURE_GLOBAL_CONSTRUCTOR_NAMES.has(callee.name) || environment.parameterIndices.has(callee.name) || environment.recursiveNames.has(callee.name) || environment.shadowedGlobalNames.has(callee.name)) return false;
|
|
23562
|
+
return (node.arguments ?? []).every((argument) => analyzeHelperExpression(argument, environment, usedParameterIndices));
|
|
23563
|
+
}
|
|
23547
23564
|
if (isNodeOfType(node, "CallExpression")) {
|
|
23548
23565
|
const callee = stripParenExpression(node.callee);
|
|
23549
23566
|
const calleeRoot = getMemberRoot(callee);
|
|
@@ -23746,7 +23763,7 @@ const collectValueEvidence = (analysis, expression, frame, remainingCallFrames,
|
|
|
23746
23763
|
}
|
|
23747
23764
|
const callee = stripParenExpression(node.callee);
|
|
23748
23765
|
const calleeRoot = getMemberRoot(callee);
|
|
23749
|
-
const isPureGlobalCall = isNodeOfType(callee, "Identifier") && PURE_GLOBAL_CALLEE_NAMES.has(callee.name) && getIdentifierBindingIdentity(analysis, callee) === null || isNodeOfType(
|
|
23766
|
+
const isPureGlobalCall = isNodeOfType(callee, "Identifier") && PURE_GLOBAL_CALLEE_NAMES.has(callee.name) && getIdentifierBindingIdentity(analysis, callee) === null || isNodeOfType(callee, "MemberExpression") && isNodeOfType(calleeRoot, "Identifier") && getIdentifierBindingIdentity(analysis, calleeRoot) === null && PURE_HELPER_NAMESPACE_MEMBER_NAMES.get(calleeRoot.name)?.has(getStaticMemberName$1(callee) ?? "") === true;
|
|
23750
23767
|
const isPureMemberTransform = isNodeOfType(callee, "MemberExpression") && PURE_MEMBER_TRANSFORM_NAMES.has(getStaticMemberName$1(callee) ?? "");
|
|
23751
23768
|
if (isPureGlobalCall || isPureMemberTransform) {
|
|
23752
23769
|
if (isPureMemberTransform && isNodeOfType(callee, "MemberExpression")) mergeEvidence(evidence, collectValueEvidence(analysis, callee.object, frame, remainingCallFrames, new Set(visitedBindings)));
|
|
@@ -23799,6 +23816,15 @@ const collectValueEvidence = (analysis, expression, frame, remainingCallFrames,
|
|
|
23799
23816
|
}
|
|
23800
23817
|
return evidence;
|
|
23801
23818
|
}
|
|
23819
|
+
if (isNodeOfType(node, "NewExpression")) {
|
|
23820
|
+
const callee = stripParenExpression(node.callee);
|
|
23821
|
+
if (!isNodeOfType(callee, "Identifier") || !PURE_GLOBAL_CONSTRUCTOR_NAMES.has(callee.name) || getIdentifierBindingIdentity(analysis, callee) !== null) {
|
|
23822
|
+
evidence.hasUnknownSource = true;
|
|
23823
|
+
return evidence;
|
|
23824
|
+
}
|
|
23825
|
+
for (const argument of node.arguments ?? []) mergeEvidence(evidence, collectValueEvidence(analysis, argument, frame, remainingCallFrames, new Set(visitedBindings)));
|
|
23826
|
+
return evidence;
|
|
23827
|
+
}
|
|
23802
23828
|
if (isFunctionLike$1(node) || isNodeOfType(node, "AwaitExpression")) {
|
|
23803
23829
|
evidence.hasUnknownSource = true;
|
|
23804
23830
|
return evidence;
|
|
@@ -28348,20 +28374,31 @@ const noDocumentStartViewTransition = defineRule({
|
|
|
28348
28374
|
} })
|
|
28349
28375
|
});
|
|
28350
28376
|
//#endregion
|
|
28377
|
+
//#region src/plugin/utils/get-static-property-name.ts
|
|
28378
|
+
const getStaticPropertyName = (memberExpression) => {
|
|
28379
|
+
const property = memberExpression.property;
|
|
28380
|
+
if (!memberExpression.computed && isNodeOfType(property, "Identifier")) return property.name;
|
|
28381
|
+
if (memberExpression.computed && isNodeOfType(property, "Literal")) return typeof property.value === "string" ? property.value : null;
|
|
28382
|
+
if (memberExpression.computed && isNodeOfType(property, "TemplateLiteral") && property.expressions.length === 0) return property.quasis[0]?.value.cooked ?? property.quasis[0]?.value.raw ?? null;
|
|
28383
|
+
return null;
|
|
28384
|
+
};
|
|
28385
|
+
//#endregion
|
|
28351
28386
|
//#region src/plugin/rules/js-performance/no-document-write.ts
|
|
28352
28387
|
const MESSAGE$24 = "`document.write()` blocks parsing, is ignored (or wipes the page) after load, and is flagged by browsers as a performance anti-pattern. Build DOM nodes or set `innerHTML`/`textContent` on a target element instead.";
|
|
28353
28388
|
const WRITE_METHODS = new Set(["write", "writeln"]);
|
|
28389
|
+
const isGlobalDocumentReference = (node, context) => node.name === "document" && context.scopes.isGlobalReference(node);
|
|
28354
28390
|
const noDocumentWrite = defineRule({
|
|
28355
28391
|
id: "no-document-write",
|
|
28356
28392
|
title: "document.write/writeln",
|
|
28357
28393
|
severity: "warn",
|
|
28358
28394
|
recommendation: "Don't use `document.write()`/`document.writeln()`. Append DOM nodes or set `innerHTML`/`textContent` on a specific element instead.",
|
|
28359
28395
|
create: (context) => ({ CallExpression(node) {
|
|
28360
|
-
const callee = node.callee;
|
|
28361
|
-
if (!isNodeOfType(callee, "MemberExpression")
|
|
28396
|
+
const callee = stripParenExpression(node.callee);
|
|
28397
|
+
if (!isNodeOfType(callee, "MemberExpression")) return;
|
|
28362
28398
|
const receiver = stripParenExpression(callee.object);
|
|
28363
|
-
if (!isNodeOfType(receiver, "Identifier") || receiver
|
|
28364
|
-
|
|
28399
|
+
if (!isNodeOfType(receiver, "Identifier") || !isGlobalDocumentReference(receiver, context)) return;
|
|
28400
|
+
const methodName = getStaticPropertyName(callee);
|
|
28401
|
+
if (methodName === null || !WRITE_METHODS.has(methodName)) return;
|
|
28365
28402
|
context.report({
|
|
28366
28403
|
node,
|
|
28367
28404
|
message: MESSAGE$24
|
|
@@ -29168,6 +29205,14 @@ const noEffectWithFreshDeps = defineRule({
|
|
|
29168
29205
|
//#endregion
|
|
29169
29206
|
//#region src/plugin/rules/security/no-eval.ts
|
|
29170
29207
|
const SANDBOX_SURFACE_PATH_PATTERN = /(?:^|[/-])sandbox(?:$|[/-])|(?:^|\/)[\w.]+-sandbox(?:\/|\.[cm]?[jt]sx?$)/i;
|
|
29208
|
+
const getExecutableGlobalName = (node, context) => {
|
|
29209
|
+
const expression = stripParenExpression(node);
|
|
29210
|
+
if (isNodeOfType(expression, "Identifier")) return context.scopes.isGlobalReference(expression) ? expression.name : null;
|
|
29211
|
+
if (!isNodeOfType(expression, "MemberExpression")) return null;
|
|
29212
|
+
const receiver = stripParenExpression(expression.object);
|
|
29213
|
+
if (!isNodeOfType(receiver, "Identifier") || receiver.name !== "globalThis" || !context.scopes.isGlobalReference(receiver)) return null;
|
|
29214
|
+
return getStaticPropertyName(expression);
|
|
29215
|
+
};
|
|
29171
29216
|
const noEval = defineRule({
|
|
29172
29217
|
id: "no-eval",
|
|
29173
29218
|
title: "eval() runs untrusted code strings",
|
|
@@ -29177,20 +29222,21 @@ const noEval = defineRule({
|
|
|
29177
29222
|
if (SANDBOX_SURFACE_PATH_PATTERN.test(normalizeFilename(context.filename ?? ""))) return {};
|
|
29178
29223
|
return {
|
|
29179
29224
|
CallExpression(node) {
|
|
29180
|
-
|
|
29225
|
+
const executableGlobalName = getExecutableGlobalName(node.callee, context);
|
|
29226
|
+
if (executableGlobalName === "eval") {
|
|
29181
29227
|
context.report({
|
|
29182
29228
|
node,
|
|
29183
29229
|
message: "eval() is a code-injection vulnerability: it runs any string as code."
|
|
29184
29230
|
});
|
|
29185
29231
|
return;
|
|
29186
29232
|
}
|
|
29187
|
-
if (
|
|
29233
|
+
if ((executableGlobalName === "setTimeout" || executableGlobalName === "setInterval") && isNodeOfType(node.arguments?.[0], "Literal") && typeof node.arguments[0].value === "string") context.report({
|
|
29188
29234
|
node,
|
|
29189
|
-
message: `Passing a string to ${
|
|
29235
|
+
message: `Passing a string to ${executableGlobalName}() is a code-injection vulnerability, since it runs that string as code.`
|
|
29190
29236
|
});
|
|
29191
29237
|
},
|
|
29192
29238
|
NewExpression(node) {
|
|
29193
|
-
if (
|
|
29239
|
+
if (getExecutableGlobalName(node.callee, context) === "Function") {
|
|
29194
29240
|
const onlyArgument = node.arguments.length === 1 ? node.arguments[0] : void 0;
|
|
29195
29241
|
if (isNodeOfType(onlyArgument, "Literal") && typeof onlyArgument.value === "string" && onlyArgument.value.trim() === "return this") return;
|
|
29196
29242
|
context.report({
|
|
@@ -54751,12 +54797,6 @@ const webhookSignatureRisk = defineRule({
|
|
|
54751
54797
|
//#region src/plugin/rules/zod/utils/zod-ast.ts
|
|
54752
54798
|
const ZOD_MODULE = "zod";
|
|
54753
54799
|
const ZOD_MODULE_SOURCES = [ZOD_MODULE];
|
|
54754
|
-
const getStaticPropertyName = (member) => {
|
|
54755
|
-
const property = member.property;
|
|
54756
|
-
if (!member.computed && isNodeOfType(property, "Identifier")) return property.name;
|
|
54757
|
-
if (member.computed && isNodeOfType(property, "Literal") && typeof property.value === "string") return property.value;
|
|
54758
|
-
return null;
|
|
54759
|
-
};
|
|
54760
54800
|
const importInfoCache = /* @__PURE__ */ new WeakMap();
|
|
54761
54801
|
const getImportInfoForIdentifier = (identifier) => {
|
|
54762
54802
|
if (importInfoCache.has(identifier)) return importInfoCache.get(identifier) ?? null;
|