react-doctor 0.7.7-dev.fbc804e → 0.7.8-dev.4829841
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/cli.js +451 -78
- package/dist/index.js +436 -75
- package/dist/lsp.js +437 -76
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d7ac2526-002a-57de-91f1-7c670298fa89")}catch(e){}}();
|
|
3
3
|
import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
6
|
+
import * as Crypto from "node:crypto";
|
|
7
|
+
import crypto, { createHash } from "node:crypto";
|
|
6
8
|
import * as NFS from "node:fs";
|
|
7
9
|
import fs from "node:fs";
|
|
8
10
|
import * as Path from "node:path";
|
|
@@ -16,8 +18,6 @@ import { parseJSON5 } from "confbox";
|
|
|
16
18
|
import * as NodeUrl from "node:url";
|
|
17
19
|
import { fileURLToPath } from "node:url";
|
|
18
20
|
import { createJiti } from "jiti";
|
|
19
|
-
import * as Crypto from "node:crypto";
|
|
20
|
-
import crypto, { createHash } from "node:crypto";
|
|
21
21
|
import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
|
|
22
22
|
import { gzipSync } from "node:zlib";
|
|
23
23
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Pipeable.js
|
|
@@ -19336,12 +19336,13 @@ var JsonReportDiagnosticV3 = class extends Class("JsonReportDiagnosticV3")({
|
|
|
19336
19336
|
fixGroupId: optional(String$1)
|
|
19337
19337
|
}) {};
|
|
19338
19338
|
/**
|
|
19339
|
-
* Deterministic identity string for a diagnostic.
|
|
19340
|
-
*
|
|
19341
|
-
* suppression files, content-hash caches, and IDE "ignore this"
|
|
19342
|
-
* actions all key off one shared shape.
|
|
19339
|
+
* Deterministic identity string for a retained diagnostic occurrence.
|
|
19340
|
+
* Severity and message distinguish content variants at one normalized site.
|
|
19343
19341
|
*/
|
|
19344
|
-
const buildDiagnosticIdentity = (input) =>
|
|
19342
|
+
const buildDiagnosticIdentity = (input) => {
|
|
19343
|
+
const occurrenceDigest = createHash("sha256").update(JSON.stringify([input.severity, input.message])).digest("hex");
|
|
19344
|
+
return `${input.filePath}::${input.line}:${input.column}::${input.plugin}/${input.rule}::${occurrenceDigest}`;
|
|
19345
|
+
};
|
|
19345
19346
|
const JsonReportMode = Literals([
|
|
19346
19347
|
"full",
|
|
19347
19348
|
"diff",
|
|
@@ -33039,7 +33040,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
33039
33040
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
33040
33041
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
33041
33042
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
33042
|
-
const CORE_PACKAGE_VERSION = "0.7.
|
|
33043
|
+
const CORE_PACKAGE_VERSION = "0.7.8";
|
|
33043
33044
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
33044
33045
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
33045
33046
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -37182,18 +37183,45 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
37182
37183
|
}
|
|
37183
37184
|
return diagnostics;
|
|
37184
37185
|
};
|
|
37185
|
-
const
|
|
37186
|
-
|
|
37187
|
-
|
|
37186
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
37187
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
37188
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
37189
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
37190
|
+
return ts.ScriptKind.JS;
|
|
37191
|
+
};
|
|
37192
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
37193
|
+
let currentExpression = expression;
|
|
37194
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
37195
|
+
return currentExpression;
|
|
37196
|
+
};
|
|
37197
|
+
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
37198
|
+
isAnimationFunction: false,
|
|
37199
|
+
isMotionComponent: false,
|
|
37200
|
+
isMotionComponentFactory: false,
|
|
37201
|
+
isMotionComponentNamespace: false,
|
|
37202
|
+
isMotionConfig: false,
|
|
37203
|
+
isMotionNamespace: false,
|
|
37204
|
+
isReducedMotionHook: false
|
|
37205
|
+
};
|
|
37206
|
+
const MOTION_COMPONENT_FACTORY_EXPORT_NAMES = new Set(["m", "motion"]);
|
|
37207
|
+
const MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES = new Set(["Reorder"]);
|
|
37208
|
+
const MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES = new Set(["Item"]);
|
|
37209
|
+
const MOTION_ANIMATION_FUNCTION_EXPORT_NAMES = new Set(["animate"]);
|
|
37210
|
+
const REDUCED_MOTION_HOOK_EXPORT_NAME = "useReducedMotion";
|
|
37211
|
+
const MOTION_CONFIG_EXPORT_NAME = "MotionConfig";
|
|
37212
|
+
const REDUCED_MOTION_PROP_NAME = "reducedMotion";
|
|
37213
|
+
const REDUCED_MOTION_CONFIG_VALUES = new Set(["always", "user"]);
|
|
37214
|
+
const SCRIPT_MODULE_EXTENSIONS = [
|
|
37188
37215
|
".ts",
|
|
37189
37216
|
".tsx",
|
|
37190
37217
|
".js",
|
|
37191
|
-
".jsx"
|
|
37192
|
-
|
|
37193
|
-
|
|
37194
|
-
]);
|
|
37195
|
-
const
|
|
37196
|
-
const
|
|
37218
|
+
".jsx"
|
|
37219
|
+
];
|
|
37220
|
+
const SCRIPT_FILE_EXTENSIONS = new Set(SCRIPT_MODULE_EXTENSIONS);
|
|
37221
|
+
const STYLE_FILE_EXTENSIONS = new Set([".css", ".scss"]);
|
|
37222
|
+
const MOTION_SOURCE_PREFILTER = /framer-motion|["']motion(?:\/[A-Za-z0-9_./-]+)?["']|MotionConfig|useReducedMotion/;
|
|
37223
|
+
const REDUCED_MOTION_MEDIA_QUERY_PATTERN = /@media\s+([^{}]*\(\s*prefers-reduced-motion\s*:\s*reduce\s*\)[^{}]*)\{/gi;
|
|
37224
|
+
const CSS_DECLARATION_PATTERN = /(?:^|[;{])\s*[-_A-Za-z][-_A-Za-z0-9]*\s*:/;
|
|
37197
37225
|
const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
37198
37226
|
filePath: "package.json",
|
|
37199
37227
|
plugin: "react-doctor",
|
|
@@ -37205,52 +37233,406 @@ const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
|
37205
37233
|
column: 0,
|
|
37206
37234
|
category: "Accessibility"
|
|
37207
37235
|
};
|
|
37208
|
-
const
|
|
37236
|
+
const isMotionModuleSource = (moduleSource) => {
|
|
37237
|
+
for (const packageName of MOTION_LIBRARY_PACKAGES) if (moduleSource === packageName || moduleSource.startsWith(`${packageName}/`)) return true;
|
|
37238
|
+
return false;
|
|
37239
|
+
};
|
|
37240
|
+
const classifyMotionExport = (exportName) => ({
|
|
37241
|
+
isAnimationFunction: MOTION_ANIMATION_FUNCTION_EXPORT_NAMES.has(exportName),
|
|
37242
|
+
isMotionComponent: false,
|
|
37243
|
+
isMotionComponentFactory: MOTION_COMPONENT_FACTORY_EXPORT_NAMES.has(exportName),
|
|
37244
|
+
isMotionComponentNamespace: MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES.has(exportName),
|
|
37245
|
+
isMotionConfig: exportName === MOTION_CONFIG_EXPORT_NAME,
|
|
37246
|
+
isMotionNamespace: false,
|
|
37247
|
+
isReducedMotionHook: exportName === REDUCED_MOTION_HOOK_EXPORT_NAME
|
|
37248
|
+
});
|
|
37249
|
+
const getImportModuleSource = (node) => {
|
|
37250
|
+
let currentNode = node;
|
|
37251
|
+
while (currentNode) {
|
|
37252
|
+
if (ts.isImportDeclaration(currentNode) && ts.isStringLiteral(currentNode.moduleSpecifier)) return currentNode.moduleSpecifier.text;
|
|
37253
|
+
currentNode = currentNode.parent;
|
|
37254
|
+
}
|
|
37255
|
+
return null;
|
|
37256
|
+
};
|
|
37257
|
+
const getImportedBindingEvidence = (declaration, typeChecker, program, visitedSymbols) => {
|
|
37258
|
+
const moduleSource = getImportModuleSource(declaration);
|
|
37259
|
+
if (!moduleSource) return null;
|
|
37260
|
+
if (isMotionModuleSource(moduleSource) && ts.isNamespaceImport(declaration)) return {
|
|
37261
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37262
|
+
isMotionNamespace: true
|
|
37263
|
+
};
|
|
37264
|
+
if (isMotionModuleSource(moduleSource) && ts.isImportSpecifier(declaration)) {
|
|
37265
|
+
if (declaration.isTypeOnly) return null;
|
|
37266
|
+
return classifyMotionExport(declaration.propertyName?.text ?? declaration.name.text);
|
|
37267
|
+
}
|
|
37268
|
+
if (isMotionModuleSource(moduleSource) && ts.isImportClause(declaration)) {
|
|
37269
|
+
if (declaration.isTypeOnly) return null;
|
|
37270
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37271
|
+
}
|
|
37272
|
+
if (ts.isImportSpecifier(declaration) && !declaration.isTypeOnly || ts.isImportClause(declaration) && !declaration.isTypeOnly && declaration.name) {
|
|
37273
|
+
const importedName = ts.isImportSpecifier(declaration) ? declaration.propertyName?.text ?? declaration.name.text : "default";
|
|
37274
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, declaration.getSourceFile().fileName, program);
|
|
37275
|
+
if (!moduleSourceFile) return null;
|
|
37276
|
+
return resolveModuleExportEvidence(moduleSourceFile, importedName, typeChecker, program, visitedSymbols);
|
|
37277
|
+
}
|
|
37278
|
+
return null;
|
|
37279
|
+
};
|
|
37280
|
+
const getLocalModuleSourceFile = (moduleSource, importingFileName, program) => {
|
|
37281
|
+
if (!moduleSource.startsWith(".")) return null;
|
|
37282
|
+
const moduleBasePath = Path.resolve(Path.dirname(importingFileName), moduleSource);
|
|
37283
|
+
const moduleBaseExtension = Path.extname(moduleBasePath);
|
|
37284
|
+
const typescriptModuleBasePath = moduleBaseExtension === ".js" || moduleBaseExtension === ".jsx" ? moduleBasePath.slice(0, -moduleBaseExtension.length) : null;
|
|
37285
|
+
const candidates = [
|
|
37286
|
+
moduleBasePath,
|
|
37287
|
+
...typescriptModuleBasePath ? [
|
|
37288
|
+
`${typescriptModuleBasePath}.ts`,
|
|
37289
|
+
`${typescriptModuleBasePath}.tsx`,
|
|
37290
|
+
Path.join(typescriptModuleBasePath, "index.ts"),
|
|
37291
|
+
Path.join(typescriptModuleBasePath, "index.tsx")
|
|
37292
|
+
] : [],
|
|
37293
|
+
...SCRIPT_MODULE_EXTENSIONS.map((extension) => `${moduleBasePath}${extension}`),
|
|
37294
|
+
...SCRIPT_MODULE_EXTENSIONS.map((extension) => Path.join(moduleBasePath, `index${extension}`))
|
|
37295
|
+
];
|
|
37296
|
+
for (const candidate of candidates) {
|
|
37297
|
+
const sourceFile = program.getSourceFile(candidate);
|
|
37298
|
+
if (sourceFile) return sourceFile;
|
|
37299
|
+
}
|
|
37300
|
+
return null;
|
|
37301
|
+
};
|
|
37302
|
+
const resolveModuleExportEvidence = (sourceFile, exportName, typeChecker, program, visitedSymbols) => {
|
|
37303
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
37304
|
+
if (moduleSymbol && visitedSymbols.has(moduleSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37305
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37306
|
+
if (moduleSymbol) nextVisitedSymbols.add(moduleSymbol);
|
|
37307
|
+
for (const statement of sourceFile.statements) {
|
|
37308
|
+
if (exportName === "default" && ts.isExportAssignment(statement) && !statement.isExportEquals) {
|
|
37309
|
+
const evidence = resolveMotionExpressionEvidence(statement.expression, typeChecker, program, nextVisitedSymbols);
|
|
37310
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37311
|
+
continue;
|
|
37312
|
+
}
|
|
37313
|
+
if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) continue;
|
|
37314
|
+
if (statement.isTypeOnly) continue;
|
|
37315
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
37316
|
+
const moduleSource = statement.moduleSpecifier.text;
|
|
37317
|
+
if (!statement.exportClause) {
|
|
37318
|
+
if (isMotionModuleSource(moduleSource)) {
|
|
37319
|
+
const evidence = classifyMotionExport(exportName);
|
|
37320
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37321
|
+
continue;
|
|
37322
|
+
}
|
|
37323
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
37324
|
+
if (moduleSourceFile) {
|
|
37325
|
+
const evidence = resolveModuleExportEvidence(moduleSourceFile, exportName, typeChecker, program, nextVisitedSymbols);
|
|
37326
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37327
|
+
}
|
|
37328
|
+
continue;
|
|
37329
|
+
}
|
|
37330
|
+
if (!ts.isNamedExports(statement.exportClause)) continue;
|
|
37331
|
+
for (const exportSpecifier of statement.exportClause.elements) {
|
|
37332
|
+
if (exportSpecifier.name.text !== exportName || exportSpecifier.isTypeOnly) continue;
|
|
37333
|
+
const sourceExportName = exportSpecifier.propertyName?.text ?? exportSpecifier.name.text;
|
|
37334
|
+
if (isMotionModuleSource(moduleSource)) return classifyMotionExport(sourceExportName);
|
|
37335
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
37336
|
+
if (!moduleSourceFile) continue;
|
|
37337
|
+
return resolveModuleExportEvidence(moduleSourceFile, sourceExportName, typeChecker, program, nextVisitedSymbols);
|
|
37338
|
+
}
|
|
37339
|
+
}
|
|
37340
|
+
if (!moduleSymbol) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37341
|
+
const exportedSymbol = typeChecker.getExportsOfModule(moduleSymbol).find((candidateSymbol) => candidateSymbol.name === exportName);
|
|
37342
|
+
if (!exportedSymbol || nextVisitedSymbols.has(exportedSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37343
|
+
nextVisitedSymbols.add(exportedSymbol);
|
|
37344
|
+
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37345
|
+
for (const declaration of exportedSymbol.declarations ?? []) {
|
|
37346
|
+
if (ts.isExportSpecifier(declaration)) {
|
|
37347
|
+
const targetSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(declaration);
|
|
37348
|
+
for (const targetDeclaration of targetSymbol?.declarations ?? []) {
|
|
37349
|
+
const importedEvidence = getImportedBindingEvidence(targetDeclaration, typeChecker, program, nextVisitedSymbols);
|
|
37350
|
+
if (importedEvidence) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
37351
|
+
if (ts.isVariableDeclaration(targetDeclaration) && targetDeclaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(targetDeclaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37352
|
+
}
|
|
37353
|
+
}
|
|
37354
|
+
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37355
|
+
}
|
|
37356
|
+
return resolvedEvidence;
|
|
37357
|
+
};
|
|
37358
|
+
const mergeMotionExpressionEvidence = (leftEvidence, rightEvidence) => ({
|
|
37359
|
+
isAnimationFunction: leftEvidence.isAnimationFunction || rightEvidence.isAnimationFunction,
|
|
37360
|
+
isMotionComponent: leftEvidence.isMotionComponent || rightEvidence.isMotionComponent,
|
|
37361
|
+
isMotionComponentFactory: leftEvidence.isMotionComponentFactory || rightEvidence.isMotionComponentFactory,
|
|
37362
|
+
isMotionComponentNamespace: leftEvidence.isMotionComponentNamespace || rightEvidence.isMotionComponentNamespace,
|
|
37363
|
+
isMotionConfig: leftEvidence.isMotionConfig || rightEvidence.isMotionConfig,
|
|
37364
|
+
isMotionNamespace: leftEvidence.isMotionNamespace || rightEvidence.isMotionNamespace,
|
|
37365
|
+
isReducedMotionHook: leftEvidence.isReducedMotionHook || rightEvidence.isReducedMotionHook
|
|
37366
|
+
});
|
|
37367
|
+
const hasMotionExpressionEvidence = (evidence) => evidence.isAnimationFunction || evidence.isMotionComponent || evidence.isMotionComponentFactory || evidence.isMotionComponentNamespace || evidence.isMotionConfig || evidence.isMotionNamespace || evidence.isReducedMotionHook;
|
|
37368
|
+
const classifyMotionMember = (receiverEvidence, memberName) => {
|
|
37369
|
+
if (receiverEvidence.isMotionNamespace) return classifyMotionExport(memberName);
|
|
37370
|
+
if (receiverEvidence.isMotionComponentFactory) return {
|
|
37371
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37372
|
+
isMotionComponent: true
|
|
37373
|
+
};
|
|
37374
|
+
if (receiverEvidence.isMotionComponentNamespace && MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES.has(memberName)) return {
|
|
37375
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37376
|
+
isMotionComponent: true
|
|
37377
|
+
};
|
|
37378
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37379
|
+
};
|
|
37380
|
+
const resolveMotionExpressionEvidence = (expression, typeChecker, program, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
37381
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
37382
|
+
if (ts.isIdentifier(unwrappedExpression)) {
|
|
37383
|
+
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
37384
|
+
if (!symbol || visitedSymbols.has(symbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37385
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37386
|
+
nextVisitedSymbols.add(symbol);
|
|
37387
|
+
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37388
|
+
for (const declaration of symbol.declarations ?? []) {
|
|
37389
|
+
const importedEvidence = getImportedBindingEvidence(declaration, typeChecker, program, nextVisitedSymbols);
|
|
37390
|
+
if (importedEvidence) {
|
|
37391
|
+
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
37392
|
+
continue;
|
|
37393
|
+
}
|
|
37394
|
+
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37395
|
+
if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent) && ts.isVariableDeclaration(declaration.parent.parent) && declaration.parent.parent.initializer) {
|
|
37396
|
+
const propertyName = declaration.propertyName ?? declaration.name;
|
|
37397
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteral(propertyName)) {
|
|
37398
|
+
const receiverEvidence = resolveMotionExpressionEvidence(declaration.parent.parent.initializer, typeChecker, program, nextVisitedSymbols);
|
|
37399
|
+
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, classifyMotionMember(receiverEvidence, propertyName.text));
|
|
37400
|
+
}
|
|
37401
|
+
}
|
|
37402
|
+
}
|
|
37403
|
+
return resolvedEvidence;
|
|
37404
|
+
}
|
|
37405
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression)) return classifyMotionMember(resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols), unwrappedExpression.name.text);
|
|
37406
|
+
if (ts.isElementAccessExpression(unwrappedExpression) && unwrappedExpression.argumentExpression && (ts.isStringLiteral(unwrappedExpression.argumentExpression) || ts.isNoSubstitutionTemplateLiteral(unwrappedExpression.argumentExpression))) return classifyMotionMember(resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols), unwrappedExpression.argumentExpression.text);
|
|
37407
|
+
if (ts.isCallExpression(unwrappedExpression)) {
|
|
37408
|
+
if (ts.isIdentifier(unwrappedExpression.expression) && unwrappedExpression.expression.text === "require" && !typeChecker.getSymbolAtLocation(unwrappedExpression.expression) && unwrappedExpression.arguments.length === 1 && ts.isStringLiteral(unwrappedExpression.arguments[0]) && isMotionModuleSource(unwrappedExpression.arguments[0].text)) return {
|
|
37409
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37410
|
+
isMotionNamespace: true
|
|
37411
|
+
};
|
|
37412
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression.expression) && unwrappedExpression.expression.name.text === "bind") {
|
|
37413
|
+
const boundReceiverEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression.expression, typeChecker, program, visitedSymbols);
|
|
37414
|
+
if (boundReceiverEvidence.isAnimationFunction) return boundReceiverEvidence;
|
|
37415
|
+
}
|
|
37416
|
+
const calleeEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols);
|
|
37417
|
+
if (calleeEvidence.isMotionComponentFactory) return {
|
|
37418
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37419
|
+
isMotionComponent: true
|
|
37420
|
+
};
|
|
37421
|
+
return calleeEvidence;
|
|
37422
|
+
}
|
|
37423
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37424
|
+
};
|
|
37425
|
+
const getStaticStringExpressionValue = (expression, typeChecker, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
37426
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
37427
|
+
if (ts.isStringLiteral(unwrappedExpression) || ts.isNoSubstitutionTemplateLiteral(unwrappedExpression)) return unwrappedExpression.text;
|
|
37428
|
+
if (!ts.isIdentifier(unwrappedExpression)) return null;
|
|
37429
|
+
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
37430
|
+
if (!symbol || visitedSymbols.has(symbol)) return null;
|
|
37431
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37432
|
+
nextVisitedSymbols.add(symbol);
|
|
37433
|
+
for (const declaration of symbol.declarations ?? []) {
|
|
37434
|
+
if (!ts.isVariableDeclaration(declaration) || !declaration.initializer) continue;
|
|
37435
|
+
if (!ts.isVariableDeclarationList(declaration.parent)) continue;
|
|
37436
|
+
if (!(declaration.parent.flags & ts.NodeFlags.Const)) continue;
|
|
37437
|
+
const value = getStaticStringExpressionValue(declaration.initializer, typeChecker, nextVisitedSymbols);
|
|
37438
|
+
if (value !== null) return value;
|
|
37439
|
+
}
|
|
37440
|
+
return null;
|
|
37441
|
+
};
|
|
37442
|
+
const getStaticJsxAttributeValue = (attribute, typeChecker) => {
|
|
37443
|
+
if (!attribute.initializer) return null;
|
|
37444
|
+
if (ts.isStringLiteral(attribute.initializer)) return attribute.initializer.text;
|
|
37445
|
+
if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return null;
|
|
37446
|
+
return getStaticStringExpressionValue(attribute.initializer.expression, typeChecker);
|
|
37447
|
+
};
|
|
37448
|
+
const isExpressionValueConsumed = (expression) => {
|
|
37449
|
+
let currentExpression = expression;
|
|
37450
|
+
while (ts.isParenthesizedExpression(currentExpression.parent) || ts.isAsExpression(currentExpression.parent) || ts.isSatisfiesExpression(currentExpression.parent) || ts.isNonNullExpression(currentExpression.parent) || ts.isTypeAssertionExpression(currentExpression.parent)) currentExpression = currentExpression.parent;
|
|
37451
|
+
return !ts.isExpressionStatement(currentExpression.parent) && !ts.isVoidExpression(currentExpression.parent);
|
|
37452
|
+
};
|
|
37453
|
+
const jsxElementHasReducedMotionConfiguration = (attributes, typeChecker) => attributes.properties.some((attribute) => ts.isJsxAttribute(attribute) && ts.isIdentifier(attribute.name) && attribute.name.text === REDUCED_MOTION_PROP_NAME && REDUCED_MOTION_CONFIG_VALUES.has(getStaticJsxAttributeValue(attribute, typeChecker) ?? ""));
|
|
37454
|
+
const collectScriptMotionEvidence = (sourceFile, typeChecker, program) => {
|
|
37455
|
+
const evidence = {
|
|
37456
|
+
hasMotionUse: false,
|
|
37457
|
+
hasReducedMotionHandling: false
|
|
37458
|
+
};
|
|
37459
|
+
const visitNode = (node) => {
|
|
37460
|
+
if (ts.isCallExpression(node)) {
|
|
37461
|
+
const calleeEvidence = resolveMotionExpressionEvidence(node.expression, typeChecker, program);
|
|
37462
|
+
const isAnimationFunctionCallViaCallOrApply = (ts.isPropertyAccessExpression(node.expression) && (node.expression.name.text === "call" || node.expression.name.text === "apply") || ts.isElementAccessExpression(node.expression) && node.expression.argumentExpression && (ts.isStringLiteral(node.expression.argumentExpression) || ts.isNoSubstitutionTemplateLiteral(node.expression.argumentExpression)) && (node.expression.argumentExpression.text === "call" || node.expression.argumentExpression.text === "apply")) && resolveMotionExpressionEvidence(node.expression.expression, typeChecker, program).isAnimationFunction;
|
|
37463
|
+
if (calleeEvidence.isAnimationFunction || isAnimationFunctionCallViaCallOrApply) evidence.hasMotionUse = true;
|
|
37464
|
+
if (calleeEvidence.isReducedMotionHook && isExpressionValueConsumed(node)) evidence.hasReducedMotionHandling = true;
|
|
37465
|
+
}
|
|
37466
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
37467
|
+
const tagEvidence = ts.isJsxNamespacedName(node.tagName) ? EMPTY_MOTION_EXPRESSION_EVIDENCE : resolveMotionExpressionEvidence(node.tagName, typeChecker, program);
|
|
37468
|
+
if (tagEvidence.isMotionComponent || tagEvidence.isMotionComponentFactory) evidence.hasMotionUse = true;
|
|
37469
|
+
if (tagEvidence.isMotionConfig && jsxElementHasReducedMotionConfiguration(node.attributes, typeChecker)) evidence.hasReducedMotionHandling = true;
|
|
37470
|
+
}
|
|
37471
|
+
ts.forEachChild(node, visitNode);
|
|
37472
|
+
};
|
|
37473
|
+
visitNode(sourceFile);
|
|
37474
|
+
return evidence;
|
|
37475
|
+
};
|
|
37476
|
+
const analyzeReducedMotionSources = (sources) => {
|
|
37477
|
+
if (!sources.some(({ sourceText }) => MOTION_SOURCE_PREFILTER.test(sourceText))) return {
|
|
37478
|
+
hasMotionUse: false,
|
|
37479
|
+
hasReducedMotionHandling: false
|
|
37480
|
+
};
|
|
37481
|
+
const compilerOptions = {
|
|
37482
|
+
allowJs: true,
|
|
37483
|
+
checkJs: false,
|
|
37484
|
+
jsx: ts.JsxEmit.Preserve,
|
|
37485
|
+
module: ts.ModuleKind.ESNext,
|
|
37486
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
37487
|
+
noEmit: true,
|
|
37488
|
+
noLib: true,
|
|
37489
|
+
noResolve: true,
|
|
37490
|
+
skipLibCheck: true,
|
|
37491
|
+
target: ts.ScriptTarget.Latest
|
|
37492
|
+
};
|
|
37493
|
+
const sourceTextByFileName = new Map(sources.map(({ fileName: sourceFileName, sourceText: content }) => [Path.resolve(sourceFileName), content]));
|
|
37494
|
+
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
37495
|
+
const getDefaultSourceFile = compilerHost.getSourceFile.bind(compilerHost);
|
|
37496
|
+
compilerHost.getSourceFile = (requestedFileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => sourceTextByFileName.has(Path.resolve(requestedFileName)) ? ts.createSourceFile(Path.resolve(requestedFileName), sourceTextByFileName.get(Path.resolve(requestedFileName)) ?? "", languageVersionOrOptions, true, getTypescriptScriptKind(requestedFileName)) : getDefaultSourceFile(requestedFileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
37497
|
+
const program = ts.createProgram([...sourceTextByFileName.keys()], compilerOptions, compilerHost);
|
|
37498
|
+
const typeChecker = program.getTypeChecker();
|
|
37499
|
+
const evidence = {
|
|
37500
|
+
hasMotionUse: false,
|
|
37501
|
+
hasReducedMotionHandling: false
|
|
37502
|
+
};
|
|
37503
|
+
for (const sourceFileName of sourceTextByFileName.keys()) {
|
|
37504
|
+
const sourceFile = program.getSourceFile(sourceFileName);
|
|
37505
|
+
if (!sourceFile) continue;
|
|
37506
|
+
const fileEvidence = collectScriptMotionEvidence(sourceFile, typeChecker, program);
|
|
37507
|
+
evidence.hasMotionUse ||= fileEvidence.hasMotionUse;
|
|
37508
|
+
evidence.hasReducedMotionHandling ||= fileEvidence.hasReducedMotionHandling;
|
|
37509
|
+
}
|
|
37510
|
+
return evidence;
|
|
37511
|
+
};
|
|
37512
|
+
const removeCssCommentsAndStrings = (content) => {
|
|
37513
|
+
let sanitizedContent = "";
|
|
37514
|
+
let quote = null;
|
|
37515
|
+
let isInsideComment = false;
|
|
37516
|
+
let isInsideLineComment = false;
|
|
37517
|
+
for (let characterIndex = 0; characterIndex < content.length; characterIndex += 1) {
|
|
37518
|
+
const character = content[characterIndex];
|
|
37519
|
+
const nextCharacter = content[characterIndex + 1];
|
|
37520
|
+
if (isInsideLineComment) {
|
|
37521
|
+
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37522
|
+
if (character === "\n") isInsideLineComment = false;
|
|
37523
|
+
continue;
|
|
37524
|
+
}
|
|
37525
|
+
if (isInsideComment) {
|
|
37526
|
+
if (character === "*" && nextCharacter === "/") {
|
|
37527
|
+
sanitizedContent += " ";
|
|
37528
|
+
characterIndex += 1;
|
|
37529
|
+
isInsideComment = false;
|
|
37530
|
+
} else sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37531
|
+
continue;
|
|
37532
|
+
}
|
|
37533
|
+
if (quote) {
|
|
37534
|
+
if (character === "\\") {
|
|
37535
|
+
sanitizedContent += " ";
|
|
37536
|
+
characterIndex += 1;
|
|
37537
|
+
continue;
|
|
37538
|
+
}
|
|
37539
|
+
if (character === quote) quote = null;
|
|
37540
|
+
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37541
|
+
continue;
|
|
37542
|
+
}
|
|
37543
|
+
if (character === "/" && nextCharacter === "*") {
|
|
37544
|
+
sanitizedContent += " ";
|
|
37545
|
+
characterIndex += 1;
|
|
37546
|
+
isInsideComment = true;
|
|
37547
|
+
continue;
|
|
37548
|
+
}
|
|
37549
|
+
if (character === "/" && nextCharacter === "/") {
|
|
37550
|
+
sanitizedContent += " ";
|
|
37551
|
+
characterIndex += 1;
|
|
37552
|
+
isInsideLineComment = true;
|
|
37553
|
+
continue;
|
|
37554
|
+
}
|
|
37555
|
+
if (character === "\"" || character === "'") {
|
|
37556
|
+
sanitizedContent += " ";
|
|
37557
|
+
quote = character;
|
|
37558
|
+
continue;
|
|
37559
|
+
}
|
|
37560
|
+
sanitizedContent += character;
|
|
37561
|
+
}
|
|
37562
|
+
return sanitizedContent;
|
|
37563
|
+
};
|
|
37564
|
+
const findMatchingClosingBrace = (content, openingBraceIndex) => {
|
|
37565
|
+
let depth = 0;
|
|
37566
|
+
for (let characterIndex = openingBraceIndex; characterIndex < content.length; characterIndex += 1) {
|
|
37567
|
+
if (content[characterIndex] === "{") depth += 1;
|
|
37568
|
+
if (content[characterIndex] !== "}") continue;
|
|
37569
|
+
depth -= 1;
|
|
37570
|
+
if (depth === 0) return characterIndex;
|
|
37571
|
+
}
|
|
37572
|
+
return -1;
|
|
37573
|
+
};
|
|
37574
|
+
const hasReducedMotionMediaQuery = (content) => {
|
|
37575
|
+
const sanitizedContent = removeCssCommentsAndStrings(content);
|
|
37576
|
+
REDUCED_MOTION_MEDIA_QUERY_PATTERN.lastIndex = 0;
|
|
37577
|
+
for (const match of sanitizedContent.matchAll(REDUCED_MOTION_MEDIA_QUERY_PATTERN)) {
|
|
37578
|
+
const mediaPrelude = match[1];
|
|
37579
|
+
if (/\bnot\b/i.test(mediaPrelude)) continue;
|
|
37580
|
+
const openingBraceIndex = (match.index ?? 0) + match[0].lastIndexOf("{");
|
|
37581
|
+
const closingBraceIndex = findMatchingClosingBrace(sanitizedContent, openingBraceIndex);
|
|
37582
|
+
if (closingBraceIndex === -1) continue;
|
|
37583
|
+
const body = sanitizedContent.slice(openingBraceIndex + 1, closingBraceIndex);
|
|
37584
|
+
if (CSS_DECLARATION_PATTERN.test(body)) return true;
|
|
37585
|
+
}
|
|
37586
|
+
return false;
|
|
37587
|
+
};
|
|
37588
|
+
const collectProjectMotionEvidence = (rootDirectory) => {
|
|
37589
|
+
const scriptSources = [];
|
|
37590
|
+
let hasReducedMotionHandling = false;
|
|
37209
37591
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
37210
|
-
|
|
37592
|
+
const extension = Path.extname(name);
|
|
37593
|
+
if (!SCRIPT_FILE_EXTENSIONS.has(extension) && !STYLE_FILE_EXTENSIONS.has(extension)) continue;
|
|
37211
37594
|
let content;
|
|
37212
37595
|
try {
|
|
37213
37596
|
content = NFS.readFileSync(absolutePath, "utf-8");
|
|
37214
37597
|
} catch {
|
|
37215
37598
|
continue;
|
|
37216
37599
|
}
|
|
37217
|
-
if (
|
|
37600
|
+
if (STYLE_FILE_EXTENSIONS.has(extension)) {
|
|
37601
|
+
if (hasReducedMotionMediaQuery(content)) hasReducedMotionHandling = true;
|
|
37602
|
+
continue;
|
|
37603
|
+
}
|
|
37604
|
+
scriptSources.push({
|
|
37605
|
+
fileName: absolutePath,
|
|
37606
|
+
sourceText: content
|
|
37607
|
+
});
|
|
37218
37608
|
}
|
|
37219
|
-
return
|
|
37609
|
+
if (scriptSources.length === 0) return {
|
|
37610
|
+
hasMotionUse: false,
|
|
37611
|
+
hasReducedMotionHandling
|
|
37612
|
+
};
|
|
37613
|
+
const scriptEvidence = analyzeReducedMotionSources(scriptSources);
|
|
37614
|
+
const hasMotionUse = scriptEvidence.hasMotionUse;
|
|
37615
|
+
hasReducedMotionHandling ||= scriptEvidence.hasReducedMotionHandling;
|
|
37616
|
+
return {
|
|
37617
|
+
hasMotionUse,
|
|
37618
|
+
hasReducedMotionHandling
|
|
37619
|
+
};
|
|
37220
37620
|
};
|
|
37221
37621
|
const checkReducedMotion = (rootDirectory) => {
|
|
37222
37622
|
const packageJsonPath = Path.join(rootDirectory, "package.json");
|
|
37223
37623
|
if (!isFile(packageJsonPath)) return [];
|
|
37224
|
-
let hasMotionLibrary = false;
|
|
37225
37624
|
try {
|
|
37226
37625
|
const packageJson = readPackageJson(packageJsonPath);
|
|
37227
37626
|
const allDependencies = {
|
|
37228
37627
|
...packageJson.dependencies,
|
|
37229
37628
|
...packageJson.devDependencies
|
|
37230
37629
|
};
|
|
37231
|
-
|
|
37630
|
+
if (!Object.keys(allDependencies).some((packageName) => MOTION_LIBRARY_PACKAGES.has(packageName))) return [];
|
|
37232
37631
|
} catch {
|
|
37233
37632
|
return [];
|
|
37234
37633
|
}
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
"grep",
|
|
37238
|
-
"--untracked",
|
|
37239
|
-
"-lE",
|
|
37240
|
-
REDUCED_MOTION_GREP_PATTERN,
|
|
37241
|
-
"--",
|
|
37242
|
-
...REDUCED_MOTION_FILE_GLOBS
|
|
37243
|
-
], {
|
|
37244
|
-
cwd: rootDirectory,
|
|
37245
|
-
encoding: "utf-8",
|
|
37246
|
-
stdio: [
|
|
37247
|
-
"ignore",
|
|
37248
|
-
"pipe",
|
|
37249
|
-
"pipe"
|
|
37250
|
-
]
|
|
37251
|
-
});
|
|
37252
|
-
if (!(!result.error && (result.status === 0 || result.status === GIT_GREP_NO_MATCH_STATUS))) return hasReducedMotionHandlingViaFilesystem(rootDirectory) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
37253
|
-
return result.status === 0 && result.stdout.split("\n").some((filePath) => filePath.length > 0 && !hasIgnoredPathSegment(filePath)) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
37634
|
+
const evidence = collectProjectMotionEvidence(rootDirectory);
|
|
37635
|
+
return evidence.hasMotionUse && !evidence.hasReducedMotionHandling ? [MISSING_REDUCED_MOTION_DIAGNOSTIC] : [];
|
|
37254
37636
|
};
|
|
37255
37637
|
const buildSecurityScanDiagnostic = (finding, entry, relativePath) => ({
|
|
37256
37638
|
filePath: relativePath,
|
|
@@ -39853,23 +40235,12 @@ const REACT_USE_BINDING_RESOLUTION = {
|
|
|
39853
40235
|
isReactUseBinding: true,
|
|
39854
40236
|
isReactNamespaceBinding: false
|
|
39855
40237
|
};
|
|
39856
|
-
const getScriptKind$2 = (filename) => {
|
|
39857
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
39858
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
39859
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
39860
|
-
return ts.ScriptKind.JS;
|
|
39861
|
-
};
|
|
39862
40238
|
const getUtf16Offset$1 = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
39863
|
-
const unwrapExpression = (expression) => {
|
|
39864
|
-
let currentExpression = expression;
|
|
39865
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
39866
|
-
return currentExpression;
|
|
39867
|
-
};
|
|
39868
40239
|
const getStaticPropertyName = (node) => {
|
|
39869
40240
|
if (!node) return null;
|
|
39870
40241
|
if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node)) return node.text;
|
|
39871
40242
|
if (ts.isComputedPropertyName(node)) {
|
|
39872
|
-
const expression =
|
|
40243
|
+
const expression = unwrapTypescriptExpression(node.expression);
|
|
39873
40244
|
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
|
|
39874
40245
|
}
|
|
39875
40246
|
return null;
|
|
@@ -39898,7 +40269,7 @@ const isReactUseObjectBindingElement = (bindingElement) => {
|
|
|
39898
40269
|
return getStaticPropertyName(bindingElement.propertyName) === USE_IDENTIFIER;
|
|
39899
40270
|
};
|
|
39900
40271
|
const isReactRequireCall = (expression) => {
|
|
39901
|
-
const unwrappedExpression =
|
|
40272
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
39902
40273
|
return ts.isCallExpression(unwrappedExpression) && ts.isIdentifier(unwrappedExpression.expression) && unwrappedExpression.expression.text === REQUIRE_IDENTIFIER && unwrappedExpression.arguments.length === 1 && ts.isStringLiteral(unwrappedExpression.arguments[0]) && unwrappedExpression.arguments[0].text === REACT_MODULE_SOURCE;
|
|
39903
40274
|
};
|
|
39904
40275
|
const getModuleSource = (node) => {
|
|
@@ -40000,7 +40371,7 @@ const isIdentifierShadowedByLocalBinding = (identifier, sourceFile) => {
|
|
|
40000
40371
|
return false;
|
|
40001
40372
|
};
|
|
40002
40373
|
const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
40003
|
-
const unwrappedExpression =
|
|
40374
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
40004
40375
|
if (isReactRequireCall(unwrappedExpression)) return true;
|
|
40005
40376
|
if (!ts.isIdentifier(unwrappedExpression)) return false;
|
|
40006
40377
|
if (reactImportBindings.namespaceNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
@@ -40008,7 +40379,7 @@ const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile,
|
|
|
40008
40379
|
};
|
|
40009
40380
|
const isReactUseExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
40010
40381
|
if (!expression) return false;
|
|
40011
|
-
const unwrappedExpression =
|
|
40382
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
40012
40383
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
40013
40384
|
if (reactImportBindings.useImportNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
40014
40385
|
if (unwrappedExpression.text === USE_IDENTIFIER) return false;
|
|
@@ -40108,7 +40479,7 @@ const findUseCallIdentifier = (sourceFile, useOffset) => {
|
|
|
40108
40479
|
return matchedIdentifier;
|
|
40109
40480
|
};
|
|
40110
40481
|
const resolveUseCallBinding = (sourceText, filename, utf8Offset) => {
|
|
40111
|
-
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true,
|
|
40482
|
+
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filename));
|
|
40112
40483
|
const useIdentifier = findUseCallIdentifier(sourceFile, getUtf16Offset$1(sourceText, utf8Offset));
|
|
40113
40484
|
if (!useIdentifier) return null;
|
|
40114
40485
|
return resolveIdentifierBinding(useIdentifier, collectReactImportBindings(sourceFile), sourceFile);
|
|
@@ -40144,12 +40515,6 @@ const WORKLET_ACCEPTING_CALLEES = new Set([
|
|
|
40144
40515
|
"executeOnUIRuntimeSync"
|
|
40145
40516
|
]);
|
|
40146
40517
|
const GESTURE_ROOT_IDENTIFIER = "Gesture";
|
|
40147
|
-
const getScriptKind$1 = (filename) => {
|
|
40148
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
40149
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
40150
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
40151
|
-
return ts.ScriptKind.JS;
|
|
40152
|
-
};
|
|
40153
40518
|
const getUtf16Offset = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
40154
40519
|
const hasWorkletDirective = (node) => {
|
|
40155
40520
|
if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) return false;
|
|
@@ -40221,17 +40586,11 @@ const shouldSuppressCompilerFindingInWorklet = (diagnostic, project, rootDirecto
|
|
|
40221
40586
|
} catch {
|
|
40222
40587
|
return false;
|
|
40223
40588
|
}
|
|
40224
|
-
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true,
|
|
40589
|
+
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(absolutePath)), getUtf16Offset(sourceText, primaryLabel.span.offset));
|
|
40225
40590
|
};
|
|
40226
40591
|
const MANUAL_MEMOIZATION_PLUGIN = "react-doctor";
|
|
40227
40592
|
const MANUAL_MEMOIZATION_RULE = "react-compiler-no-manual-memoization";
|
|
40228
40593
|
const REACT_COMPILER_PLUGIN = "react-hooks-js";
|
|
40229
|
-
const getScriptKind = (filename) => {
|
|
40230
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
40231
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
40232
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
40233
|
-
return ts.ScriptKind.JS;
|
|
40234
|
-
};
|
|
40235
40594
|
const isManualMemoizationDiagnostic = (diagnostic) => diagnostic.plugin === MANUAL_MEMOIZATION_PLUGIN && diagnostic.rule === MANUAL_MEMOIZATION_RULE;
|
|
40236
40595
|
const nodeLineRange = (sourceFile, node) => ({
|
|
40237
40596
|
startLine: sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1,
|
|
@@ -40293,7 +40652,7 @@ const suppressMemoizationInBailedOutFunctions = (diagnostics, rootDirectory) =>
|
|
|
40293
40652
|
try {
|
|
40294
40653
|
const buffer = NFS.readFileSync(absolutePath);
|
|
40295
40654
|
parsed = {
|
|
40296
|
-
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true,
|
|
40655
|
+
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true, getTypescriptScriptKind(absolutePath)),
|
|
40297
40656
|
buffer
|
|
40298
40657
|
};
|
|
40299
40658
|
} catch {
|
|
@@ -42884,7 +43243,9 @@ const toJsonReportDiagnostic = (diagnostic, projectRoot, reportRoot) => {
|
|
|
42884
43243
|
line: diagnostic.line,
|
|
42885
43244
|
column: diagnostic.column,
|
|
42886
43245
|
plugin: diagnostic.plugin,
|
|
42887
|
-
rule: diagnostic.rule
|
|
43246
|
+
rule: diagnostic.rule,
|
|
43247
|
+
severity: diagnostic.severity,
|
|
43248
|
+
message: diagnostic.message
|
|
42888
43249
|
}),
|
|
42889
43250
|
normalizedFilePath,
|
|
42890
43251
|
category: ruleIdentity.category,
|
|
@@ -43278,4 +43639,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43278
43639
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43279
43640
|
|
|
43280
43641
|
//# sourceMappingURL=index.js.map
|
|
43281
|
-
//# debugId=
|
|
43642
|
+
//# debugId=d7ac2526-002a-57de-91f1-7c670298fa89
|