react-doctor 0.7.7-dev.4190897 → 0.7.7-dev.4fce1c1
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 +77 -450
- package/dist/index.js +74 -435
- package/dist/lsp.js +74 -435
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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]="50d648e9-77ea-5f0f-87a2-6d2a2461613e")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -9,8 +9,6 @@ import * as NFS from "node:fs";
|
|
|
9
9
|
import fs, { mkdtempSync, rmSync } from "node:fs";
|
|
10
10
|
import process$1 from "node:process";
|
|
11
11
|
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";
|
|
12
|
-
import * as Crypto from "node:crypto";
|
|
13
|
-
import crypto, { createHash, randomUUID } from "node:crypto";
|
|
14
12
|
import ts from "typescript";
|
|
15
13
|
import * as OS from "node:os";
|
|
16
14
|
import os, { tmpdir } from "node:os";
|
|
@@ -18,6 +16,8 @@ import { parseJSON5 } from "confbox";
|
|
|
18
16
|
import * as NodeUrl from "node:url";
|
|
19
17
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
20
18
|
import { createJiti } from "jiti";
|
|
19
|
+
import * as Crypto from "node:crypto";
|
|
20
|
+
import crypto, { createHash, randomUUID } 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
|
import * as Sentry from "@sentry/node";
|
|
@@ -22437,13 +22437,12 @@ var JsonReportDiagnosticV3 = class extends Class("JsonReportDiagnosticV3")({
|
|
|
22437
22437
|
fixGroupId: optional(String$1)
|
|
22438
22438
|
}) {};
|
|
22439
22439
|
/**
|
|
22440
|
-
* Deterministic identity string for a
|
|
22441
|
-
*
|
|
22440
|
+
* Deterministic identity string for a diagnostic. Same diagnostic
|
|
22441
|
+
* across two scans yields the same identity; lets baselines,
|
|
22442
|
+
* suppression files, content-hash caches, and IDE "ignore this"
|
|
22443
|
+
* actions all key off one shared shape.
|
|
22442
22444
|
*/
|
|
22443
|
-
const buildDiagnosticIdentity = (input) => {
|
|
22444
|
-
const occurrenceDigest = createHash("sha256").update(JSON.stringify([input.severity, input.message])).digest("hex");
|
|
22445
|
-
return `${input.filePath}::${input.line}:${input.column}::${input.plugin}/${input.rule}::${occurrenceDigest}`;
|
|
22446
|
-
};
|
|
22445
|
+
const buildDiagnosticIdentity = (input) => `${input.filePath}::${input.line}:${input.column}::${input.plugin}/${input.rule}`;
|
|
22447
22446
|
const JsonReportMode = Literals([
|
|
22448
22447
|
"full",
|
|
22449
22448
|
"diff",
|
|
@@ -40411,45 +40410,18 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
40411
40410
|
}
|
|
40412
40411
|
return diagnostics;
|
|
40413
40412
|
};
|
|
40414
|
-
const
|
|
40415
|
-
|
|
40416
|
-
|
|
40417
|
-
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
40418
|
-
return ts.ScriptKind.JS;
|
|
40419
|
-
};
|
|
40420
|
-
const unwrapTypescriptExpression = (expression) => {
|
|
40421
|
-
let currentExpression = expression;
|
|
40422
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
40423
|
-
return currentExpression;
|
|
40424
|
-
};
|
|
40425
|
-
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
40426
|
-
isAnimationFunction: false,
|
|
40427
|
-
isMotionComponent: false,
|
|
40428
|
-
isMotionComponentFactory: false,
|
|
40429
|
-
isMotionComponentNamespace: false,
|
|
40430
|
-
isMotionConfig: false,
|
|
40431
|
-
isMotionNamespace: false,
|
|
40432
|
-
isReducedMotionHook: false
|
|
40433
|
-
};
|
|
40434
|
-
const MOTION_COMPONENT_FACTORY_EXPORT_NAMES = new Set(["m", "motion"]);
|
|
40435
|
-
const MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES = new Set(["Reorder"]);
|
|
40436
|
-
const MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES = new Set(["Item"]);
|
|
40437
|
-
const MOTION_ANIMATION_FUNCTION_EXPORT_NAMES = new Set(["animate"]);
|
|
40438
|
-
const REDUCED_MOTION_HOOK_EXPORT_NAME = "useReducedMotion";
|
|
40439
|
-
const MOTION_CONFIG_EXPORT_NAME = "MotionConfig";
|
|
40440
|
-
const REDUCED_MOTION_PROP_NAME = "reducedMotion";
|
|
40441
|
-
const REDUCED_MOTION_CONFIG_VALUES = new Set(["always", "user"]);
|
|
40442
|
-
const SCRIPT_MODULE_EXTENSIONS = [
|
|
40413
|
+
const REDUCED_MOTION_GREP_PATTERN = "prefers-reduced-motion|useReducedMotion|MotionConfig|reducedMotion";
|
|
40414
|
+
const REDUCED_MOTION_PATTERN = new RegExp(REDUCED_MOTION_GREP_PATTERN);
|
|
40415
|
+
const REDUCED_MOTION_FILE_EXTENSIONS = new Set([
|
|
40443
40416
|
".ts",
|
|
40444
40417
|
".tsx",
|
|
40445
40418
|
".js",
|
|
40446
|
-
".jsx"
|
|
40447
|
-
|
|
40448
|
-
|
|
40449
|
-
|
|
40450
|
-
const
|
|
40451
|
-
const
|
|
40452
|
-
const CSS_DECLARATION_PATTERN = /(?:^|[;{])\s*[-_A-Za-z][-_A-Za-z0-9]*\s*:/;
|
|
40419
|
+
".jsx",
|
|
40420
|
+
".css",
|
|
40421
|
+
".scss"
|
|
40422
|
+
]);
|
|
40423
|
+
const REDUCED_MOTION_FILE_GLOBS = [...REDUCED_MOTION_FILE_EXTENSIONS].map((extension) => `*${extension}`);
|
|
40424
|
+
const GIT_GREP_NO_MATCH_STATUS = 1;
|
|
40453
40425
|
const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
40454
40426
|
filePath: "package.json",
|
|
40455
40427
|
plugin: "react-doctor",
|
|
@@ -40461,406 +40433,52 @@ const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
|
40461
40433
|
column: 0,
|
|
40462
40434
|
category: "Accessibility"
|
|
40463
40435
|
};
|
|
40464
|
-
const
|
|
40465
|
-
for (const packageName of MOTION_LIBRARY_PACKAGES) if (moduleSource === packageName || moduleSource.startsWith(`${packageName}/`)) return true;
|
|
40466
|
-
return false;
|
|
40467
|
-
};
|
|
40468
|
-
const classifyMotionExport = (exportName) => ({
|
|
40469
|
-
isAnimationFunction: MOTION_ANIMATION_FUNCTION_EXPORT_NAMES.has(exportName),
|
|
40470
|
-
isMotionComponent: false,
|
|
40471
|
-
isMotionComponentFactory: MOTION_COMPONENT_FACTORY_EXPORT_NAMES.has(exportName),
|
|
40472
|
-
isMotionComponentNamespace: MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES.has(exportName),
|
|
40473
|
-
isMotionConfig: exportName === MOTION_CONFIG_EXPORT_NAME,
|
|
40474
|
-
isMotionNamespace: false,
|
|
40475
|
-
isReducedMotionHook: exportName === REDUCED_MOTION_HOOK_EXPORT_NAME
|
|
40476
|
-
});
|
|
40477
|
-
const getImportModuleSource = (node) => {
|
|
40478
|
-
let currentNode = node;
|
|
40479
|
-
while (currentNode) {
|
|
40480
|
-
if (ts.isImportDeclaration(currentNode) && ts.isStringLiteral(currentNode.moduleSpecifier)) return currentNode.moduleSpecifier.text;
|
|
40481
|
-
currentNode = currentNode.parent;
|
|
40482
|
-
}
|
|
40483
|
-
return null;
|
|
40484
|
-
};
|
|
40485
|
-
const getImportedBindingEvidence = (declaration, typeChecker, program, visitedSymbols) => {
|
|
40486
|
-
const moduleSource = getImportModuleSource(declaration);
|
|
40487
|
-
if (!moduleSource) return null;
|
|
40488
|
-
if (isMotionModuleSource(moduleSource) && ts.isNamespaceImport(declaration)) return {
|
|
40489
|
-
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
40490
|
-
isMotionNamespace: true
|
|
40491
|
-
};
|
|
40492
|
-
if (isMotionModuleSource(moduleSource) && ts.isImportSpecifier(declaration)) {
|
|
40493
|
-
if (declaration.isTypeOnly) return null;
|
|
40494
|
-
return classifyMotionExport(declaration.propertyName?.text ?? declaration.name.text);
|
|
40495
|
-
}
|
|
40496
|
-
if (isMotionModuleSource(moduleSource) && ts.isImportClause(declaration)) {
|
|
40497
|
-
if (declaration.isTypeOnly) return null;
|
|
40498
|
-
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40499
|
-
}
|
|
40500
|
-
if (ts.isImportSpecifier(declaration) && !declaration.isTypeOnly || ts.isImportClause(declaration) && !declaration.isTypeOnly && declaration.name) {
|
|
40501
|
-
const importedName = ts.isImportSpecifier(declaration) ? declaration.propertyName?.text ?? declaration.name.text : "default";
|
|
40502
|
-
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, declaration.getSourceFile().fileName, program);
|
|
40503
|
-
if (!moduleSourceFile) return null;
|
|
40504
|
-
return resolveModuleExportEvidence(moduleSourceFile, importedName, typeChecker, program, visitedSymbols);
|
|
40505
|
-
}
|
|
40506
|
-
return null;
|
|
40507
|
-
};
|
|
40508
|
-
const getLocalModuleSourceFile = (moduleSource, importingFileName, program) => {
|
|
40509
|
-
if (!moduleSource.startsWith(".")) return null;
|
|
40510
|
-
const moduleBasePath = Path.resolve(Path.dirname(importingFileName), moduleSource);
|
|
40511
|
-
const moduleBaseExtension = Path.extname(moduleBasePath);
|
|
40512
|
-
const typescriptModuleBasePath = moduleBaseExtension === ".js" || moduleBaseExtension === ".jsx" ? moduleBasePath.slice(0, -moduleBaseExtension.length) : null;
|
|
40513
|
-
const candidates = [
|
|
40514
|
-
moduleBasePath,
|
|
40515
|
-
...typescriptModuleBasePath ? [
|
|
40516
|
-
`${typescriptModuleBasePath}.ts`,
|
|
40517
|
-
`${typescriptModuleBasePath}.tsx`,
|
|
40518
|
-
Path.join(typescriptModuleBasePath, "index.ts"),
|
|
40519
|
-
Path.join(typescriptModuleBasePath, "index.tsx")
|
|
40520
|
-
] : [],
|
|
40521
|
-
...SCRIPT_MODULE_EXTENSIONS.map((extension) => `${moduleBasePath}${extension}`),
|
|
40522
|
-
...SCRIPT_MODULE_EXTENSIONS.map((extension) => Path.join(moduleBasePath, `index${extension}`))
|
|
40523
|
-
];
|
|
40524
|
-
for (const candidate of candidates) {
|
|
40525
|
-
const sourceFile = program.getSourceFile(candidate);
|
|
40526
|
-
if (sourceFile) return sourceFile;
|
|
40527
|
-
}
|
|
40528
|
-
return null;
|
|
40529
|
-
};
|
|
40530
|
-
const resolveModuleExportEvidence = (sourceFile, exportName, typeChecker, program, visitedSymbols) => {
|
|
40531
|
-
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
40532
|
-
if (moduleSymbol && visitedSymbols.has(moduleSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40533
|
-
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
40534
|
-
if (moduleSymbol) nextVisitedSymbols.add(moduleSymbol);
|
|
40535
|
-
for (const statement of sourceFile.statements) {
|
|
40536
|
-
if (exportName === "default" && ts.isExportAssignment(statement) && !statement.isExportEquals) {
|
|
40537
|
-
const evidence = resolveMotionExpressionEvidence(statement.expression, typeChecker, program, nextVisitedSymbols);
|
|
40538
|
-
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
40539
|
-
continue;
|
|
40540
|
-
}
|
|
40541
|
-
if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) continue;
|
|
40542
|
-
if (statement.isTypeOnly) continue;
|
|
40543
|
-
if (!ts.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
40544
|
-
const moduleSource = statement.moduleSpecifier.text;
|
|
40545
|
-
if (!statement.exportClause) {
|
|
40546
|
-
if (isMotionModuleSource(moduleSource)) {
|
|
40547
|
-
const evidence = classifyMotionExport(exportName);
|
|
40548
|
-
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
40549
|
-
continue;
|
|
40550
|
-
}
|
|
40551
|
-
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
40552
|
-
if (moduleSourceFile) {
|
|
40553
|
-
const evidence = resolveModuleExportEvidence(moduleSourceFile, exportName, typeChecker, program, nextVisitedSymbols);
|
|
40554
|
-
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
40555
|
-
}
|
|
40556
|
-
continue;
|
|
40557
|
-
}
|
|
40558
|
-
if (!ts.isNamedExports(statement.exportClause)) continue;
|
|
40559
|
-
for (const exportSpecifier of statement.exportClause.elements) {
|
|
40560
|
-
if (exportSpecifier.name.text !== exportName || exportSpecifier.isTypeOnly) continue;
|
|
40561
|
-
const sourceExportName = exportSpecifier.propertyName?.text ?? exportSpecifier.name.text;
|
|
40562
|
-
if (isMotionModuleSource(moduleSource)) return classifyMotionExport(sourceExportName);
|
|
40563
|
-
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
40564
|
-
if (!moduleSourceFile) continue;
|
|
40565
|
-
return resolveModuleExportEvidence(moduleSourceFile, sourceExportName, typeChecker, program, nextVisitedSymbols);
|
|
40566
|
-
}
|
|
40567
|
-
}
|
|
40568
|
-
if (!moduleSymbol) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40569
|
-
const exportedSymbol = typeChecker.getExportsOfModule(moduleSymbol).find((candidateSymbol) => candidateSymbol.name === exportName);
|
|
40570
|
-
if (!exportedSymbol || nextVisitedSymbols.has(exportedSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40571
|
-
nextVisitedSymbols.add(exportedSymbol);
|
|
40572
|
-
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40573
|
-
for (const declaration of exportedSymbol.declarations ?? []) {
|
|
40574
|
-
if (ts.isExportSpecifier(declaration)) {
|
|
40575
|
-
const targetSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(declaration);
|
|
40576
|
-
for (const targetDeclaration of targetSymbol?.declarations ?? []) {
|
|
40577
|
-
const importedEvidence = getImportedBindingEvidence(targetDeclaration, typeChecker, program, nextVisitedSymbols);
|
|
40578
|
-
if (importedEvidence) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
40579
|
-
if (ts.isVariableDeclaration(targetDeclaration) && targetDeclaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(targetDeclaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
40580
|
-
}
|
|
40581
|
-
}
|
|
40582
|
-
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
40583
|
-
}
|
|
40584
|
-
return resolvedEvidence;
|
|
40585
|
-
};
|
|
40586
|
-
const mergeMotionExpressionEvidence = (leftEvidence, rightEvidence) => ({
|
|
40587
|
-
isAnimationFunction: leftEvidence.isAnimationFunction || rightEvidence.isAnimationFunction,
|
|
40588
|
-
isMotionComponent: leftEvidence.isMotionComponent || rightEvidence.isMotionComponent,
|
|
40589
|
-
isMotionComponentFactory: leftEvidence.isMotionComponentFactory || rightEvidence.isMotionComponentFactory,
|
|
40590
|
-
isMotionComponentNamespace: leftEvidence.isMotionComponentNamespace || rightEvidence.isMotionComponentNamespace,
|
|
40591
|
-
isMotionConfig: leftEvidence.isMotionConfig || rightEvidence.isMotionConfig,
|
|
40592
|
-
isMotionNamespace: leftEvidence.isMotionNamespace || rightEvidence.isMotionNamespace,
|
|
40593
|
-
isReducedMotionHook: leftEvidence.isReducedMotionHook || rightEvidence.isReducedMotionHook
|
|
40594
|
-
});
|
|
40595
|
-
const hasMotionExpressionEvidence = (evidence) => evidence.isAnimationFunction || evidence.isMotionComponent || evidence.isMotionComponentFactory || evidence.isMotionComponentNamespace || evidence.isMotionConfig || evidence.isMotionNamespace || evidence.isReducedMotionHook;
|
|
40596
|
-
const classifyMotionMember = (receiverEvidence, memberName) => {
|
|
40597
|
-
if (receiverEvidence.isMotionNamespace) return classifyMotionExport(memberName);
|
|
40598
|
-
if (receiverEvidence.isMotionComponentFactory) return {
|
|
40599
|
-
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
40600
|
-
isMotionComponent: true
|
|
40601
|
-
};
|
|
40602
|
-
if (receiverEvidence.isMotionComponentNamespace && MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES.has(memberName)) return {
|
|
40603
|
-
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
40604
|
-
isMotionComponent: true
|
|
40605
|
-
};
|
|
40606
|
-
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40607
|
-
};
|
|
40608
|
-
const resolveMotionExpressionEvidence = (expression, typeChecker, program, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
40609
|
-
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
40610
|
-
if (ts.isIdentifier(unwrappedExpression)) {
|
|
40611
|
-
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
40612
|
-
if (!symbol || visitedSymbols.has(symbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40613
|
-
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
40614
|
-
nextVisitedSymbols.add(symbol);
|
|
40615
|
-
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40616
|
-
for (const declaration of symbol.declarations ?? []) {
|
|
40617
|
-
const importedEvidence = getImportedBindingEvidence(declaration, typeChecker, program, nextVisitedSymbols);
|
|
40618
|
-
if (importedEvidence) {
|
|
40619
|
-
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
40620
|
-
continue;
|
|
40621
|
-
}
|
|
40622
|
-
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
40623
|
-
if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent) && ts.isVariableDeclaration(declaration.parent.parent) && declaration.parent.parent.initializer) {
|
|
40624
|
-
const propertyName = declaration.propertyName ?? declaration.name;
|
|
40625
|
-
if (ts.isIdentifier(propertyName) || ts.isStringLiteral(propertyName)) {
|
|
40626
|
-
const receiverEvidence = resolveMotionExpressionEvidence(declaration.parent.parent.initializer, typeChecker, program, nextVisitedSymbols);
|
|
40627
|
-
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, classifyMotionMember(receiverEvidence, propertyName.text));
|
|
40628
|
-
}
|
|
40629
|
-
}
|
|
40630
|
-
}
|
|
40631
|
-
return resolvedEvidence;
|
|
40632
|
-
}
|
|
40633
|
-
if (ts.isPropertyAccessExpression(unwrappedExpression)) return classifyMotionMember(resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols), unwrappedExpression.name.text);
|
|
40634
|
-
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);
|
|
40635
|
-
if (ts.isCallExpression(unwrappedExpression)) {
|
|
40636
|
-
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 {
|
|
40637
|
-
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
40638
|
-
isMotionNamespace: true
|
|
40639
|
-
};
|
|
40640
|
-
if (ts.isPropertyAccessExpression(unwrappedExpression.expression) && unwrappedExpression.expression.name.text === "bind") {
|
|
40641
|
-
const boundReceiverEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression.expression, typeChecker, program, visitedSymbols);
|
|
40642
|
-
if (boundReceiverEvidence.isAnimationFunction) return boundReceiverEvidence;
|
|
40643
|
-
}
|
|
40644
|
-
const calleeEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols);
|
|
40645
|
-
if (calleeEvidence.isMotionComponentFactory) return {
|
|
40646
|
-
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
40647
|
-
isMotionComponent: true
|
|
40648
|
-
};
|
|
40649
|
-
return calleeEvidence;
|
|
40650
|
-
}
|
|
40651
|
-
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
40652
|
-
};
|
|
40653
|
-
const getStaticStringExpressionValue = (expression, typeChecker, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
40654
|
-
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
40655
|
-
if (ts.isStringLiteral(unwrappedExpression) || ts.isNoSubstitutionTemplateLiteral(unwrappedExpression)) return unwrappedExpression.text;
|
|
40656
|
-
if (!ts.isIdentifier(unwrappedExpression)) return null;
|
|
40657
|
-
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
40658
|
-
if (!symbol || visitedSymbols.has(symbol)) return null;
|
|
40659
|
-
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
40660
|
-
nextVisitedSymbols.add(symbol);
|
|
40661
|
-
for (const declaration of symbol.declarations ?? []) {
|
|
40662
|
-
if (!ts.isVariableDeclaration(declaration) || !declaration.initializer) continue;
|
|
40663
|
-
if (!ts.isVariableDeclarationList(declaration.parent)) continue;
|
|
40664
|
-
if (!(declaration.parent.flags & ts.NodeFlags.Const)) continue;
|
|
40665
|
-
const value = getStaticStringExpressionValue(declaration.initializer, typeChecker, nextVisitedSymbols);
|
|
40666
|
-
if (value !== null) return value;
|
|
40667
|
-
}
|
|
40668
|
-
return null;
|
|
40669
|
-
};
|
|
40670
|
-
const getStaticJsxAttributeValue = (attribute, typeChecker) => {
|
|
40671
|
-
if (!attribute.initializer) return null;
|
|
40672
|
-
if (ts.isStringLiteral(attribute.initializer)) return attribute.initializer.text;
|
|
40673
|
-
if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return null;
|
|
40674
|
-
return getStaticStringExpressionValue(attribute.initializer.expression, typeChecker);
|
|
40675
|
-
};
|
|
40676
|
-
const isExpressionValueConsumed = (expression) => {
|
|
40677
|
-
let currentExpression = expression;
|
|
40678
|
-
while (ts.isParenthesizedExpression(currentExpression.parent) || ts.isAsExpression(currentExpression.parent) || ts.isSatisfiesExpression(currentExpression.parent) || ts.isNonNullExpression(currentExpression.parent) || ts.isTypeAssertionExpression(currentExpression.parent)) currentExpression = currentExpression.parent;
|
|
40679
|
-
return !ts.isExpressionStatement(currentExpression.parent) && !ts.isVoidExpression(currentExpression.parent);
|
|
40680
|
-
};
|
|
40681
|
-
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) ?? ""));
|
|
40682
|
-
const collectScriptMotionEvidence = (sourceFile, typeChecker, program) => {
|
|
40683
|
-
const evidence = {
|
|
40684
|
-
hasMotionUse: false,
|
|
40685
|
-
hasReducedMotionHandling: false
|
|
40686
|
-
};
|
|
40687
|
-
const visitNode = (node) => {
|
|
40688
|
-
if (ts.isCallExpression(node)) {
|
|
40689
|
-
const calleeEvidence = resolveMotionExpressionEvidence(node.expression, typeChecker, program);
|
|
40690
|
-
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;
|
|
40691
|
-
if (calleeEvidence.isAnimationFunction || isAnimationFunctionCallViaCallOrApply) evidence.hasMotionUse = true;
|
|
40692
|
-
if (calleeEvidence.isReducedMotionHook && isExpressionValueConsumed(node)) evidence.hasReducedMotionHandling = true;
|
|
40693
|
-
}
|
|
40694
|
-
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
40695
|
-
const tagEvidence = ts.isJsxNamespacedName(node.tagName) ? EMPTY_MOTION_EXPRESSION_EVIDENCE : resolveMotionExpressionEvidence(node.tagName, typeChecker, program);
|
|
40696
|
-
if (tagEvidence.isMotionComponent || tagEvidence.isMotionComponentFactory) evidence.hasMotionUse = true;
|
|
40697
|
-
if (tagEvidence.isMotionConfig && jsxElementHasReducedMotionConfiguration(node.attributes, typeChecker)) evidence.hasReducedMotionHandling = true;
|
|
40698
|
-
}
|
|
40699
|
-
ts.forEachChild(node, visitNode);
|
|
40700
|
-
};
|
|
40701
|
-
visitNode(sourceFile);
|
|
40702
|
-
return evidence;
|
|
40703
|
-
};
|
|
40704
|
-
const analyzeReducedMotionSources = (sources) => {
|
|
40705
|
-
if (!sources.some(({ sourceText }) => MOTION_SOURCE_PREFILTER.test(sourceText))) return {
|
|
40706
|
-
hasMotionUse: false,
|
|
40707
|
-
hasReducedMotionHandling: false
|
|
40708
|
-
};
|
|
40709
|
-
const compilerOptions = {
|
|
40710
|
-
allowJs: true,
|
|
40711
|
-
checkJs: false,
|
|
40712
|
-
jsx: ts.JsxEmit.Preserve,
|
|
40713
|
-
module: ts.ModuleKind.ESNext,
|
|
40714
|
-
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
40715
|
-
noEmit: true,
|
|
40716
|
-
noLib: true,
|
|
40717
|
-
noResolve: true,
|
|
40718
|
-
skipLibCheck: true,
|
|
40719
|
-
target: ts.ScriptTarget.Latest
|
|
40720
|
-
};
|
|
40721
|
-
const sourceTextByFileName = new Map(sources.map(({ fileName: sourceFileName, sourceText: content }) => [Path.resolve(sourceFileName), content]));
|
|
40722
|
-
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
40723
|
-
const getDefaultSourceFile = compilerHost.getSourceFile.bind(compilerHost);
|
|
40724
|
-
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);
|
|
40725
|
-
const program = ts.createProgram([...sourceTextByFileName.keys()], compilerOptions, compilerHost);
|
|
40726
|
-
const typeChecker = program.getTypeChecker();
|
|
40727
|
-
const evidence = {
|
|
40728
|
-
hasMotionUse: false,
|
|
40729
|
-
hasReducedMotionHandling: false
|
|
40730
|
-
};
|
|
40731
|
-
for (const sourceFileName of sourceTextByFileName.keys()) {
|
|
40732
|
-
const sourceFile = program.getSourceFile(sourceFileName);
|
|
40733
|
-
if (!sourceFile) continue;
|
|
40734
|
-
const fileEvidence = collectScriptMotionEvidence(sourceFile, typeChecker, program);
|
|
40735
|
-
evidence.hasMotionUse ||= fileEvidence.hasMotionUse;
|
|
40736
|
-
evidence.hasReducedMotionHandling ||= fileEvidence.hasReducedMotionHandling;
|
|
40737
|
-
}
|
|
40738
|
-
return evidence;
|
|
40739
|
-
};
|
|
40740
|
-
const removeCssCommentsAndStrings = (content) => {
|
|
40741
|
-
let sanitizedContent = "";
|
|
40742
|
-
let quote = null;
|
|
40743
|
-
let isInsideComment = false;
|
|
40744
|
-
let isInsideLineComment = false;
|
|
40745
|
-
for (let characterIndex = 0; characterIndex < content.length; characterIndex += 1) {
|
|
40746
|
-
const character = content[characterIndex];
|
|
40747
|
-
const nextCharacter = content[characterIndex + 1];
|
|
40748
|
-
if (isInsideLineComment) {
|
|
40749
|
-
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
40750
|
-
if (character === "\n") isInsideLineComment = false;
|
|
40751
|
-
continue;
|
|
40752
|
-
}
|
|
40753
|
-
if (isInsideComment) {
|
|
40754
|
-
if (character === "*" && nextCharacter === "/") {
|
|
40755
|
-
sanitizedContent += " ";
|
|
40756
|
-
characterIndex += 1;
|
|
40757
|
-
isInsideComment = false;
|
|
40758
|
-
} else sanitizedContent += character === "\n" ? "\n" : " ";
|
|
40759
|
-
continue;
|
|
40760
|
-
}
|
|
40761
|
-
if (quote) {
|
|
40762
|
-
if (character === "\\") {
|
|
40763
|
-
sanitizedContent += " ";
|
|
40764
|
-
characterIndex += 1;
|
|
40765
|
-
continue;
|
|
40766
|
-
}
|
|
40767
|
-
if (character === quote) quote = null;
|
|
40768
|
-
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
40769
|
-
continue;
|
|
40770
|
-
}
|
|
40771
|
-
if (character === "/" && nextCharacter === "*") {
|
|
40772
|
-
sanitizedContent += " ";
|
|
40773
|
-
characterIndex += 1;
|
|
40774
|
-
isInsideComment = true;
|
|
40775
|
-
continue;
|
|
40776
|
-
}
|
|
40777
|
-
if (character === "/" && nextCharacter === "/") {
|
|
40778
|
-
sanitizedContent += " ";
|
|
40779
|
-
characterIndex += 1;
|
|
40780
|
-
isInsideLineComment = true;
|
|
40781
|
-
continue;
|
|
40782
|
-
}
|
|
40783
|
-
if (character === "\"" || character === "'") {
|
|
40784
|
-
sanitizedContent += " ";
|
|
40785
|
-
quote = character;
|
|
40786
|
-
continue;
|
|
40787
|
-
}
|
|
40788
|
-
sanitizedContent += character;
|
|
40789
|
-
}
|
|
40790
|
-
return sanitizedContent;
|
|
40791
|
-
};
|
|
40792
|
-
const findMatchingClosingBrace = (content, openingBraceIndex) => {
|
|
40793
|
-
let depth = 0;
|
|
40794
|
-
for (let characterIndex = openingBraceIndex; characterIndex < content.length; characterIndex += 1) {
|
|
40795
|
-
if (content[characterIndex] === "{") depth += 1;
|
|
40796
|
-
if (content[characterIndex] !== "}") continue;
|
|
40797
|
-
depth -= 1;
|
|
40798
|
-
if (depth === 0) return characterIndex;
|
|
40799
|
-
}
|
|
40800
|
-
return -1;
|
|
40801
|
-
};
|
|
40802
|
-
const hasReducedMotionMediaQuery = (content) => {
|
|
40803
|
-
const sanitizedContent = removeCssCommentsAndStrings(content);
|
|
40804
|
-
REDUCED_MOTION_MEDIA_QUERY_PATTERN.lastIndex = 0;
|
|
40805
|
-
for (const match of sanitizedContent.matchAll(REDUCED_MOTION_MEDIA_QUERY_PATTERN)) {
|
|
40806
|
-
const mediaPrelude = match[1];
|
|
40807
|
-
if (/\bnot\b/i.test(mediaPrelude)) continue;
|
|
40808
|
-
const openingBraceIndex = (match.index ?? 0) + match[0].lastIndexOf("{");
|
|
40809
|
-
const closingBraceIndex = findMatchingClosingBrace(sanitizedContent, openingBraceIndex);
|
|
40810
|
-
if (closingBraceIndex === -1) continue;
|
|
40811
|
-
const body = sanitizedContent.slice(openingBraceIndex + 1, closingBraceIndex);
|
|
40812
|
-
if (CSS_DECLARATION_PATTERN.test(body)) return true;
|
|
40813
|
-
}
|
|
40814
|
-
return false;
|
|
40815
|
-
};
|
|
40816
|
-
const collectProjectMotionEvidence = (rootDirectory) => {
|
|
40817
|
-
const scriptSources = [];
|
|
40818
|
-
let hasReducedMotionHandling = false;
|
|
40436
|
+
const hasReducedMotionHandlingViaFilesystem = (rootDirectory) => {
|
|
40819
40437
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
40820
|
-
|
|
40821
|
-
if (!SCRIPT_FILE_EXTENSIONS.has(extension) && !STYLE_FILE_EXTENSIONS.has(extension)) continue;
|
|
40438
|
+
if (!REDUCED_MOTION_FILE_EXTENSIONS.has(Path.extname(name))) continue;
|
|
40822
40439
|
let content;
|
|
40823
40440
|
try {
|
|
40824
40441
|
content = NFS.readFileSync(absolutePath, "utf-8");
|
|
40825
40442
|
} catch {
|
|
40826
40443
|
continue;
|
|
40827
40444
|
}
|
|
40828
|
-
if (
|
|
40829
|
-
if (hasReducedMotionMediaQuery(content)) hasReducedMotionHandling = true;
|
|
40830
|
-
continue;
|
|
40831
|
-
}
|
|
40832
|
-
scriptSources.push({
|
|
40833
|
-
fileName: absolutePath,
|
|
40834
|
-
sourceText: content
|
|
40835
|
-
});
|
|
40445
|
+
if (REDUCED_MOTION_PATTERN.test(content)) return true;
|
|
40836
40446
|
}
|
|
40837
|
-
|
|
40838
|
-
hasMotionUse: false,
|
|
40839
|
-
hasReducedMotionHandling
|
|
40840
|
-
};
|
|
40841
|
-
const scriptEvidence = analyzeReducedMotionSources(scriptSources);
|
|
40842
|
-
const hasMotionUse = scriptEvidence.hasMotionUse;
|
|
40843
|
-
hasReducedMotionHandling ||= scriptEvidence.hasReducedMotionHandling;
|
|
40844
|
-
return {
|
|
40845
|
-
hasMotionUse,
|
|
40846
|
-
hasReducedMotionHandling
|
|
40847
|
-
};
|
|
40447
|
+
return false;
|
|
40848
40448
|
};
|
|
40849
40449
|
const checkReducedMotion = (rootDirectory) => {
|
|
40850
40450
|
const packageJsonPath = Path.join(rootDirectory, "package.json");
|
|
40851
40451
|
if (!isFile(packageJsonPath)) return [];
|
|
40452
|
+
let hasMotionLibrary = false;
|
|
40852
40453
|
try {
|
|
40853
40454
|
const packageJson = readPackageJson$1(packageJsonPath);
|
|
40854
40455
|
const allDependencies = {
|
|
40855
40456
|
...packageJson.dependencies,
|
|
40856
40457
|
...packageJson.devDependencies
|
|
40857
40458
|
};
|
|
40858
|
-
|
|
40459
|
+
hasMotionLibrary = Object.keys(allDependencies).some((packageName) => MOTION_LIBRARY_PACKAGES.has(packageName));
|
|
40859
40460
|
} catch {
|
|
40860
40461
|
return [];
|
|
40861
40462
|
}
|
|
40862
|
-
|
|
40863
|
-
|
|
40463
|
+
if (!hasMotionLibrary) return [];
|
|
40464
|
+
const result = spawnSync("git", [
|
|
40465
|
+
"grep",
|
|
40466
|
+
"--untracked",
|
|
40467
|
+
"-lE",
|
|
40468
|
+
REDUCED_MOTION_GREP_PATTERN,
|
|
40469
|
+
"--",
|
|
40470
|
+
...REDUCED_MOTION_FILE_GLOBS
|
|
40471
|
+
], {
|
|
40472
|
+
cwd: rootDirectory,
|
|
40473
|
+
encoding: "utf-8",
|
|
40474
|
+
stdio: [
|
|
40475
|
+
"ignore",
|
|
40476
|
+
"pipe",
|
|
40477
|
+
"pipe"
|
|
40478
|
+
]
|
|
40479
|
+
});
|
|
40480
|
+
if (!(!result.error && (result.status === 0 || result.status === GIT_GREP_NO_MATCH_STATUS))) return hasReducedMotionHandlingViaFilesystem(rootDirectory) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
40481
|
+
return result.status === 0 && result.stdout.split("\n").some((filePath) => filePath.length > 0 && !hasIgnoredPathSegment(filePath)) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
40864
40482
|
};
|
|
40865
40483
|
const buildSecurityScanDiagnostic = (finding, entry, relativePath) => ({
|
|
40866
40484
|
filePath: relativePath,
|
|
@@ -43479,12 +43097,23 @@ const REACT_USE_BINDING_RESOLUTION = {
|
|
|
43479
43097
|
isReactUseBinding: true,
|
|
43480
43098
|
isReactNamespaceBinding: false
|
|
43481
43099
|
};
|
|
43100
|
+
const getScriptKind$2 = (filename) => {
|
|
43101
|
+
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
43102
|
+
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
43103
|
+
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
43104
|
+
return ts.ScriptKind.JS;
|
|
43105
|
+
};
|
|
43482
43106
|
const getUtf16Offset$1 = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
43107
|
+
const unwrapExpression = (expression) => {
|
|
43108
|
+
let currentExpression = expression;
|
|
43109
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
43110
|
+
return currentExpression;
|
|
43111
|
+
};
|
|
43483
43112
|
const getStaticPropertyName = (node) => {
|
|
43484
43113
|
if (!node) return null;
|
|
43485
43114
|
if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node)) return node.text;
|
|
43486
43115
|
if (ts.isComputedPropertyName(node)) {
|
|
43487
|
-
const expression =
|
|
43116
|
+
const expression = unwrapExpression(node.expression);
|
|
43488
43117
|
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
|
|
43489
43118
|
}
|
|
43490
43119
|
return null;
|
|
@@ -43513,7 +43142,7 @@ const isReactUseObjectBindingElement = (bindingElement) => {
|
|
|
43513
43142
|
return getStaticPropertyName(bindingElement.propertyName) === USE_IDENTIFIER;
|
|
43514
43143
|
};
|
|
43515
43144
|
const isReactRequireCall = (expression) => {
|
|
43516
|
-
const unwrappedExpression =
|
|
43145
|
+
const unwrappedExpression = unwrapExpression(expression);
|
|
43517
43146
|
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;
|
|
43518
43147
|
};
|
|
43519
43148
|
const getModuleSource = (node) => {
|
|
@@ -43615,7 +43244,7 @@ const isIdentifierShadowedByLocalBinding = (identifier, sourceFile) => {
|
|
|
43615
43244
|
return false;
|
|
43616
43245
|
};
|
|
43617
43246
|
const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
43618
|
-
const unwrappedExpression =
|
|
43247
|
+
const unwrappedExpression = unwrapExpression(expression);
|
|
43619
43248
|
if (isReactRequireCall(unwrappedExpression)) return true;
|
|
43620
43249
|
if (!ts.isIdentifier(unwrappedExpression)) return false;
|
|
43621
43250
|
if (reactImportBindings.namespaceNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
@@ -43623,7 +43252,7 @@ const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile,
|
|
|
43623
43252
|
};
|
|
43624
43253
|
const isReactUseExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
43625
43254
|
if (!expression) return false;
|
|
43626
|
-
const unwrappedExpression =
|
|
43255
|
+
const unwrappedExpression = unwrapExpression(expression);
|
|
43627
43256
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
43628
43257
|
if (reactImportBindings.useImportNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
43629
43258
|
if (unwrappedExpression.text === USE_IDENTIFIER) return false;
|
|
@@ -43723,7 +43352,7 @@ const findUseCallIdentifier = (sourceFile, useOffset) => {
|
|
|
43723
43352
|
return matchedIdentifier;
|
|
43724
43353
|
};
|
|
43725
43354
|
const resolveUseCallBinding = (sourceText, filename, utf8Offset) => {
|
|
43726
|
-
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true,
|
|
43355
|
+
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true, getScriptKind$2(filename));
|
|
43727
43356
|
const useIdentifier = findUseCallIdentifier(sourceFile, getUtf16Offset$1(sourceText, utf8Offset));
|
|
43728
43357
|
if (!useIdentifier) return null;
|
|
43729
43358
|
return resolveIdentifierBinding(useIdentifier, collectReactImportBindings(sourceFile), sourceFile);
|
|
@@ -43759,6 +43388,12 @@ const WORKLET_ACCEPTING_CALLEES = new Set([
|
|
|
43759
43388
|
"executeOnUIRuntimeSync"
|
|
43760
43389
|
]);
|
|
43761
43390
|
const GESTURE_ROOT_IDENTIFIER = "Gesture";
|
|
43391
|
+
const getScriptKind$1 = (filename) => {
|
|
43392
|
+
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
43393
|
+
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
43394
|
+
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
43395
|
+
return ts.ScriptKind.JS;
|
|
43396
|
+
};
|
|
43762
43397
|
const getUtf16Offset = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
43763
43398
|
const hasWorkletDirective = (node) => {
|
|
43764
43399
|
if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) return false;
|
|
@@ -43830,11 +43465,17 @@ const shouldSuppressCompilerFindingInWorklet = (diagnostic, project, rootDirecto
|
|
|
43830
43465
|
} catch {
|
|
43831
43466
|
return false;
|
|
43832
43467
|
}
|
|
43833
|
-
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true,
|
|
43468
|
+
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind$1(absolutePath)), getUtf16Offset(sourceText, primaryLabel.span.offset));
|
|
43834
43469
|
};
|
|
43835
43470
|
const MANUAL_MEMOIZATION_PLUGIN = "react-doctor";
|
|
43836
43471
|
const MANUAL_MEMOIZATION_RULE = "react-compiler-no-manual-memoization";
|
|
43837
43472
|
const REACT_COMPILER_PLUGIN = "react-hooks-js";
|
|
43473
|
+
const getScriptKind = (filename) => {
|
|
43474
|
+
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
43475
|
+
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
43476
|
+
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
43477
|
+
return ts.ScriptKind.JS;
|
|
43478
|
+
};
|
|
43838
43479
|
const isManualMemoizationDiagnostic = (diagnostic) => diagnostic.plugin === MANUAL_MEMOIZATION_PLUGIN && diagnostic.rule === MANUAL_MEMOIZATION_RULE;
|
|
43839
43480
|
const nodeLineRange = (sourceFile, node) => ({
|
|
43840
43481
|
startLine: sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1,
|
|
@@ -43896,7 +43537,7 @@ const suppressMemoizationInBailedOutFunctions = (diagnostics, rootDirectory) =>
|
|
|
43896
43537
|
try {
|
|
43897
43538
|
const buffer = NFS.readFileSync(absolutePath);
|
|
43898
43539
|
parsed = {
|
|
43899
|
-
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true,
|
|
43540
|
+
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true, getScriptKind(absolutePath)),
|
|
43900
43541
|
buffer
|
|
43901
43542
|
};
|
|
43902
43543
|
} catch {
|
|
@@ -46511,9 +46152,7 @@ const toJsonReportDiagnostic = (diagnostic, projectRoot, reportRoot) => {
|
|
|
46511
46152
|
line: diagnostic.line,
|
|
46512
46153
|
column: diagnostic.column,
|
|
46513
46154
|
plugin: diagnostic.plugin,
|
|
46514
|
-
rule: diagnostic.rule
|
|
46515
|
-
severity: diagnostic.severity,
|
|
46516
|
-
message: diagnostic.message
|
|
46155
|
+
rule: diagnostic.rule
|
|
46517
46156
|
}),
|
|
46518
46157
|
normalizedFilePath,
|
|
46519
46158
|
category: ruleIdentity.category,
|
|
@@ -47135,7 +46774,7 @@ const makeNoopConsole = () => ({
|
|
|
47135
46774
|
});
|
|
47136
46775
|
//#endregion
|
|
47137
46776
|
//#region src/cli/utils/version.ts
|
|
47138
|
-
const VERSION = "0.7.7-dev.
|
|
46777
|
+
const VERSION = "0.7.7-dev.4fce1c1";
|
|
47139
46778
|
//#endregion
|
|
47140
46779
|
//#region src/cli/utils/json-mode.ts
|
|
47141
46780
|
let context = null;
|
|
@@ -47504,13 +47143,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47504
47143
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47505
47144
|
* standard `SENTRY_RELEASE` override.
|
|
47506
47145
|
*/
|
|
47507
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.7-dev.
|
|
47146
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.7-dev.4fce1c1`;
|
|
47508
47147
|
/**
|
|
47509
47148
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47510
47149
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47511
47150
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47512
47151
|
*/
|
|
47513
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.7-dev.
|
|
47152
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.7-dev.4fce1c1") ? "development" : "production");
|
|
47514
47153
|
/**
|
|
47515
47154
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47516
47155
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -60027,25 +59666,14 @@ const buildOutcomeAttributes = (input) => {
|
|
|
60027
59666
|
const largestRuleBucket = buildRuleBlastRadii(result.diagnostics)[0] ?? null;
|
|
60028
59667
|
let diagnosticsInTestFiles = 0;
|
|
60029
59668
|
let diagnosticsInStoryFiles = 0;
|
|
60030
|
-
const diagnosticSiteCounts = /* @__PURE__ */ new Map();
|
|
60031
59669
|
const findingsPerFixGroup = /* @__PURE__ */ new Map();
|
|
60032
59670
|
for (const diagnostic of result.diagnostics) {
|
|
60033
59671
|
if (diagnostic.fileContext === "test") diagnosticsInTestFiles += 1;
|
|
60034
59672
|
if (diagnostic.fileContext === "story") diagnosticsInStoryFiles += 1;
|
|
60035
|
-
const diagnosticSite = JSON.stringify([
|
|
60036
|
-
diagnostic.filePath,
|
|
60037
|
-
diagnostic.line,
|
|
60038
|
-
diagnostic.column,
|
|
60039
|
-
diagnostic.plugin,
|
|
60040
|
-
diagnostic.rule
|
|
60041
|
-
]);
|
|
60042
|
-
diagnosticSiteCounts.set(diagnosticSite, (diagnosticSiteCounts.get(diagnosticSite) ?? 0) + 1);
|
|
60043
59673
|
if (diagnostic.fixGroupId) findingsPerFixGroup.set(diagnostic.fixGroupId, (findingsPerFixGroup.get(diagnostic.fixGroupId) ?? 0) + 1);
|
|
60044
59674
|
}
|
|
60045
59675
|
let fixGroupedFindings = 0;
|
|
60046
59676
|
for (const count of findingsPerFixGroup.values()) fixGroupedFindings += count;
|
|
60047
|
-
let sameSiteOccurrences = 0;
|
|
60048
|
-
for (const count of diagnosticSiteCounts.values()) sameSiteOccurrences += Math.max(0, count - 1);
|
|
60049
59677
|
const categoryRollup = {};
|
|
60050
59678
|
for (const [category, count] of countByCategory) categoryRollup[`category.${toCategoryKey(category)}`] = count;
|
|
60051
59679
|
const suppressionRollup = {};
|
|
@@ -60082,7 +59710,6 @@ const buildOutcomeAttributes = (input) => {
|
|
|
60082
59710
|
inStoryFiles: diagnosticsInStoryFiles,
|
|
60083
59711
|
distinctRules: countByRule.size,
|
|
60084
59712
|
topRule,
|
|
60085
|
-
sameSiteOccurrences,
|
|
60086
59713
|
fixGroups: findingsPerFixGroup.size,
|
|
60087
59714
|
fixGroupedFindings,
|
|
60088
59715
|
...categoryRollup,
|
|
@@ -65788,4 +65415,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65788
65415
|
export {};
|
|
65789
65416
|
|
|
65790
65417
|
//# sourceMappingURL=cli.js.map
|
|
65791
|
-
//# debugId=
|
|
65418
|
+
//# debugId=50d648e9-77ea-5f0f-87a2-6d2a2461613e
|