oxlint-plugin-react-doctor 0.7.4-dev.118f806 → 0.7.4-dev.4a5d9bb
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 +524 -209
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9191,6 +9191,24 @@ const fileContainsReleaseForUsage = (usage, context) => {
|
|
|
9191
9191
|
});
|
|
9192
9192
|
return didFindRelease;
|
|
9193
9193
|
};
|
|
9194
|
+
const isUseSyncExternalStoreSubscribeFunction = (functionNode, context) => {
|
|
9195
|
+
const bindingIdentifier = getFunctionBindingIdentifier(functionNode);
|
|
9196
|
+
if (!bindingIdentifier) return false;
|
|
9197
|
+
const visitedSymbolIds = /* @__PURE__ */ new Set();
|
|
9198
|
+
const isSubscribeBinding = (candidateBinding) => {
|
|
9199
|
+
const symbol = context.scopes.symbolFor(candidateBinding);
|
|
9200
|
+
if (!symbol || visitedSymbolIds.has(symbol.id) || symbol.references.length === 0) return false;
|
|
9201
|
+
visitedSymbolIds.add(symbol.id);
|
|
9202
|
+
return symbol.references.every((reference) => {
|
|
9203
|
+
const referenceRoot = findTransparentExpressionRoot(reference.identifier);
|
|
9204
|
+
const referenceParent = referenceRoot.parent;
|
|
9205
|
+
if (isNodeOfType(referenceParent, "CallExpression") && referenceParent.arguments?.[0] === referenceRoot) return isReactApiCall(referenceParent, "useSyncExternalStore", context.scopes);
|
|
9206
|
+
const aliasDeclaration = referenceParent?.parent;
|
|
9207
|
+
return Boolean(isNodeOfType(referenceParent, "VariableDeclarator") && referenceParent.init === referenceRoot && isNodeOfType(referenceParent.id, "Identifier") && isNodeOfType(aliasDeclaration, "VariableDeclaration") && aliasDeclaration.kind === "const" && isSubscribeBinding(referenceParent.id));
|
|
9208
|
+
});
|
|
9209
|
+
};
|
|
9210
|
+
return isSubscribeBinding(bindingIdentifier);
|
|
9211
|
+
};
|
|
9194
9212
|
const doesResourceResultEscape = (resourceNode, allowConciseReturnEscape) => {
|
|
9195
9213
|
let currentNode = resourceNode;
|
|
9196
9214
|
let parentNode = currentNode.parent;
|
|
@@ -9212,6 +9230,8 @@ const findRetainedFunctionLeak = (retainedFunction, context) => {
|
|
|
9212
9230
|
if (!body) return null;
|
|
9213
9231
|
let leak = null;
|
|
9214
9232
|
const allowConciseReturnEscape = !isInlineRetainedHandlerFunction(retainedFunction, context);
|
|
9233
|
+
const isExternalStoreSubscribeFunction = isUseSyncExternalStoreSubscribeFunction(retainedFunction, context);
|
|
9234
|
+
const hasReleaseForUsage = (usage) => isExternalStoreSubscribeFunction ? effectHasCleanupForUsage(retainedFunction, usage, context) : fileContainsReleaseForUsage(usage, context);
|
|
9215
9235
|
walkAst(body, (child) => {
|
|
9216
9236
|
if (leak !== null) return false;
|
|
9217
9237
|
if (isFunctionLike$1(child)) return false;
|
|
@@ -9226,7 +9246,7 @@ const findRetainedFunctionLeak = (retainedFunction, context) => {
|
|
|
9226
9246
|
eventKey: null,
|
|
9227
9247
|
handlerKey: null
|
|
9228
9248
|
};
|
|
9229
|
-
if (!
|
|
9249
|
+
if (!hasReleaseForUsage(socketUsage)) {
|
|
9230
9250
|
leak = socketUsage;
|
|
9231
9251
|
return false;
|
|
9232
9252
|
}
|
|
@@ -9243,7 +9263,7 @@ const findRetainedFunctionLeak = (retainedFunction, context) => {
|
|
|
9243
9263
|
eventKey: null,
|
|
9244
9264
|
handlerKey: null
|
|
9245
9265
|
};
|
|
9246
|
-
if (!
|
|
9266
|
+
if (!hasReleaseForUsage(timerUsage)) {
|
|
9247
9267
|
leak = timerUsage;
|
|
9248
9268
|
return false;
|
|
9249
9269
|
}
|
|
@@ -9257,7 +9277,7 @@ const findRetainedFunctionLeak = (retainedFunction, context) => {
|
|
|
9257
9277
|
handleKey: findAssignedResourceKey(child, context),
|
|
9258
9278
|
...registrationDetails
|
|
9259
9279
|
};
|
|
9260
|
-
if (!hasSelfReleasingListenerOptions(child, context) && !
|
|
9280
|
+
if (!hasSelfReleasingListenerOptions(child, context) && !hasReleaseForUsage(subscriptionUsage)) leak = subscriptionUsage;
|
|
9261
9281
|
return false;
|
|
9262
9282
|
}
|
|
9263
9283
|
});
|
|
@@ -20988,6 +21008,7 @@ const findExportedFunctionBody = (programRoot, exportedName) => {
|
|
|
20988
21008
|
continue;
|
|
20989
21009
|
}
|
|
20990
21010
|
if (isNodeOfType(statement, "ExportNamedDeclaration")) {
|
|
21011
|
+
if (statement.exportKind === "type") continue;
|
|
20991
21012
|
const declaration = statement.declaration;
|
|
20992
21013
|
if (declaration && isNodeOfType(declaration, "VariableDeclaration")) {
|
|
20993
21014
|
recordVariableDeclaration(declaration);
|
|
@@ -21002,6 +21023,7 @@ const findExportedFunctionBody = (programRoot, exportedName) => {
|
|
|
21002
21023
|
}
|
|
21003
21024
|
for (const specifier of statement.specifiers ?? []) {
|
|
21004
21025
|
if (!isNodeOfType(specifier, "ExportSpecifier")) continue;
|
|
21026
|
+
if (specifier.exportKind === "type") continue;
|
|
21005
21027
|
const local = specifier.local;
|
|
21006
21028
|
const exported = specifier.exported;
|
|
21007
21029
|
if (!isNodeOfType(local, "Identifier")) continue;
|
|
@@ -21050,25 +21072,37 @@ const resolveImportedExportName = (importSpecifier) => {
|
|
|
21050
21072
|
if (isNodeOfType(importSpecifier, "ImportDefaultSpecifier")) return "default";
|
|
21051
21073
|
return null;
|
|
21052
21074
|
};
|
|
21053
|
-
const
|
|
21075
|
+
const findReExportTargetsForName = (programRoot, exportedName) => {
|
|
21054
21076
|
if (!isNodeOfType(programRoot, "Program")) return [];
|
|
21055
|
-
const
|
|
21077
|
+
const exportAllTargets = [];
|
|
21056
21078
|
for (const statement of programRoot.body ?? []) {
|
|
21057
21079
|
if (isNodeOfType(statement, "ExportNamedDeclaration") && statement.source) {
|
|
21080
|
+
if (statement.exportKind === "type") continue;
|
|
21058
21081
|
const sourceValue = statement.source.value;
|
|
21059
21082
|
if (typeof sourceValue !== "string") continue;
|
|
21060
21083
|
for (const specifier of statement.specifiers ?? []) {
|
|
21061
21084
|
if (!isNodeOfType(specifier, "ExportSpecifier")) continue;
|
|
21085
|
+
if (specifier.exportKind === "type") continue;
|
|
21062
21086
|
const exported = specifier.exported;
|
|
21063
|
-
if ((isNodeOfType(exported, "Identifier") ? exported.name : isNodeOfType(exported, "Literal") && typeof exported.value === "string" ? exported.value : null)
|
|
21087
|
+
if ((isNodeOfType(exported, "Identifier") ? exported.name : isNodeOfType(exported, "Literal") && typeof exported.value === "string" ? exported.value : null) !== exportedName) continue;
|
|
21088
|
+
const local = specifier.local;
|
|
21089
|
+
const importedName = isNodeOfType(local, "Identifier") ? local.name : isNodeOfType(local, "Literal") && typeof local.value === "string" ? local.value : null;
|
|
21090
|
+
if (importedName) return [{
|
|
21091
|
+
importedName,
|
|
21092
|
+
source: sourceValue
|
|
21093
|
+
}];
|
|
21064
21094
|
}
|
|
21065
21095
|
}
|
|
21066
21096
|
if (isNodeOfType(statement, "ExportAllDeclaration") && statement.source) {
|
|
21097
|
+
if (statement.exportKind === "type" || statement.exported) continue;
|
|
21067
21098
|
const sourceValue = statement.source.value;
|
|
21068
|
-
if (typeof sourceValue === "string")
|
|
21099
|
+
if (typeof sourceValue === "string") exportAllTargets.push({
|
|
21100
|
+
importedName: exportedName,
|
|
21101
|
+
source: sourceValue
|
|
21102
|
+
});
|
|
21069
21103
|
}
|
|
21070
21104
|
}
|
|
21071
|
-
return
|
|
21105
|
+
return exportAllTargets;
|
|
21072
21106
|
};
|
|
21073
21107
|
//#endregion
|
|
21074
21108
|
//#region src/plugin/utils/attach-parent-references.ts
|
|
@@ -21157,139 +21191,6 @@ const parseSourceFile = (absoluteFilePath) => {
|
|
|
21157
21191
|
return parsedProgram;
|
|
21158
21192
|
};
|
|
21159
21193
|
//#endregion
|
|
21160
|
-
//#region src/plugin/utils/is-barrel-index-module.ts
|
|
21161
|
-
const INDEX_MODULE_FILE_PATTERN = /^index\.(?:[cm]?[jt]sx?|mjs)$/;
|
|
21162
|
-
const BINDING_IMPORT_DECLARATION_PATTERN = /^\s*import\s+(type\s+)?(?!["'])([^;]*?)\s+from\s+["']([^"']+)["']\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
21163
|
-
const BARREL_REEXPORT_DECLARATION_PATTERN = /^\s*export\s+(type\s+)?(?:\*(?:\s+as\s+([\w$]+))?|\{([\s\S]*?)\})\s+from\s+["']([^"']+)["']\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
21164
|
-
const LOCAL_EXPORT_SPECIFIER_DECLARATION_PATTERN = /^\s*export\s+(type\s+)?\{([\s\S]*?)\}\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
21165
|
-
const barrelIndexModuleInfoCache = /* @__PURE__ */ new Map();
|
|
21166
|
-
const isIndexModuleFilePath = (filePath) => INDEX_MODULE_FILE_PATTERN.test(path.basename(filePath));
|
|
21167
|
-
const createNonBarrelInfo = () => ({
|
|
21168
|
-
isBarrel: false,
|
|
21169
|
-
exportsByName: /* @__PURE__ */ new Map(),
|
|
21170
|
-
starExportSources: []
|
|
21171
|
-
});
|
|
21172
|
-
const addImportedBinding = (importedBindings, binding) => {
|
|
21173
|
-
importedBindings.set(binding.localName, {
|
|
21174
|
-
...binding,
|
|
21175
|
-
didExport: false
|
|
21176
|
-
});
|
|
21177
|
-
};
|
|
21178
|
-
const collectNamedImportBindings = (namedSpecifiersText, source, declarationIsTypeOnly, importedBindings) => {
|
|
21179
|
-
for (const specifier of parseExportSpecifiers(namedSpecifiersText, declarationIsTypeOnly)) addImportedBinding(importedBindings, {
|
|
21180
|
-
localName: specifier.exportedName,
|
|
21181
|
-
importedName: specifier.localName,
|
|
21182
|
-
source,
|
|
21183
|
-
isTypeOnly: specifier.isTypeOnly
|
|
21184
|
-
});
|
|
21185
|
-
};
|
|
21186
|
-
const collectImportBindings = (importClause, source, declarationIsTypeOnly, importedBindings) => {
|
|
21187
|
-
const trimmedImportClause = importClause.trim();
|
|
21188
|
-
const namespaceMatch = trimmedImportClause.match(/(?:^|,\s*)\*\s+as\s+([\w$]+)/);
|
|
21189
|
-
if (namespaceMatch?.[1]) addImportedBinding(importedBindings, {
|
|
21190
|
-
localName: namespaceMatch[1],
|
|
21191
|
-
importedName: "*",
|
|
21192
|
-
source,
|
|
21193
|
-
isTypeOnly: declarationIsTypeOnly
|
|
21194
|
-
});
|
|
21195
|
-
const namedImportMatch = trimmedImportClause.match(/\{([\s\S]*?)\}/);
|
|
21196
|
-
if (namedImportMatch?.[1]) collectNamedImportBindings(namedImportMatch[1], source, declarationIsTypeOnly, importedBindings);
|
|
21197
|
-
const defaultImportName = trimmedImportClause.split(",")[0]?.trim();
|
|
21198
|
-
if (defaultImportName && !defaultImportName.startsWith("{") && !defaultImportName.startsWith("*")) addImportedBinding(importedBindings, {
|
|
21199
|
-
localName: defaultImportName,
|
|
21200
|
-
importedName: "default",
|
|
21201
|
-
source,
|
|
21202
|
-
isTypeOnly: declarationIsTypeOnly
|
|
21203
|
-
});
|
|
21204
|
-
};
|
|
21205
|
-
const replaceKnownDeclarations = (sourceText, importedBindings, exportsByName, starExportSources) => {
|
|
21206
|
-
let withoutKnownDeclarations = sourceText.replace(BINDING_IMPORT_DECLARATION_PATTERN, (_match, typeKeyword, importClause, source) => {
|
|
21207
|
-
collectImportBindings(importClause, source, Boolean(typeKeyword), importedBindings);
|
|
21208
|
-
return "";
|
|
21209
|
-
});
|
|
21210
|
-
withoutKnownDeclarations = withoutKnownDeclarations.replace(BARREL_REEXPORT_DECLARATION_PATTERN, (_match, typeKeyword, namespaceExportName, specifiersText, source) => {
|
|
21211
|
-
const isTypeOnly = Boolean(typeKeyword);
|
|
21212
|
-
if (namespaceExportName) {
|
|
21213
|
-
exportsByName.set(namespaceExportName, {
|
|
21214
|
-
exportedName: namespaceExportName,
|
|
21215
|
-
importedName: "*",
|
|
21216
|
-
source,
|
|
21217
|
-
isTypeOnly
|
|
21218
|
-
});
|
|
21219
|
-
return "";
|
|
21220
|
-
}
|
|
21221
|
-
if (specifiersText) {
|
|
21222
|
-
for (const specifier of parseExportSpecifiers(specifiersText, isTypeOnly)) exportsByName.set(specifier.exportedName, {
|
|
21223
|
-
exportedName: specifier.exportedName,
|
|
21224
|
-
importedName: specifier.localName,
|
|
21225
|
-
source,
|
|
21226
|
-
isTypeOnly: specifier.isTypeOnly
|
|
21227
|
-
});
|
|
21228
|
-
return "";
|
|
21229
|
-
}
|
|
21230
|
-
starExportSources.push(source);
|
|
21231
|
-
return "";
|
|
21232
|
-
});
|
|
21233
|
-
withoutKnownDeclarations = withoutKnownDeclarations.replace(LOCAL_EXPORT_SPECIFIER_DECLARATION_PATTERN, (_match, typeKeyword, specifiersText) => {
|
|
21234
|
-
for (const specifier of parseExportSpecifiers(specifiersText, Boolean(typeKeyword))) {
|
|
21235
|
-
const importedBinding = importedBindings.get(specifier.localName);
|
|
21236
|
-
if (!importedBinding) return _match;
|
|
21237
|
-
importedBinding.didExport = true;
|
|
21238
|
-
exportsByName.set(specifier.exportedName, {
|
|
21239
|
-
exportedName: specifier.exportedName,
|
|
21240
|
-
importedName: importedBinding.importedName,
|
|
21241
|
-
source: importedBinding.source,
|
|
21242
|
-
isTypeOnly: specifier.isTypeOnly || importedBinding.isTypeOnly
|
|
21243
|
-
});
|
|
21244
|
-
}
|
|
21245
|
-
return "";
|
|
21246
|
-
});
|
|
21247
|
-
return withoutKnownDeclarations;
|
|
21248
|
-
};
|
|
21249
|
-
const hasUnexportedRuntimeImport = (importedBindings) => {
|
|
21250
|
-
for (const binding of importedBindings.values()) if (!binding.isTypeOnly && !binding.didExport) return true;
|
|
21251
|
-
return false;
|
|
21252
|
-
};
|
|
21253
|
-
const classifyBarrelModule = (sourceText) => {
|
|
21254
|
-
const strippedSource = stripJsComments(sourceText).trim();
|
|
21255
|
-
if (!strippedSource) return createNonBarrelInfo();
|
|
21256
|
-
const importedBindings = /* @__PURE__ */ new Map();
|
|
21257
|
-
const exportsByName = /* @__PURE__ */ new Map();
|
|
21258
|
-
const starExportSources = [];
|
|
21259
|
-
if (replaceKnownDeclarations(strippedSource, importedBindings, exportsByName, starExportSources).trim() || hasUnexportedRuntimeImport(importedBindings)) return createNonBarrelInfo();
|
|
21260
|
-
return {
|
|
21261
|
-
isBarrel: exportsByName.size > 0 || starExportSources.length > 0,
|
|
21262
|
-
exportsByName,
|
|
21263
|
-
starExportSources
|
|
21264
|
-
};
|
|
21265
|
-
};
|
|
21266
|
-
const getBarrelIndexModuleInfo = (filePath) => {
|
|
21267
|
-
if (!isIndexModuleFilePath(filePath)) return createNonBarrelInfo();
|
|
21268
|
-
recordContentProbe(filePath);
|
|
21269
|
-
let fileStat;
|
|
21270
|
-
try {
|
|
21271
|
-
fileStat = fs.statSync(filePath);
|
|
21272
|
-
} catch {
|
|
21273
|
-
fileStat = null;
|
|
21274
|
-
}
|
|
21275
|
-
const cachedResult = barrelIndexModuleInfoCache.get(filePath);
|
|
21276
|
-
if (cachedResult !== void 0 && fileStat !== null && cachedResult.mtimeMs === fileStat.mtimeMs && cachedResult.size === fileStat.size) return cachedResult.moduleInfo;
|
|
21277
|
-
if (fileStat === null) return createNonBarrelInfo();
|
|
21278
|
-
let moduleInfo = createNonBarrelInfo();
|
|
21279
|
-
try {
|
|
21280
|
-
moduleInfo = classifyBarrelModule(fs.readFileSync(filePath, "utf8"));
|
|
21281
|
-
} catch {
|
|
21282
|
-
moduleInfo = createNonBarrelInfo();
|
|
21283
|
-
}
|
|
21284
|
-
barrelIndexModuleInfoCache.set(filePath, {
|
|
21285
|
-
mtimeMs: fileStat.mtimeMs,
|
|
21286
|
-
size: fileStat.size,
|
|
21287
|
-
moduleInfo
|
|
21288
|
-
});
|
|
21289
|
-
return moduleInfo;
|
|
21290
|
-
};
|
|
21291
|
-
const isBarrelIndexModule = (filePath) => getBarrelIndexModuleInfo(filePath).isBarrel;
|
|
21292
|
-
//#endregion
|
|
21293
21194
|
//#region src/plugin/utils/resolve-relative-import-path.ts
|
|
21294
21195
|
const MODULE_FILE_EXTENSIONS = [
|
|
21295
21196
|
".ts",
|
|
@@ -21406,35 +21307,6 @@ const resolveModuleFileFromAbsolutePath = (importPath) => {
|
|
|
21406
21307
|
};
|
|
21407
21308
|
const resolveRelativeImportPath = (filename, source) => resolveModuleFileFromAbsolutePath(path.resolve(path.dirname(filename), source));
|
|
21408
21309
|
//#endregion
|
|
21409
|
-
//#region src/plugin/utils/resolve-barrel-export-file-path.ts
|
|
21410
|
-
const getUniqueFilePath = (filePaths) => {
|
|
21411
|
-
const uniqueFilePaths = new Set(filePaths);
|
|
21412
|
-
if (uniqueFilePaths.size !== 1) return null;
|
|
21413
|
-
const [filePath] = uniqueFilePaths;
|
|
21414
|
-
return filePath ?? null;
|
|
21415
|
-
};
|
|
21416
|
-
const resolveStarExportFilePath = (barrelFilePath, exportedName, source, visitedFilePaths) => {
|
|
21417
|
-
const resolvedTargetPath = resolveRelativeImportPath(barrelFilePath, source);
|
|
21418
|
-
if (!resolvedTargetPath) return null;
|
|
21419
|
-
const nestedTargetPath = resolveBarrelExportFilePath(resolvedTargetPath, exportedName, new Set(visitedFilePaths));
|
|
21420
|
-
if (nestedTargetPath) return nestedTargetPath;
|
|
21421
|
-
return doesModuleExportName(resolvedTargetPath, exportedName) ? resolvedTargetPath : null;
|
|
21422
|
-
};
|
|
21423
|
-
const resolveBarrelExportFilePath = (barrelFilePath, exportedName, visitedFilePaths = /* @__PURE__ */ new Set()) => {
|
|
21424
|
-
if (visitedFilePaths.has(barrelFilePath)) return null;
|
|
21425
|
-
visitedFilePaths.add(barrelFilePath);
|
|
21426
|
-
const moduleInfo = getBarrelIndexModuleInfo(barrelFilePath);
|
|
21427
|
-
if (!moduleInfo.isBarrel) return null;
|
|
21428
|
-
const target = moduleInfo.exportsByName.get(exportedName);
|
|
21429
|
-
if (target) {
|
|
21430
|
-
const resolvedTargetPath = resolveRelativeImportPath(barrelFilePath, target.source);
|
|
21431
|
-
if (!resolvedTargetPath) return null;
|
|
21432
|
-
return resolveBarrelExportFilePath(resolvedTargetPath, target.importedName, visitedFilePaths) ?? resolvedTargetPath;
|
|
21433
|
-
}
|
|
21434
|
-
if (exportedName === "default") return null;
|
|
21435
|
-
return getUniqueFilePath(moduleInfo.starExportSources.map((source) => resolveStarExportFilePath(barrelFilePath, exportedName, source, visitedFilePaths)).filter((filePath) => Boolean(filePath)));
|
|
21436
|
-
};
|
|
21437
|
-
//#endregion
|
|
21438
21310
|
//#region src/plugin/utils/resolve-tsconfig-alias.ts
|
|
21439
21311
|
const TSCONFIG_FILE_NAMES = ["tsconfig.json", "jsconfig.json"];
|
|
21440
21312
|
const isObjectRecord = (value) => typeof value === "object" && value !== null;
|
|
@@ -21613,25 +21485,29 @@ const resolveTsconfigAliasPath = (fromFilename, source) => {
|
|
|
21613
21485
|
};
|
|
21614
21486
|
//#endregion
|
|
21615
21487
|
//#region src/plugin/utils/resolve-module-path.ts
|
|
21616
|
-
const resolveModulePath = (fromFilename, source) =>
|
|
21488
|
+
const resolveModulePath = (fromFilename, source) => {
|
|
21489
|
+
if (path.isAbsolute(source)) return null;
|
|
21490
|
+
return source.startsWith(".") ? resolveRelativeImportPath(fromFilename, source) : resolveTsconfigAliasPath(fromFilename, source);
|
|
21491
|
+
};
|
|
21617
21492
|
//#endregion
|
|
21618
21493
|
//#region src/plugin/utils/resolve-cross-file-function-export.ts
|
|
21619
21494
|
const resolveFunctionExportInFile = (filePath, exportedName, visitedFilePaths) => {
|
|
21620
21495
|
if (visitedFilePaths.size >= 4) return null;
|
|
21621
21496
|
if (visitedFilePaths.has(filePath)) return null;
|
|
21622
21497
|
visitedFilePaths.add(filePath);
|
|
21623
|
-
const
|
|
21624
|
-
const programRoot = parseSourceFile(actualFilePath);
|
|
21498
|
+
const programRoot = parseSourceFile(filePath);
|
|
21625
21499
|
if (!programRoot) return null;
|
|
21626
21500
|
const exported = findExportedFunctionBody(programRoot, exportedName);
|
|
21627
21501
|
if (exported) return exported;
|
|
21628
|
-
|
|
21629
|
-
|
|
21502
|
+
const resolvedCandidates = /* @__PURE__ */ new Set();
|
|
21503
|
+
for (const target of findReExportTargetsForName(programRoot, exportedName)) {
|
|
21504
|
+
const nextFilePath = resolveModulePath(filePath, target.source);
|
|
21630
21505
|
if (!nextFilePath) continue;
|
|
21631
|
-
const resolved = resolveFunctionExportInFile(nextFilePath,
|
|
21632
|
-
if (resolved)
|
|
21506
|
+
const resolved = resolveFunctionExportInFile(nextFilePath, target.importedName, new Set(visitedFilePaths));
|
|
21507
|
+
if (resolved) resolvedCandidates.add(resolved);
|
|
21633
21508
|
}
|
|
21634
|
-
return null;
|
|
21509
|
+
if (resolvedCandidates.size !== 1) return null;
|
|
21510
|
+
return resolvedCandidates.values().next().value ?? null;
|
|
21635
21511
|
};
|
|
21636
21512
|
const resolveCrossFileFunctionExport = (fromFilename, source, exportedName) => {
|
|
21637
21513
|
const resolvedFilePath = resolveModulePath(fromFilename, source);
|
|
@@ -22814,6 +22690,46 @@ const PURE_GLOBAL_CALLEE_NAMES = new Set([
|
|
|
22814
22690
|
"parseInt"
|
|
22815
22691
|
]);
|
|
22816
22692
|
const PURE_GLOBAL_NAMESPACE_NAMES = new Set(["JSON", "Math"]);
|
|
22693
|
+
const PURE_HELPER_NAMESPACE_MEMBER_NAMES = new Map([["JSON", new Set([
|
|
22694
|
+
"isRawJSON",
|
|
22695
|
+
"parse",
|
|
22696
|
+
"rawJSON",
|
|
22697
|
+
"stringify"
|
|
22698
|
+
])], ["Math", new Set([
|
|
22699
|
+
"abs",
|
|
22700
|
+
"acos",
|
|
22701
|
+
"acosh",
|
|
22702
|
+
"asin",
|
|
22703
|
+
"asinh",
|
|
22704
|
+
"atan",
|
|
22705
|
+
"atan2",
|
|
22706
|
+
"atanh",
|
|
22707
|
+
"cbrt",
|
|
22708
|
+
"ceil",
|
|
22709
|
+
"clz32",
|
|
22710
|
+
"cos",
|
|
22711
|
+
"cosh",
|
|
22712
|
+
"exp",
|
|
22713
|
+
"floor",
|
|
22714
|
+
"fround",
|
|
22715
|
+
"hypot",
|
|
22716
|
+
"imul",
|
|
22717
|
+
"log",
|
|
22718
|
+
"log10",
|
|
22719
|
+
"log1p",
|
|
22720
|
+
"log2",
|
|
22721
|
+
"max",
|
|
22722
|
+
"min",
|
|
22723
|
+
"pow",
|
|
22724
|
+
"round",
|
|
22725
|
+
"sign",
|
|
22726
|
+
"sin",
|
|
22727
|
+
"sinh",
|
|
22728
|
+
"sqrt",
|
|
22729
|
+
"tan",
|
|
22730
|
+
"tanh",
|
|
22731
|
+
"trunc"
|
|
22732
|
+
])]]);
|
|
22817
22733
|
const PURE_MEMBER_TRANSFORM_NAMES = new Set([
|
|
22818
22734
|
"concat",
|
|
22819
22735
|
"filter",
|
|
@@ -22860,6 +22776,42 @@ const getParameterBindingIdentity = (analysis, functionNode, parameter) => {
|
|
|
22860
22776
|
}
|
|
22861
22777
|
return parameter;
|
|
22862
22778
|
};
|
|
22779
|
+
const isAsyncOrGeneratorFunction = (functionNode) => Boolean(functionNode.async === true || functionNode.generator === true);
|
|
22780
|
+
const isModuleFunction = (functionNode) => {
|
|
22781
|
+
let ancestor = functionNode.parent;
|
|
22782
|
+
while (ancestor) {
|
|
22783
|
+
if (isFunctionLike$1(ancestor)) return false;
|
|
22784
|
+
if (isNodeOfType(ancestor, "Program")) return true;
|
|
22785
|
+
ancestor = ancestor.parent;
|
|
22786
|
+
}
|
|
22787
|
+
return false;
|
|
22788
|
+
};
|
|
22789
|
+
const getFunctionBindingNames = (functionNode) => {
|
|
22790
|
+
const names = /* @__PURE__ */ new Set();
|
|
22791
|
+
if ((isNodeOfType(functionNode, "FunctionDeclaration") || isNodeOfType(functionNode, "FunctionExpression")) && functionNode.id) names.add(functionNode.id.name);
|
|
22792
|
+
const parent = functionNode.parent;
|
|
22793
|
+
if (parent && isNodeOfType(parent, "VariableDeclarator") && isNodeOfType(parent.id, "Identifier")) names.add(parent.id.name);
|
|
22794
|
+
return names;
|
|
22795
|
+
};
|
|
22796
|
+
const collectModuleBindingNames = (functionNode) => {
|
|
22797
|
+
let program = functionNode.parent;
|
|
22798
|
+
while (program && !isNodeOfType(program, "Program")) program = program.parent;
|
|
22799
|
+
const bindingNames = /* @__PURE__ */ new Set();
|
|
22800
|
+
if (!program || !isNodeOfType(program, "Program")) return bindingNames;
|
|
22801
|
+
for (const statement of program.body ?? []) {
|
|
22802
|
+
if (isNodeOfType(statement, "ImportDeclaration")) {
|
|
22803
|
+
for (const specifier of statement.specifiers ?? []) if (isNodeOfType(specifier.local, "Identifier")) bindingNames.add(specifier.local.name);
|
|
22804
|
+
continue;
|
|
22805
|
+
}
|
|
22806
|
+
const declaration = isNodeOfType(statement, "ExportNamedDeclaration") || isNodeOfType(statement, "ExportDefaultDeclaration") ? statement.declaration : statement;
|
|
22807
|
+
if (isNodeOfType(declaration, "VariableDeclaration")) {
|
|
22808
|
+
for (const declarator of declaration.declarations ?? []) collectPatternNames(declarator.id, bindingNames);
|
|
22809
|
+
continue;
|
|
22810
|
+
}
|
|
22811
|
+
if ((isNodeOfType(declaration, "FunctionDeclaration") || isNodeOfType(declaration, "ClassDeclaration")) && isNodeOfType(declaration.id, "Identifier")) bindingNames.add(declaration.id.name);
|
|
22812
|
+
}
|
|
22813
|
+
return bindingNames;
|
|
22814
|
+
};
|
|
22863
22815
|
const buildSubstitutions = (analysis, functionNode, argumentExpressions, parentFrame) => {
|
|
22864
22816
|
const substitutions = /* @__PURE__ */ new Map();
|
|
22865
22817
|
const parameters = getFunctionParameters(functionNode);
|
|
@@ -22990,7 +22942,7 @@ const collectIntroducedBindings = (analysis, functionNode) => {
|
|
|
22990
22942
|
for (const parameter of getFunctionParameters(functionNode)) if (isNodeOfType(parameter, "Identifier")) introducedBindings.add(getParameterBindingIdentity(analysis, functionNode, parameter));
|
|
22991
22943
|
return introducedBindings;
|
|
22992
22944
|
};
|
|
22993
|
-
const collectBoundedEffectExecutionFrames = (analysis, effectNode) => {
|
|
22945
|
+
const collectBoundedEffectExecutionFrames = (analysis, effectNode, currentFilename) => {
|
|
22994
22946
|
const effectFunction = getEffectFn(analysis, effectNode);
|
|
22995
22947
|
if (!effectFunction || !isFunctionLike$1(effectFunction) || effectFunction.async === true) return [];
|
|
22996
22948
|
const invokedFunctionEvidence = collectEffectInvokedFunctions(effectFunction);
|
|
@@ -22999,7 +22951,8 @@ const collectBoundedEffectExecutionFrames = (analysis, effectNode) => {
|
|
|
22999
22951
|
invocation: null,
|
|
23000
22952
|
isDeferred: false,
|
|
23001
22953
|
introducedBindings: /* @__PURE__ */ new Set(),
|
|
23002
|
-
substitutions: /* @__PURE__ */ new Map()
|
|
22954
|
+
substitutions: /* @__PURE__ */ new Map(),
|
|
22955
|
+
currentFilename
|
|
23003
22956
|
};
|
|
23004
22957
|
const frames = [rootFrame];
|
|
23005
22958
|
walkAst(effectFunction, (child) => {
|
|
@@ -23020,7 +22973,8 @@ const collectBoundedEffectExecutionFrames = (analysis, effectNode) => {
|
|
|
23020
22973
|
invocation: child,
|
|
23021
22974
|
isDeferred,
|
|
23022
22975
|
introducedBindings,
|
|
23023
|
-
substitutions: buildSubstitutions(analysis, callable, argumentsForCallable, rootFrame)
|
|
22976
|
+
substitutions: buildSubstitutions(analysis, callable, argumentsForCallable, rootFrame),
|
|
22977
|
+
currentFilename
|
|
23024
22978
|
});
|
|
23025
22979
|
};
|
|
23026
22980
|
if (isFunctionLike$1(callee)) {
|
|
@@ -23073,6 +23027,174 @@ const isOpaqueHookCall = (callExpression) => {
|
|
|
23073
23027
|
const calleeName = getCallCalleeName$1(callExpression);
|
|
23074
23028
|
return Boolean(calleeName && /^use[A-Z0-9]/.test(calleeName) && calleeName !== "useMemo" && calleeName !== "useCallback" && calleeName !== "useEffectEvent");
|
|
23075
23029
|
};
|
|
23030
|
+
const analyzeHelperStatements = (statements, environment, usedParameterIndices, analyzeExpression) => {
|
|
23031
|
+
let canContinue = true;
|
|
23032
|
+
for (const statement of statements) {
|
|
23033
|
+
if (!canContinue) {
|
|
23034
|
+
if (!isNodeOfType(statement, "EmptyStatement")) return {
|
|
23035
|
+
canContinue: false,
|
|
23036
|
+
isValid: false
|
|
23037
|
+
};
|
|
23038
|
+
continue;
|
|
23039
|
+
}
|
|
23040
|
+
if (isNodeOfType(statement, "EmptyStatement")) continue;
|
|
23041
|
+
if (isNodeOfType(statement, "ReturnStatement")) {
|
|
23042
|
+
if (!statement.argument || !analyzeExpression(statement.argument, environment, usedParameterIndices)) return {
|
|
23043
|
+
canContinue: false,
|
|
23044
|
+
isValid: false
|
|
23045
|
+
};
|
|
23046
|
+
canContinue = false;
|
|
23047
|
+
continue;
|
|
23048
|
+
}
|
|
23049
|
+
if (isNodeOfType(statement, "BlockStatement")) {
|
|
23050
|
+
const blockSummary = analyzeHelperStatements(statement.body ?? [], environment, usedParameterIndices, analyzeExpression);
|
|
23051
|
+
if (!blockSummary.isValid) return blockSummary;
|
|
23052
|
+
canContinue = blockSummary.canContinue;
|
|
23053
|
+
continue;
|
|
23054
|
+
}
|
|
23055
|
+
if (isNodeOfType(statement, "IfStatement")) {
|
|
23056
|
+
if (!analyzeExpression(statement.test, environment, usedParameterIndices)) return {
|
|
23057
|
+
canContinue: false,
|
|
23058
|
+
isValid: false
|
|
23059
|
+
};
|
|
23060
|
+
const consequentSummary = analyzeHelperStatements([statement.consequent], environment, usedParameterIndices, analyzeExpression);
|
|
23061
|
+
if (!consequentSummary.isValid) return consequentSummary;
|
|
23062
|
+
const alternateSummary = statement.alternate ? analyzeHelperStatements([statement.alternate], environment, usedParameterIndices, analyzeExpression) : {
|
|
23063
|
+
canContinue: true,
|
|
23064
|
+
isValid: true
|
|
23065
|
+
};
|
|
23066
|
+
if (!alternateSummary.isValid) return alternateSummary;
|
|
23067
|
+
canContinue = consequentSummary.canContinue || alternateSummary.canContinue;
|
|
23068
|
+
continue;
|
|
23069
|
+
}
|
|
23070
|
+
return {
|
|
23071
|
+
canContinue: false,
|
|
23072
|
+
isValid: false
|
|
23073
|
+
};
|
|
23074
|
+
}
|
|
23075
|
+
return {
|
|
23076
|
+
canContinue,
|
|
23077
|
+
isValid: true
|
|
23078
|
+
};
|
|
23079
|
+
};
|
|
23080
|
+
const analyzeHelperExpression = (expression, environment, usedParameterIndices) => {
|
|
23081
|
+
const node = stripParenExpression(expression);
|
|
23082
|
+
if (isNodeOfType(node, "Literal") || isNodeOfType(node, "TemplateElement")) return true;
|
|
23083
|
+
if (isNodeOfType(node, "Identifier")) {
|
|
23084
|
+
const parameterIndex = environment.parameterIndices.get(node.name);
|
|
23085
|
+
if (parameterIndex !== void 0) {
|
|
23086
|
+
if (parameterIndex !== null) usedParameterIndices.add(parameterIndex);
|
|
23087
|
+
return true;
|
|
23088
|
+
}
|
|
23089
|
+
return node.name === "undefined" || node.name === "NaN" || node.name === "Infinity";
|
|
23090
|
+
}
|
|
23091
|
+
if (isNodeOfType(node, "ArrayExpression")) return (node.elements ?? []).every((element) => !element || analyzeHelperExpression(element, environment, usedParameterIndices));
|
|
23092
|
+
if (isNodeOfType(node, "ObjectExpression")) return (node.properties ?? []).every((property) => {
|
|
23093
|
+
if (isNodeOfType(property, "SpreadElement")) return analyzeHelperExpression(property.argument, environment, usedParameterIndices);
|
|
23094
|
+
if (!isNodeOfType(property, "Property") || property.kind !== "init" || property.method === true) return false;
|
|
23095
|
+
if (property.computed && !analyzeHelperExpression(property.key, environment, usedParameterIndices)) return false;
|
|
23096
|
+
return analyzeHelperExpression(property.value, environment, usedParameterIndices);
|
|
23097
|
+
});
|
|
23098
|
+
if (isNodeOfType(node, "TemplateLiteral")) return (node.expressions ?? []).every((templateExpression) => analyzeHelperExpression(templateExpression, environment, usedParameterIndices));
|
|
23099
|
+
if (isNodeOfType(node, "UnaryExpression")) return node.operator !== "delete" && analyzeHelperExpression(node.argument, environment, usedParameterIndices);
|
|
23100
|
+
if (isNodeOfType(node, "BinaryExpression") || isNodeOfType(node, "LogicalExpression")) return analyzeHelperExpression(node.left, environment, usedParameterIndices) && analyzeHelperExpression(node.right, environment, usedParameterIndices);
|
|
23101
|
+
if (isNodeOfType(node, "ConditionalExpression")) return analyzeHelperExpression(node.test, environment, usedParameterIndices) && analyzeHelperExpression(node.consequent, environment, usedParameterIndices) && analyzeHelperExpression(node.alternate, environment, usedParameterIndices);
|
|
23102
|
+
if (isNodeOfType(node, "MemberExpression")) {
|
|
23103
|
+
if (!analyzeHelperExpression(node.object, environment, usedParameterIndices)) return false;
|
|
23104
|
+
return !node.computed || analyzeHelperExpression(node.property, environment, usedParameterIndices);
|
|
23105
|
+
}
|
|
23106
|
+
if (isFunctionLike$1(node)) {
|
|
23107
|
+
if (isAsyncOrGeneratorFunction(node)) return false;
|
|
23108
|
+
const callbackParameterIndices = new Map(environment.parameterIndices);
|
|
23109
|
+
for (const parameter of getFunctionParameters(node)) {
|
|
23110
|
+
if (!isNodeOfType(parameter, "Identifier")) return false;
|
|
23111
|
+
callbackParameterIndices.set(parameter.name, null);
|
|
23112
|
+
}
|
|
23113
|
+
const callbackEnvironment = {
|
|
23114
|
+
parameterIndices: callbackParameterIndices,
|
|
23115
|
+
recursiveNames: environment.recursiveNames,
|
|
23116
|
+
shadowedGlobalNames: environment.shadowedGlobalNames
|
|
23117
|
+
};
|
|
23118
|
+
if (!isNodeOfType(node.body, "BlockStatement")) return analyzeHelperExpression(node.body, callbackEnvironment, usedParameterIndices);
|
|
23119
|
+
const callbackSummary = analyzeHelperStatements(node.body.body ?? [], callbackEnvironment, usedParameterIndices, analyzeHelperExpression);
|
|
23120
|
+
return callbackSummary.isValid && !callbackSummary.canContinue;
|
|
23121
|
+
}
|
|
23122
|
+
if (isNodeOfType(node, "CallExpression")) {
|
|
23123
|
+
const callee = stripParenExpression(node.callee);
|
|
23124
|
+
const calleeRoot = getMemberRoot(callee);
|
|
23125
|
+
const isPureGlobalCall = isNodeOfType(callee, "Identifier") && PURE_GLOBAL_CALLEE_NAMES.has(callee.name) && !environment.parameterIndices.has(callee.name) && !environment.recursiveNames.has(callee.name) && !environment.shadowedGlobalNames.has(callee.name);
|
|
23126
|
+
const namespaceName = isNodeOfType(calleeRoot, "Identifier") && !environment.parameterIndices.has(calleeRoot.name) && !environment.recursiveNames.has(calleeRoot.name) && !environment.shadowedGlobalNames.has(calleeRoot.name) ? calleeRoot.name : null;
|
|
23127
|
+
const namespaceMemberName = getStaticMemberName(callee);
|
|
23128
|
+
const isPureNamespaceCall = isNodeOfType(callee, "MemberExpression") && namespaceName !== null && namespaceMemberName !== null && PURE_HELPER_NAMESPACE_MEMBER_NAMES.get(namespaceName)?.has(namespaceMemberName) === true;
|
|
23129
|
+
const isPureMemberTransform = isNodeOfType(callee, "MemberExpression") && PURE_MEMBER_TRANSFORM_NAMES.has(getStaticMemberName(callee) ?? "");
|
|
23130
|
+
if (!isPureGlobalCall && !isPureNamespaceCall && !isPureMemberTransform) return false;
|
|
23131
|
+
if (isPureMemberTransform && isNodeOfType(callee, "MemberExpression") && !analyzeHelperExpression(callee.object, environment, usedParameterIndices)) return false;
|
|
23132
|
+
return (node.arguments ?? []).every((argument) => analyzeHelperExpression(argument, environment, usedParameterIndices));
|
|
23133
|
+
}
|
|
23134
|
+
if (isNodeOfType(node, "SpreadElement")) return analyzeHelperExpression(node.argument, environment, usedParameterIndices);
|
|
23135
|
+
return false;
|
|
23136
|
+
};
|
|
23137
|
+
const helperSummaryCache = /* @__PURE__ */ new WeakMap();
|
|
23138
|
+
const summarizeHelperReturn = (functionNode) => {
|
|
23139
|
+
if (!isFunctionLike$1(functionNode) || !isModuleFunction(functionNode)) return null;
|
|
23140
|
+
if (helperSummaryCache.has(functionNode)) return helperSummaryCache.get(functionNode) ?? null;
|
|
23141
|
+
if (isAsyncOrGeneratorFunction(functionNode)) {
|
|
23142
|
+
helperSummaryCache.set(functionNode, null);
|
|
23143
|
+
return null;
|
|
23144
|
+
}
|
|
23145
|
+
const parameterIndices = /* @__PURE__ */ new Map();
|
|
23146
|
+
const parameters = getFunctionParameters(functionNode);
|
|
23147
|
+
for (let parameterIndex = 0; parameterIndex < parameters.length; parameterIndex += 1) {
|
|
23148
|
+
const parameter = parameters[parameterIndex];
|
|
23149
|
+
if (!parameter || !isNodeOfType(parameter, "Identifier") || parameterIndices.has(parameter.name)) {
|
|
23150
|
+
helperSummaryCache.set(functionNode, null);
|
|
23151
|
+
return null;
|
|
23152
|
+
}
|
|
23153
|
+
parameterIndices.set(parameter.name, parameterIndex);
|
|
23154
|
+
}
|
|
23155
|
+
const environment = {
|
|
23156
|
+
parameterIndices,
|
|
23157
|
+
recursiveNames: getFunctionBindingNames(functionNode),
|
|
23158
|
+
shadowedGlobalNames: collectModuleBindingNames(functionNode)
|
|
23159
|
+
};
|
|
23160
|
+
const usedParameterIndices = /* @__PURE__ */ new Set();
|
|
23161
|
+
if (!isNodeOfType(functionNode.body, "BlockStatement")) {
|
|
23162
|
+
if (!analyzeHelperExpression(functionNode.body, environment, usedParameterIndices)) {
|
|
23163
|
+
helperSummaryCache.set(functionNode, null);
|
|
23164
|
+
return null;
|
|
23165
|
+
}
|
|
23166
|
+
} else {
|
|
23167
|
+
const controlFlowSummary = analyzeHelperStatements(functionNode.body.body ?? [], environment, usedParameterIndices, analyzeHelperExpression);
|
|
23168
|
+
if (!controlFlowSummary.isValid || controlFlowSummary.canContinue) {
|
|
23169
|
+
helperSummaryCache.set(functionNode, null);
|
|
23170
|
+
return null;
|
|
23171
|
+
}
|
|
23172
|
+
}
|
|
23173
|
+
const summary = { usedParameterIndices };
|
|
23174
|
+
helperSummaryCache.set(functionNode, summary);
|
|
23175
|
+
return summary;
|
|
23176
|
+
};
|
|
23177
|
+
const resolveValueHelperFunction = (analysis, callee, currentFilename) => {
|
|
23178
|
+
if (!isNodeOfType(callee, "Identifier")) return null;
|
|
23179
|
+
const reference = getRef(analysis, callee);
|
|
23180
|
+
if (!reference?.resolved) return null;
|
|
23181
|
+
const importDefinition = reference.resolved.defs.find((definition) => definition.type === "ImportBinding");
|
|
23182
|
+
if (importDefinition) {
|
|
23183
|
+
if (!currentFilename) return null;
|
|
23184
|
+
const specifier = importDefinition.node;
|
|
23185
|
+
if (!isNodeOfType(specifier, "ImportSpecifier") && !isNodeOfType(specifier, "ImportDefaultSpecifier")) return null;
|
|
23186
|
+
const importDeclaration = specifier.parent;
|
|
23187
|
+
if (!importDeclaration || !isNodeOfType(importDeclaration, "ImportDeclaration")) return null;
|
|
23188
|
+
if (importDeclaration.importKind === "type" || isNodeOfType(specifier, "ImportSpecifier") && specifier.importKind === "type") return null;
|
|
23189
|
+
const source = importDeclaration.source?.value;
|
|
23190
|
+
if (typeof source !== "string") return null;
|
|
23191
|
+
const exportedName = resolveImportedExportName(specifier);
|
|
23192
|
+
if (!exportedName) return null;
|
|
23193
|
+
return resolveCrossFileFunctionExport(currentFilename, source, exportedName);
|
|
23194
|
+
}
|
|
23195
|
+
const callable = resolveWrappedCallable(analysis, callee);
|
|
23196
|
+
return callable && isModuleFunction(callable) ? callable : null;
|
|
23197
|
+
};
|
|
23076
23198
|
const isLocallyConstructedObjectMember = (reference, memberExpression) => isNodeOfType(memberExpression, "MemberExpression") && reference.resolved?.defs.some((definition) => {
|
|
23077
23199
|
const definitionNode = definition.node;
|
|
23078
23200
|
return isNodeOfType(definitionNode, "VariableDeclarator") && Boolean(definitionNode.init) && (isNodeOfType(definitionNode.init, "ObjectExpression") || isNodeOfType(definitionNode.init, "ArrayExpression"));
|
|
@@ -23158,38 +23280,55 @@ const collectValueEvidence = (analysis, expression, frame, remainingCallFrames,
|
|
|
23158
23280
|
const calleeRoot = getMemberRoot(callee);
|
|
23159
23281
|
const isPureGlobalCall = isNodeOfType(callee, "Identifier") && PURE_GLOBAL_CALLEE_NAMES.has(callee.name) && getIdentifierBindingIdentity(analysis, callee) === null || isNodeOfType(calleeRoot, "Identifier") && PURE_GLOBAL_NAMESPACE_NAMES.has(calleeRoot.name) && getIdentifierBindingIdentity(analysis, calleeRoot) === null;
|
|
23160
23282
|
const isPureMemberTransform = isNodeOfType(callee, "MemberExpression") && PURE_MEMBER_TRANSFORM_NAMES.has(getStaticMemberName(callee) ?? "");
|
|
23161
|
-
if (isPureMemberTransform)
|
|
23162
|
-
|
|
23163
|
-
|
|
23164
|
-
|
|
23165
|
-
|
|
23166
|
-
|
|
23167
|
-
if (isNodeOfType(callee, "MemberExpression")) {
|
|
23168
|
-
evidence.hasUnknownSource = true;
|
|
23283
|
+
if (isPureGlobalCall || isPureMemberTransform) {
|
|
23284
|
+
if (isPureMemberTransform && isNodeOfType(callee, "MemberExpression")) mergeEvidence(evidence, collectValueEvidence(analysis, callee.object, frame, remainingCallFrames, new Set(visitedBindings)));
|
|
23285
|
+
for (const argument of node.arguments ?? []) {
|
|
23286
|
+
if (isFunctionLike$1(argument)) continue;
|
|
23287
|
+
mergeEvidence(evidence, collectValueEvidence(analysis, argument, frame, remainingCallFrames, new Set(visitedBindings)));
|
|
23288
|
+
}
|
|
23169
23289
|
return evidence;
|
|
23170
23290
|
}
|
|
23171
23291
|
if (remainingCallFrames <= 0) {
|
|
23172
23292
|
evidence.hasUnknownSource = true;
|
|
23173
23293
|
return evidence;
|
|
23174
23294
|
}
|
|
23175
|
-
const
|
|
23176
|
-
if (
|
|
23177
|
-
|
|
23295
|
+
const localHelperFunction = resolveWrappedCallable(analysis, callee);
|
|
23296
|
+
if (localHelperFunction && !isModuleFunction(localHelperFunction)) {
|
|
23297
|
+
if (isAsyncOrGeneratorFunction(localHelperFunction) || functionInvokesItself(analysis, localHelperFunction)) {
|
|
23298
|
+
evidence.hasUnknownSource = true;
|
|
23299
|
+
return evidence;
|
|
23300
|
+
}
|
|
23301
|
+
const localHelperFrame = {
|
|
23302
|
+
functionNode: localHelperFunction,
|
|
23303
|
+
invocation: node,
|
|
23304
|
+
isDeferred: false,
|
|
23305
|
+
introducedBindings: /* @__PURE__ */ new Set(),
|
|
23306
|
+
substitutions: buildSubstitutions(analysis, localHelperFunction, node.arguments ?? [], frame),
|
|
23307
|
+
currentFilename: frame.currentFilename
|
|
23308
|
+
};
|
|
23309
|
+
const returnedExpressions = getReturnedExpressions(localHelperFunction);
|
|
23310
|
+
if (returnedExpressions.length === 0) {
|
|
23311
|
+
evidence.hasUnknownSource = true;
|
|
23312
|
+
return evidence;
|
|
23313
|
+
}
|
|
23314
|
+
for (const returnedExpression of returnedExpressions) mergeEvidence(evidence, collectValueEvidence(analysis, returnedExpression, localHelperFrame, remainingCallFrames - 1, new Set(visitedBindings)));
|
|
23178
23315
|
return evidence;
|
|
23179
23316
|
}
|
|
23180
|
-
const
|
|
23181
|
-
|
|
23182
|
-
|
|
23183
|
-
isDeferred: false,
|
|
23184
|
-
introducedBindings: /* @__PURE__ */ new Set(),
|
|
23185
|
-
substitutions: buildSubstitutions(analysis, callable, node.arguments ?? [], frame)
|
|
23186
|
-
};
|
|
23187
|
-
const returnedExpressions = getReturnedExpressions(callable);
|
|
23188
|
-
if (returnedExpressions.length === 0) {
|
|
23317
|
+
const helperFunction = resolveValueHelperFunction(analysis, callee, frame.currentFilename);
|
|
23318
|
+
const helperSummary = helperFunction ? summarizeHelperReturn(helperFunction) : null;
|
|
23319
|
+
if (!helperSummary) {
|
|
23189
23320
|
evidence.hasUnknownSource = true;
|
|
23190
23321
|
return evidence;
|
|
23191
23322
|
}
|
|
23192
|
-
|
|
23323
|
+
const argumentsForHelper = node.arguments ?? [];
|
|
23324
|
+
for (const parameterIndex of helperSummary.usedParameterIndices) {
|
|
23325
|
+
const argument = argumentsForHelper[parameterIndex];
|
|
23326
|
+
if (!argument) {
|
|
23327
|
+
evidence.hasUnknownSource = true;
|
|
23328
|
+
return evidence;
|
|
23329
|
+
}
|
|
23330
|
+
mergeEvidence(evidence, collectValueEvidence(analysis, argument, frame, remainingCallFrames - 1, new Set(visitedBindings)));
|
|
23331
|
+
}
|
|
23193
23332
|
return evidence;
|
|
23194
23333
|
}
|
|
23195
23334
|
if (isFunctionLike$1(node) || isNodeOfType(node, "AwaitExpression")) {
|
|
@@ -23269,8 +23408,8 @@ const areInMutuallyExclusiveBranches = (leftNode, rightNode) => {
|
|
|
23269
23408
|
}
|
|
23270
23409
|
return false;
|
|
23271
23410
|
};
|
|
23272
|
-
const collectEffectStateWriteFacts = (analysis, effectNode) => {
|
|
23273
|
-
const frames = collectBoundedEffectExecutionFrames(analysis, effectNode);
|
|
23411
|
+
const collectEffectStateWriteFacts = (analysis, effectNode, currentFilename) => {
|
|
23412
|
+
const frames = collectBoundedEffectExecutionFrames(analysis, effectNode, currentFilename);
|
|
23274
23413
|
if (frames.length === 0) return [];
|
|
23275
23414
|
const effectHasCleanup = hasCleanup(analysis, effectNode);
|
|
23276
23415
|
const cleanupManagedStateDeclarators = /* @__PURE__ */ new Set();
|
|
@@ -23290,7 +23429,8 @@ const collectEffectStateWriteFacts = (analysis, effectNode) => {
|
|
|
23290
23429
|
invocation: callExpression,
|
|
23291
23430
|
isDeferred: frame.isDeferred,
|
|
23292
23431
|
introducedBindings: collectIntroducedBindings(analysis, writtenValue),
|
|
23293
|
-
substitutions: /* @__PURE__ */ new Map()
|
|
23432
|
+
substitutions: /* @__PURE__ */ new Map(),
|
|
23433
|
+
currentFilename
|
|
23294
23434
|
};
|
|
23295
23435
|
valueEvidence = emptyEvidence();
|
|
23296
23436
|
const returnedExpressions = getReturnedExpressions(writtenValue);
|
|
@@ -23339,7 +23479,7 @@ const noAdjustStateOnPropChange = defineRule({
|
|
|
23339
23479
|
const dependencyReferences = getEffectDepsRefs(analysis, node);
|
|
23340
23480
|
if (!dependencyReferences) return;
|
|
23341
23481
|
if (!dependencyReferences.flatMap((reference) => isState(analysis, reference) ? [] : getUpstreamRefs(analysis, reference)).some((reference) => isProp(analysis, reference))) return;
|
|
23342
|
-
for (const fact of collectEffectStateWriteFacts(analysis, node)) {
|
|
23482
|
+
for (const fact of collectEffectStateWriteFacts(analysis, node, context.filename)) {
|
|
23343
23483
|
if (!fact.isRenderKnownCopy || fact.resetsSourceState) continue;
|
|
23344
23484
|
context.report({
|
|
23345
23485
|
node: fact.callExpression,
|
|
@@ -24600,6 +24740,139 @@ const createRelativeImportSource = (filename, targetFilePath) => {
|
|
|
24600
24740
|
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
24601
24741
|
};
|
|
24602
24742
|
//#endregion
|
|
24743
|
+
//#region src/plugin/utils/is-barrel-index-module.ts
|
|
24744
|
+
const INDEX_MODULE_FILE_PATTERN = /^index\.(?:[cm]?[jt]sx?|mjs)$/;
|
|
24745
|
+
const BINDING_IMPORT_DECLARATION_PATTERN = /^\s*import\s+(type\s+)?(?!["'])([^;]*?)\s+from\s+["']([^"']+)["']\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
24746
|
+
const BARREL_REEXPORT_DECLARATION_PATTERN = /^\s*export\s+(type\s+)?(?:\*(?:\s+as\s+([\w$]+))?|\{([\s\S]*?)\})\s+from\s+["']([^"']+)["']\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
24747
|
+
const LOCAL_EXPORT_SPECIFIER_DECLARATION_PATTERN = /^\s*export\s+(type\s+)?\{([\s\S]*?)\}\s*;?\s*(?:(?:\/\/[^\n]*)?\s*)/gm;
|
|
24748
|
+
const barrelIndexModuleInfoCache = /* @__PURE__ */ new Map();
|
|
24749
|
+
const isIndexModuleFilePath = (filePath) => INDEX_MODULE_FILE_PATTERN.test(path.basename(filePath));
|
|
24750
|
+
const createNonBarrelInfo = () => ({
|
|
24751
|
+
isBarrel: false,
|
|
24752
|
+
exportsByName: /* @__PURE__ */ new Map(),
|
|
24753
|
+
starExportSources: []
|
|
24754
|
+
});
|
|
24755
|
+
const addImportedBinding = (importedBindings, binding) => {
|
|
24756
|
+
importedBindings.set(binding.localName, {
|
|
24757
|
+
...binding,
|
|
24758
|
+
didExport: false
|
|
24759
|
+
});
|
|
24760
|
+
};
|
|
24761
|
+
const collectNamedImportBindings = (namedSpecifiersText, source, declarationIsTypeOnly, importedBindings) => {
|
|
24762
|
+
for (const specifier of parseExportSpecifiers(namedSpecifiersText, declarationIsTypeOnly)) addImportedBinding(importedBindings, {
|
|
24763
|
+
localName: specifier.exportedName,
|
|
24764
|
+
importedName: specifier.localName,
|
|
24765
|
+
source,
|
|
24766
|
+
isTypeOnly: specifier.isTypeOnly
|
|
24767
|
+
});
|
|
24768
|
+
};
|
|
24769
|
+
const collectImportBindings = (importClause, source, declarationIsTypeOnly, importedBindings) => {
|
|
24770
|
+
const trimmedImportClause = importClause.trim();
|
|
24771
|
+
const namespaceMatch = trimmedImportClause.match(/(?:^|,\s*)\*\s+as\s+([\w$]+)/);
|
|
24772
|
+
if (namespaceMatch?.[1]) addImportedBinding(importedBindings, {
|
|
24773
|
+
localName: namespaceMatch[1],
|
|
24774
|
+
importedName: "*",
|
|
24775
|
+
source,
|
|
24776
|
+
isTypeOnly: declarationIsTypeOnly
|
|
24777
|
+
});
|
|
24778
|
+
const namedImportMatch = trimmedImportClause.match(/\{([\s\S]*?)\}/);
|
|
24779
|
+
if (namedImportMatch?.[1]) collectNamedImportBindings(namedImportMatch[1], source, declarationIsTypeOnly, importedBindings);
|
|
24780
|
+
const defaultImportName = trimmedImportClause.split(",")[0]?.trim();
|
|
24781
|
+
if (defaultImportName && !defaultImportName.startsWith("{") && !defaultImportName.startsWith("*")) addImportedBinding(importedBindings, {
|
|
24782
|
+
localName: defaultImportName,
|
|
24783
|
+
importedName: "default",
|
|
24784
|
+
source,
|
|
24785
|
+
isTypeOnly: declarationIsTypeOnly
|
|
24786
|
+
});
|
|
24787
|
+
};
|
|
24788
|
+
const replaceKnownDeclarations = (sourceText, importedBindings, exportsByName, starExportSources) => {
|
|
24789
|
+
let withoutKnownDeclarations = sourceText.replace(BINDING_IMPORT_DECLARATION_PATTERN, (_match, typeKeyword, importClause, source) => {
|
|
24790
|
+
collectImportBindings(importClause, source, Boolean(typeKeyword), importedBindings);
|
|
24791
|
+
return "";
|
|
24792
|
+
});
|
|
24793
|
+
withoutKnownDeclarations = withoutKnownDeclarations.replace(BARREL_REEXPORT_DECLARATION_PATTERN, (_match, typeKeyword, namespaceExportName, specifiersText, source) => {
|
|
24794
|
+
const isTypeOnly = Boolean(typeKeyword);
|
|
24795
|
+
if (namespaceExportName) {
|
|
24796
|
+
exportsByName.set(namespaceExportName, {
|
|
24797
|
+
exportedName: namespaceExportName,
|
|
24798
|
+
importedName: "*",
|
|
24799
|
+
source,
|
|
24800
|
+
isTypeOnly
|
|
24801
|
+
});
|
|
24802
|
+
return "";
|
|
24803
|
+
}
|
|
24804
|
+
if (specifiersText) {
|
|
24805
|
+
for (const specifier of parseExportSpecifiers(specifiersText, isTypeOnly)) exportsByName.set(specifier.exportedName, {
|
|
24806
|
+
exportedName: specifier.exportedName,
|
|
24807
|
+
importedName: specifier.localName,
|
|
24808
|
+
source,
|
|
24809
|
+
isTypeOnly: specifier.isTypeOnly
|
|
24810
|
+
});
|
|
24811
|
+
return "";
|
|
24812
|
+
}
|
|
24813
|
+
starExportSources.push(source);
|
|
24814
|
+
return "";
|
|
24815
|
+
});
|
|
24816
|
+
withoutKnownDeclarations = withoutKnownDeclarations.replace(LOCAL_EXPORT_SPECIFIER_DECLARATION_PATTERN, (_match, typeKeyword, specifiersText) => {
|
|
24817
|
+
for (const specifier of parseExportSpecifiers(specifiersText, Boolean(typeKeyword))) {
|
|
24818
|
+
const importedBinding = importedBindings.get(specifier.localName);
|
|
24819
|
+
if (!importedBinding) return _match;
|
|
24820
|
+
importedBinding.didExport = true;
|
|
24821
|
+
exportsByName.set(specifier.exportedName, {
|
|
24822
|
+
exportedName: specifier.exportedName,
|
|
24823
|
+
importedName: importedBinding.importedName,
|
|
24824
|
+
source: importedBinding.source,
|
|
24825
|
+
isTypeOnly: specifier.isTypeOnly || importedBinding.isTypeOnly
|
|
24826
|
+
});
|
|
24827
|
+
}
|
|
24828
|
+
return "";
|
|
24829
|
+
});
|
|
24830
|
+
return withoutKnownDeclarations;
|
|
24831
|
+
};
|
|
24832
|
+
const hasUnexportedRuntimeImport = (importedBindings) => {
|
|
24833
|
+
for (const binding of importedBindings.values()) if (!binding.isTypeOnly && !binding.didExport) return true;
|
|
24834
|
+
return false;
|
|
24835
|
+
};
|
|
24836
|
+
const classifyBarrelModule = (sourceText) => {
|
|
24837
|
+
const strippedSource = stripJsComments(sourceText).trim();
|
|
24838
|
+
if (!strippedSource) return createNonBarrelInfo();
|
|
24839
|
+
const importedBindings = /* @__PURE__ */ new Map();
|
|
24840
|
+
const exportsByName = /* @__PURE__ */ new Map();
|
|
24841
|
+
const starExportSources = [];
|
|
24842
|
+
if (replaceKnownDeclarations(strippedSource, importedBindings, exportsByName, starExportSources).trim() || hasUnexportedRuntimeImport(importedBindings)) return createNonBarrelInfo();
|
|
24843
|
+
return {
|
|
24844
|
+
isBarrel: exportsByName.size > 0 || starExportSources.length > 0,
|
|
24845
|
+
exportsByName,
|
|
24846
|
+
starExportSources
|
|
24847
|
+
};
|
|
24848
|
+
};
|
|
24849
|
+
const getBarrelIndexModuleInfo = (filePath) => {
|
|
24850
|
+
if (!isIndexModuleFilePath(filePath)) return createNonBarrelInfo();
|
|
24851
|
+
recordContentProbe(filePath);
|
|
24852
|
+
let fileStat;
|
|
24853
|
+
try {
|
|
24854
|
+
fileStat = fs.statSync(filePath);
|
|
24855
|
+
} catch {
|
|
24856
|
+
fileStat = null;
|
|
24857
|
+
}
|
|
24858
|
+
const cachedResult = barrelIndexModuleInfoCache.get(filePath);
|
|
24859
|
+
if (cachedResult !== void 0 && fileStat !== null && cachedResult.mtimeMs === fileStat.mtimeMs && cachedResult.size === fileStat.size) return cachedResult.moduleInfo;
|
|
24860
|
+
if (fileStat === null) return createNonBarrelInfo();
|
|
24861
|
+
let moduleInfo = createNonBarrelInfo();
|
|
24862
|
+
try {
|
|
24863
|
+
moduleInfo = classifyBarrelModule(fs.readFileSync(filePath, "utf8"));
|
|
24864
|
+
} catch {
|
|
24865
|
+
moduleInfo = createNonBarrelInfo();
|
|
24866
|
+
}
|
|
24867
|
+
barrelIndexModuleInfoCache.set(filePath, {
|
|
24868
|
+
mtimeMs: fileStat.mtimeMs,
|
|
24869
|
+
size: fileStat.size,
|
|
24870
|
+
moduleInfo
|
|
24871
|
+
});
|
|
24872
|
+
return moduleInfo;
|
|
24873
|
+
};
|
|
24874
|
+
const isBarrelIndexModule = (filePath) => getBarrelIndexModuleInfo(filePath).isBarrel;
|
|
24875
|
+
//#endregion
|
|
24603
24876
|
//#region src/react-native-dependency-names.ts
|
|
24604
24877
|
const EXPO_MANAGED_DEPENDENCY_NAMES = new Set([
|
|
24605
24878
|
"expo",
|
|
@@ -24802,6 +25075,35 @@ const classifyReactNativeFileTarget = (context) => {
|
|
|
24802
25075
|
};
|
|
24803
25076
|
const isReactNativeFileActive = (context) => classifyReactNativeFileTarget(context) !== "web";
|
|
24804
25077
|
//#endregion
|
|
25078
|
+
//#region src/plugin/utils/resolve-barrel-export-file-path.ts
|
|
25079
|
+
const getUniqueFilePath = (filePaths) => {
|
|
25080
|
+
const uniqueFilePaths = new Set(filePaths);
|
|
25081
|
+
if (uniqueFilePaths.size !== 1) return null;
|
|
25082
|
+
const [filePath] = uniqueFilePaths;
|
|
25083
|
+
return filePath ?? null;
|
|
25084
|
+
};
|
|
25085
|
+
const resolveStarExportFilePath = (barrelFilePath, exportedName, source, visitedFilePaths) => {
|
|
25086
|
+
const resolvedTargetPath = resolveRelativeImportPath(barrelFilePath, source);
|
|
25087
|
+
if (!resolvedTargetPath) return null;
|
|
25088
|
+
const nestedTargetPath = resolveBarrelExportFilePath(resolvedTargetPath, exportedName, new Set(visitedFilePaths));
|
|
25089
|
+
if (nestedTargetPath) return nestedTargetPath;
|
|
25090
|
+
return doesModuleExportName(resolvedTargetPath, exportedName) ? resolvedTargetPath : null;
|
|
25091
|
+
};
|
|
25092
|
+
const resolveBarrelExportFilePath = (barrelFilePath, exportedName, visitedFilePaths = /* @__PURE__ */ new Set()) => {
|
|
25093
|
+
if (visitedFilePaths.has(barrelFilePath)) return null;
|
|
25094
|
+
visitedFilePaths.add(barrelFilePath);
|
|
25095
|
+
const moduleInfo = getBarrelIndexModuleInfo(barrelFilePath);
|
|
25096
|
+
if (!moduleInfo.isBarrel) return null;
|
|
25097
|
+
const target = moduleInfo.exportsByName.get(exportedName);
|
|
25098
|
+
if (target) {
|
|
25099
|
+
const resolvedTargetPath = resolveRelativeImportPath(barrelFilePath, target.source);
|
|
25100
|
+
if (!resolvedTargetPath) return null;
|
|
25101
|
+
return resolveBarrelExportFilePath(resolvedTargetPath, target.importedName, visitedFilePaths) ?? resolvedTargetPath;
|
|
25102
|
+
}
|
|
25103
|
+
if (exportedName === "default") return null;
|
|
25104
|
+
return getUniqueFilePath(moduleInfo.starExportSources.map((source) => resolveStarExportFilePath(barrelFilePath, exportedName, source, visitedFilePaths)).filter((filePath) => Boolean(filePath)));
|
|
25105
|
+
};
|
|
25106
|
+
//#endregion
|
|
24805
25107
|
//#region src/plugin/rules/bundle-size/no-barrel-import.ts
|
|
24806
25108
|
const TYPE_DECLARATION_FILE_PATTERN = /\.d\.[cm]?ts$/;
|
|
24807
25109
|
const SERVER_ONLY_FILE_PATTERN = /\.server\.[cm]?[jt]sx?$/;
|
|
@@ -26117,7 +26419,7 @@ const noDerivedState = defineRule({
|
|
|
26117
26419
|
if (!isUseEffect(node)) return;
|
|
26118
26420
|
const analysis = getProgramAnalysis(node);
|
|
26119
26421
|
if (!analysis) return;
|
|
26120
|
-
for (const fact of collectEffectStateWriteFacts(analysis, node)) {
|
|
26422
|
+
for (const fact of collectEffectStateWriteFacts(analysis, node, context.filename)) {
|
|
26121
26423
|
if (!fact.isRenderKnownCopy || fact.resetsSourceState) continue;
|
|
26122
26424
|
const stateName = getStateName$1(fact.stateDeclarator);
|
|
26123
26425
|
context.report({
|
|
@@ -26139,7 +26441,7 @@ const noDerivedStateEffect = defineRule({
|
|
|
26139
26441
|
if (!isHookCall$2(node, EFFECT_HOOK_NAMES$1)) return;
|
|
26140
26442
|
const analysis = getProgramAnalysis(node);
|
|
26141
26443
|
if (!analysis) return;
|
|
26142
|
-
if (!collectEffectStateWriteFacts(analysis, node).find((fact) => fact.isRenderKnownCopy && !fact.resetsSourceState)) return;
|
|
26444
|
+
if (!collectEffectStateWriteFacts(analysis, node, context.filename).find((fact) => fact.isRenderKnownCopy && !fact.resetsSourceState)) return;
|
|
26143
26445
|
context.report({
|
|
26144
26446
|
node,
|
|
26145
26447
|
message: "You pay an extra render for state you can derive from other values."
|
|
@@ -30467,7 +30769,7 @@ const noInitializeState = defineRule({
|
|
|
30467
30769
|
if (!dependencies || !isNodeOfType(dependencies, "ArrayExpression") || (dependencies.elements ?? []).length !== 0) return;
|
|
30468
30770
|
const analysis = getProgramAnalysis(node);
|
|
30469
30771
|
if (!analysis) return;
|
|
30470
|
-
for (const fact of collectEffectStateWriteFacts(analysis, node)) {
|
|
30772
|
+
for (const fact of collectEffectStateWriteFacts(analysis, node, context.filename)) {
|
|
30471
30773
|
if (!fact.isRenderKnownCopy || fact.matchesStateInitializer || fact.resetsSourceState) continue;
|
|
30472
30774
|
const stateName = getStateName(fact.stateDeclarator);
|
|
30473
30775
|
context.report({
|
|
@@ -58897,6 +59199,11 @@ const CROSS_FILE_RULE_IDS = new Set([
|
|
|
58897
59199
|
"no-indeterminate-attribute",
|
|
58898
59200
|
"no-locale-format-in-render",
|
|
58899
59201
|
"no-match-media-in-state-initializer",
|
|
59202
|
+
"no-adjust-state-on-prop-change",
|
|
59203
|
+
"no-derived-state",
|
|
59204
|
+
"no-derived-state-effect",
|
|
59205
|
+
"no-event-handler",
|
|
59206
|
+
"no-initialize-state",
|
|
58900
59207
|
"no-mutating-reducer-state",
|
|
58901
59208
|
"no-unguarded-browser-global-in-render-or-hook-init",
|
|
58902
59209
|
"prefer-dynamic-import",
|
|
@@ -58950,6 +59257,9 @@ const collectNextjsSearchParamsDependencies = ({ absoluteFilePath, staticImports
|
|
|
58950
59257
|
if (hasAncestorSuspenseLayout(absoluteFilePath)) return;
|
|
58951
59258
|
for (const entry of flattenImportEntries(staticImports)) resolveCrossFileFunctionExport(absoluteFilePath, entry.source, entry.exportedName);
|
|
58952
59259
|
};
|
|
59260
|
+
const collectEffectValueHelperDependencies = ({ absoluteFilePath, staticImports }) => {
|
|
59261
|
+
for (const entry of flattenImportEntries(staticImports)) resolveCrossFileFunctionExport(absoluteFilePath, entry.source, entry.exportedName);
|
|
59262
|
+
};
|
|
58953
59263
|
const collectMutatingReducerDependencies = ({ absoluteFilePath, sourceText, staticImports, program }) => {
|
|
58954
59264
|
const namedUseReducerLocals = /* @__PURE__ */ new Set();
|
|
58955
59265
|
const reactObjectLocals = /* @__PURE__ */ new Set();
|
|
@@ -59036,6 +59346,11 @@ const CROSS_FILE_DEPENDENCY_COLLECTORS = new Map([
|
|
|
59036
59346
|
["no-indeterminate-attribute", collectNearestManifestDependencies],
|
|
59037
59347
|
["no-locale-format-in-render", collectNearestManifestDependencies],
|
|
59038
59348
|
["no-match-media-in-state-initializer", collectNearestManifestDependencies],
|
|
59349
|
+
["no-adjust-state-on-prop-change", collectEffectValueHelperDependencies],
|
|
59350
|
+
["no-derived-state", collectEffectValueHelperDependencies],
|
|
59351
|
+
["no-derived-state-effect", collectEffectValueHelperDependencies],
|
|
59352
|
+
["no-event-handler", collectEffectValueHelperDependencies],
|
|
59353
|
+
["no-initialize-state", collectEffectValueHelperDependencies],
|
|
59039
59354
|
["no-mutating-reducer-state", collectMutatingReducerDependencies],
|
|
59040
59355
|
["no-unguarded-browser-global-in-render-or-hook-init", collectNearestManifestDependencies],
|
|
59041
59356
|
["prefer-dynamic-import", collectNearestManifestDependencies],
|