oxlint-plugin-react-doctor 0.9.2-dev.1f6e181 → 0.9.2-dev.2992a03
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 +122 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -56090,6 +56090,9 @@ const isInitialOnlyPropName = (propName) => {
|
|
|
56090
56090
|
return /^initial[A-Z]/.test(propName) || /^default[A-Z]/.test(propName) || /^seed[A-Z]/.test(propName) || /^starting[A-Z]/.test(propName) || /^baseline[A-Z]/.test(propName) || /^preset[A-Z]/.test(propName);
|
|
56091
56091
|
};
|
|
56092
56092
|
//#endregion
|
|
56093
|
+
//#region src/plugin/utils/nextjs-page-data-export-names.ts
|
|
56094
|
+
const NEXTJS_PAGE_DATA_EXPORT_NAMES = new Set(["getServerSideProps", "getStaticProps"]);
|
|
56095
|
+
//#endregion
|
|
56093
56096
|
//#region src/plugin/rules/state-and-effects/no-derived-use-state.ts
|
|
56094
56097
|
const isInitialOnlySeedName = (propName) => isInitialOnlyPropName(propName) || propName === "initial" || propName === "autoFocus" || propName === "autoPlay" || propName === "startOpen" || /^initially[A-Z]/.test(propName) || /Initial([A-Z]|$)/.test(propName);
|
|
56095
56098
|
const SNAPSHOT_STATE_NAME_PATTERN = /^(initial|previous|prev|preserved|saved|original|cached|snapshot|prior|debounced|deferred)([A-Z_]|$)/;
|
|
@@ -56246,7 +56249,6 @@ const isDraftCommittedToParent = (componentFunction, stateValueName, isPropName)
|
|
|
56246
56249
|
});
|
|
56247
56250
|
return isCommitted;
|
|
56248
56251
|
};
|
|
56249
|
-
const NEXTJS_PAGE_DATA_EXPORT_NAMES = new Set(["getServerSideProps", "getStaticProps"]);
|
|
56250
56252
|
const isNextjsDataFetchingPage = (node) => {
|
|
56251
56253
|
const program = findProgramRoot(node);
|
|
56252
56254
|
if (!program) return false;
|
|
@@ -67191,6 +67193,124 @@ const isInsideSnapshotHelper = (node) => {
|
|
|
67191
67193
|
}
|
|
67192
67194
|
return false;
|
|
67193
67195
|
};
|
|
67196
|
+
const findEnclosingNextjsPageDataFunction = (node) => {
|
|
67197
|
+
let outermostFunction = null;
|
|
67198
|
+
let cursor = node.parent;
|
|
67199
|
+
while (cursor) {
|
|
67200
|
+
if (isFunctionLike$1(cursor)) outermostFunction = cursor;
|
|
67201
|
+
if (isNodeOfType(cursor, "Program")) {
|
|
67202
|
+
if (!outermostFunction) return null;
|
|
67203
|
+
for (const exportName of NEXTJS_PAGE_DATA_EXPORT_NAMES) {
|
|
67204
|
+
const exportedValue = findExportedValue(cursor, exportName);
|
|
67205
|
+
if (exportedValue && isAstDescendant(outermostFunction, exportedValue)) return outermostFunction;
|
|
67206
|
+
}
|
|
67207
|
+
return null;
|
|
67208
|
+
}
|
|
67209
|
+
cursor = cursor.parent ?? null;
|
|
67210
|
+
}
|
|
67211
|
+
return null;
|
|
67212
|
+
};
|
|
67213
|
+
const findConditionalReturnExpressionRoot = (node) => {
|
|
67214
|
+
let expressionRoot = findTransparentExpressionRoot(node);
|
|
67215
|
+
while (expressionRoot.parent && isNodeOfType(expressionRoot.parent, "ConditionalExpression") && (expressionRoot.parent.consequent === expressionRoot || expressionRoot.parent.alternate === expressionRoot)) expressionRoot = findTransparentExpressionRoot(expressionRoot.parent);
|
|
67216
|
+
return expressionRoot;
|
|
67217
|
+
};
|
|
67218
|
+
const isReturnedPageDataResultBinding = (returnExpression, pageDataFunction, context) => {
|
|
67219
|
+
const declarator = returnExpression.parent;
|
|
67220
|
+
if (!isNodeOfType(declarator, "VariableDeclarator") || declarator.init !== returnExpression || !isNodeOfType(declarator.id, "Identifier") || findEnclosingFunction$1(declarator) !== pageDataFunction) return false;
|
|
67221
|
+
const bindingSymbol = context.scopes.symbolFor(declarator.id);
|
|
67222
|
+
if (!bindingSymbol || bindingSymbol.references.length !== 1) return false;
|
|
67223
|
+
const referenceRoot = findTransparentExpressionRoot(bindingSymbol.references[0].identifier);
|
|
67224
|
+
const returnStatement = referenceRoot.parent;
|
|
67225
|
+
return isNodeOfType(returnStatement, "ReturnStatement") && returnStatement.argument === referenceRoot && findEnclosingFunction$1(returnStatement) === pageDataFunction;
|
|
67226
|
+
};
|
|
67227
|
+
const isSameShorthandPropertyValue = (node, property) => property.shorthand && (node === property.key || node === property.value);
|
|
67228
|
+
const isValueForwardedThroughLiteralStructure = (node, structure) => {
|
|
67229
|
+
const strippedNode = stripParenExpression(node);
|
|
67230
|
+
const strippedStructure = stripParenExpression(structure);
|
|
67231
|
+
if (strippedNode === strippedStructure) return true;
|
|
67232
|
+
if (isNodeOfType(strippedStructure, "ConditionalExpression")) return isValueForwardedThroughLiteralStructure(strippedNode, strippedStructure.consequent) || isValueForwardedThroughLiteralStructure(strippedNode, strippedStructure.alternate);
|
|
67233
|
+
if (isNodeOfType(strippedStructure, "ArrayExpression")) return strippedStructure.elements.some((element) => element && !isNodeOfType(element, "SpreadElement") && isValueForwardedThroughLiteralStructure(strippedNode, element));
|
|
67234
|
+
if (!isNodeOfType(strippedStructure, "ObjectExpression")) return false;
|
|
67235
|
+
return strippedStructure.properties.some((property) => {
|
|
67236
|
+
if (isNodeOfType(property, "SpreadElement")) return isValueForwardedThroughLiteralStructure(strippedNode, property.argument);
|
|
67237
|
+
if (!isNodeOfType(property, "Property")) return false;
|
|
67238
|
+
if (isValueForwardedThroughLiteralStructure(strippedNode, property.value)) return true;
|
|
67239
|
+
return isSameShorthandPropertyValue(strippedNode, property);
|
|
67240
|
+
});
|
|
67241
|
+
};
|
|
67242
|
+
const isValueForwardedToPropertyValue = (node, property) => {
|
|
67243
|
+
const directValue = findConditionalReturnExpressionRoot(node);
|
|
67244
|
+
if (isValueForwardedThroughLiteralStructure(directValue, property.value)) return true;
|
|
67245
|
+
return isSameShorthandPropertyValue(directValue, property);
|
|
67246
|
+
};
|
|
67247
|
+
const isInsideReturnedNextjsProps = (node, pageDataFunction, context) => {
|
|
67248
|
+
let cursor = node.parent;
|
|
67249
|
+
while (cursor && cursor !== pageDataFunction) {
|
|
67250
|
+
if (isNodeOfType(cursor, "Property") && getStaticPropertyKeyName(cursor, { allowComputedString: true }) === "props" && isValueForwardedToPropertyValue(node, cursor)) {
|
|
67251
|
+
const propertyContainer = cursor.parent;
|
|
67252
|
+
if (!propertyContainer) return false;
|
|
67253
|
+
const returnExpression = findConditionalReturnExpressionRoot(propertyContainer);
|
|
67254
|
+
const returnStatement = returnExpression.parent;
|
|
67255
|
+
if (isNodeOfType(returnStatement, "ReturnStatement") && findEnclosingFunction$1(returnStatement) === pageDataFunction) return true;
|
|
67256
|
+
if (isNodeOfType(pageDataFunction, "ArrowFunctionExpression") && !isNodeOfType(pageDataFunction.body, "BlockStatement") && stripParenExpression(pageDataFunction.body) === stripParenExpression(returnExpression)) return true;
|
|
67257
|
+
if (isReturnedPageDataResultBinding(returnExpression, pageDataFunction, context)) return true;
|
|
67258
|
+
}
|
|
67259
|
+
cursor = cursor.parent ?? null;
|
|
67260
|
+
}
|
|
67261
|
+
return false;
|
|
67262
|
+
};
|
|
67263
|
+
const isExpressionReturnedByFunction = (node, functionNode) => {
|
|
67264
|
+
const returnExpression = findConditionalReturnExpressionRoot(node);
|
|
67265
|
+
if (isNodeOfType(functionNode, "ArrowFunctionExpression") && !isNodeOfType(functionNode.body, "BlockStatement")) return stripParenExpression(functionNode.body) === stripParenExpression(returnExpression);
|
|
67266
|
+
const returnStatement = returnExpression.parent;
|
|
67267
|
+
return isNodeOfType(returnStatement, "ReturnStatement") && returnStatement.argument === returnExpression && findEnclosingFunction$1(returnStatement) === functionNode;
|
|
67268
|
+
};
|
|
67269
|
+
const isValueForwardedToBindingInitializer = (node, bindingInitializer) => {
|
|
67270
|
+
if (isValueForwardedThroughLiteralStructure(findConditionalReturnExpressionRoot(node), bindingInitializer)) return true;
|
|
67271
|
+
const initializer = stripParenExpression(bindingInitializer);
|
|
67272
|
+
if (!isNodeOfType(initializer, "CallExpression")) return false;
|
|
67273
|
+
const callee = stripParenExpression(initializer.callee);
|
|
67274
|
+
return isFunctionLike$1(callee) && isExpressionReturnedByFunction(node, callee);
|
|
67275
|
+
};
|
|
67276
|
+
const findPageDataResultBinding = (node) => {
|
|
67277
|
+
let cursor = node.parent;
|
|
67278
|
+
while (cursor) {
|
|
67279
|
+
if (isNodeOfType(cursor, "VariableDeclarator")) {
|
|
67280
|
+
if (cursor.init && isNodeOfType(cursor.id, "Identifier") && isValueForwardedToBindingInitializer(node, cursor.init)) return cursor.id;
|
|
67281
|
+
return null;
|
|
67282
|
+
}
|
|
67283
|
+
cursor = cursor.parent ?? null;
|
|
67284
|
+
}
|
|
67285
|
+
return null;
|
|
67286
|
+
};
|
|
67287
|
+
const isUsedToSerializeNextjsPageProps = (node, context) => {
|
|
67288
|
+
if (!isInProjectDirectory(context, "pages") || isInProjectDirectory(context, "pages/api")) return false;
|
|
67289
|
+
const pageDataFunction = findEnclosingNextjsPageDataFunction(node);
|
|
67290
|
+
if (!pageDataFunction) return false;
|
|
67291
|
+
if (isInsideReturnedNextjsProps(node, pageDataFunction, context)) return true;
|
|
67292
|
+
const bindingIdentifier = findPageDataResultBinding(node);
|
|
67293
|
+
const bindingSymbol = bindingIdentifier ? context.scopes.symbolFor(bindingIdentifier) : null;
|
|
67294
|
+
if (!bindingSymbol) return false;
|
|
67295
|
+
const aliasSymbols = collectConstAliasSymbols(bindingSymbol, context.scopes);
|
|
67296
|
+
const aliasSymbolIds = new Set(aliasSymbols.map((aliasSymbol) => aliasSymbol.id));
|
|
67297
|
+
let hasPagePropsReference = false;
|
|
67298
|
+
for (const aliasSymbol of aliasSymbols) for (const reference of aliasSymbol.references) {
|
|
67299
|
+
if (findEnclosingFunction$1(reference.identifier) !== pageDataFunction) return false;
|
|
67300
|
+
if (isInsideReturnedNextjsProps(reference.identifier, pageDataFunction, context)) {
|
|
67301
|
+
hasPagePropsReference = true;
|
|
67302
|
+
continue;
|
|
67303
|
+
}
|
|
67304
|
+
const referenceRoot = findTransparentExpressionRoot(reference.identifier);
|
|
67305
|
+
const declarator = referenceRoot.parent;
|
|
67306
|
+
if (isNodeOfType(declarator, "VariableDeclarator") && declarator.init === referenceRoot && isNodeOfType(declarator.id, "Identifier")) {
|
|
67307
|
+
const aliasSymbolForReference = context.scopes.symbolFor(declarator.id);
|
|
67308
|
+
if (aliasSymbolForReference && aliasSymbolIds.has(aliasSymbolForReference.id)) continue;
|
|
67309
|
+
}
|
|
67310
|
+
return false;
|
|
67311
|
+
}
|
|
67312
|
+
return hasPagePropsReference;
|
|
67313
|
+
};
|
|
67194
67314
|
const noJsonParseStringifyClone = defineRule({
|
|
67195
67315
|
id: "no-json-parse-stringify-clone",
|
|
67196
67316
|
title: "JSON parse/stringify deep clone",
|
|
@@ -67208,6 +67328,7 @@ const noJsonParseStringifyClone = defineRule({
|
|
|
67208
67328
|
if (isInsideSnapshotHelper(node)) return;
|
|
67209
67329
|
if (isAssignedToNormalizationBinding(node)) return;
|
|
67210
67330
|
if (isCatchParameterRoundTrip(firstArgument)) return;
|
|
67331
|
+
if (isUsedToSerializeNextjsPageProps(node, context)) return;
|
|
67211
67332
|
context.report({
|
|
67212
67333
|
node,
|
|
67213
67334
|
message: MESSAGE$35
|