react-doctor 0.9.0 → 0.9.1-dev.1aa6b12
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/README.md +2 -0
- package/dist/cli.js +1136 -130
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1129 -124
- package/dist/lsp.js +1132 -126
- package/package.json +7 -6
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]="f34e66dd-4b16-53f5-a3af-9844fbc71772")}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";
|
|
@@ -11,6 +11,7 @@ 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
12
|
import * as Crypto from "node:crypto";
|
|
13
13
|
import crypto, { createHash, randomUUID } from "node:crypto";
|
|
14
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
14
15
|
import ts from "typescript";
|
|
15
16
|
import * as OS from "node:os";
|
|
16
17
|
import os, { tmpdir } from "node:os";
|
|
@@ -64616,7 +64617,8 @@ var AmbiguousProjectError = class extends Error {
|
|
|
64616
64617
|
}
|
|
64617
64618
|
};
|
|
64618
64619
|
const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
|
|
64619
|
-
const
|
|
64620
|
+
const HTML_FILE_PATTERN = /\.html$/i;
|
|
64621
|
+
const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
64620
64622
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
64621
64623
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
64622
64624
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
@@ -64994,7 +64996,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
64994
64996
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
64995
64997
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
64996
64998
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
64997
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
64999
|
+
const CORE_PACKAGE_VERSION = "0.9.1";
|
|
64998
65000
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
64999
65001
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
65000
65002
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -65239,7 +65241,7 @@ const findMonorepoRoot = (startDirectory) => {
|
|
|
65239
65241
|
*/
|
|
65240
65242
|
const isProjectBoundary = (directory) => NFS.existsSync(Path.join(directory, ".git")) || isMonorepoRoot(directory);
|
|
65241
65243
|
const TSCONFIG_FILENAME = "tsconfig.json";
|
|
65242
|
-
const
|
|
65244
|
+
const isLocalModuleSpecifier = (moduleSpecifier) => moduleSpecifier === "." || moduleSpecifier === ".." || moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../") || Path.isAbsolute(moduleSpecifier);
|
|
65243
65245
|
const ensureJsonExtension = (filePath) => Path.extname(filePath) === "" ? `${filePath}.json` : filePath;
|
|
65244
65246
|
const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
65245
65247
|
const requireFromConfig = createRequire(Path.join(fromConfigDirectory, "tsconfig.json"));
|
|
@@ -65256,7 +65258,12 @@ const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
|
65256
65258
|
return null;
|
|
65257
65259
|
};
|
|
65258
65260
|
const resolveExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
65259
|
-
if (
|
|
65261
|
+
if (isLocalModuleSpecifier(extendsValue)) {
|
|
65262
|
+
const resolvedPath = Path.resolve(fromConfigDirectory, extendsValue);
|
|
65263
|
+
if (isFile(resolvedPath)) return resolvedPath;
|
|
65264
|
+
const directoryConfigPath = Path.join(resolvedPath, TSCONFIG_FILENAME);
|
|
65265
|
+
return isFile(directoryConfigPath) ? directoryConfigPath : ensureJsonExtension(resolvedPath);
|
|
65266
|
+
}
|
|
65260
65267
|
return resolvePackageExtendsPath(extendsValue, fromConfigDirectory);
|
|
65261
65268
|
};
|
|
65262
65269
|
const normalizeCompilerOptions = (compilerOptions) => {
|
|
@@ -65379,6 +65386,7 @@ const frameworkMergeRank = (framework) => {
|
|
|
65379
65386
|
return MOBILE_FRAMEWORKS.has(framework) ? 2 : 1;
|
|
65380
65387
|
};
|
|
65381
65388
|
const REACT_COMPILER_LINT_PACKAGES = new Set(["eslint-plugin-react-compiler"]);
|
|
65389
|
+
const REACT_COMPILER_RUNTIME_PACKAGES = new Set(["react-compiler-runtime"]);
|
|
65382
65390
|
const NEXT_CONFIG_FILENAMES = [
|
|
65383
65391
|
"next.config.js",
|
|
65384
65392
|
"next.config.mjs",
|
|
@@ -65449,6 +65457,15 @@ const REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS = [
|
|
|
65449
65457
|
".cts",
|
|
65450
65458
|
".json"
|
|
65451
65459
|
];
|
|
65460
|
+
const REACT_COMPILER_CONFIG_RESOLVER = new ResolverFactory({
|
|
65461
|
+
conditionNames: [
|
|
65462
|
+
"import",
|
|
65463
|
+
"require",
|
|
65464
|
+
"node",
|
|
65465
|
+
"default"
|
|
65466
|
+
],
|
|
65467
|
+
extensions: REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS
|
|
65468
|
+
});
|
|
65452
65469
|
const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
|
|
65453
65470
|
const hasCompilerPackage = (packageJson, compilerPackages) => {
|
|
65454
65471
|
const allDependencies = {
|
|
@@ -65472,6 +65489,18 @@ const hasCompilerPackageInAncestors = (directory, compilerPackages) => {
|
|
|
65472
65489
|
return false;
|
|
65473
65490
|
};
|
|
65474
65491
|
const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
65492
|
+
if (!isLocalModuleSpecifier(moduleSpecifier)) {
|
|
65493
|
+
try {
|
|
65494
|
+
const resolvedPath = REACT_COMPILER_CONFIG_RESOLVER.resolveFileSync(fromFilePath, moduleSpecifier).path;
|
|
65495
|
+
if (resolvedPath && isFile(resolvedPath)) return resolvedPath;
|
|
65496
|
+
} catch {}
|
|
65497
|
+
try {
|
|
65498
|
+
const resolvedPath = createRequire(fromFilePath).resolve(moduleSpecifier);
|
|
65499
|
+
return isFile(resolvedPath) ? resolvedPath : null;
|
|
65500
|
+
} catch {
|
|
65501
|
+
return null;
|
|
65502
|
+
}
|
|
65503
|
+
}
|
|
65475
65504
|
const unresolvedPath = Path.resolve(Path.dirname(fromFilePath), moduleSpecifier);
|
|
65476
65505
|
const extension = Path.extname(unresolvedPath);
|
|
65477
65506
|
return (extension ? [unresolvedPath, ...REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS.map((sourceExtension) => `${unresolvedPath.slice(0, -extension.length)}${sourceExtension}`)] : [
|
|
@@ -65481,10 +65510,10 @@ const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
|
65481
65510
|
]).find(isFile) ?? null;
|
|
65482
65511
|
};
|
|
65483
65512
|
const parseConfigSourceFile = (filePath, content) => filePath.endsWith(".json") || Path.basename(filePath) === ".babelrc" ? ts.parseJsonText(filePath, content) : ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
65484
|
-
const getStaticPropertyName$
|
|
65513
|
+
const getStaticPropertyName$2 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
|
|
65485
65514
|
const isCommonJsConfigExportAssignment = (node, sourceFile) => ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && (node.left.getText(sourceFile) === "module.exports" || node.left.getText(sourceFile) === "exports.default");
|
|
65486
65515
|
const hasExportModifier = (node) => ts.canHaveModifiers(node) && Boolean(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
|
|
65487
|
-
const getRequireModuleSpecifier = (expression) => {
|
|
65516
|
+
const getRequireModuleSpecifier$1 = (expression) => {
|
|
65488
65517
|
if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "require" || expression.arguments.length !== 1) return null;
|
|
65489
65518
|
const moduleSpecifier = expression.arguments[0];
|
|
65490
65519
|
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
@@ -65497,7 +65526,7 @@ const hasTopLevelValueBinding = (sourceFile, bindingName) => sourceFile.statemen
|
|
|
65497
65526
|
const namedBindings = importClause?.namedBindings;
|
|
65498
65527
|
return namedBindings ? ts.isNamespaceImport(namedBindings) ? namedBindings.name.text === bindingName : namedBindings.elements.some((element) => element.name.text === bindingName) : false;
|
|
65499
65528
|
}
|
|
65500
|
-
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) =>
|
|
65529
|
+
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContainsIdentifier(declaration.name, bindingName));
|
|
65501
65530
|
return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === bindingName;
|
|
65502
65531
|
});
|
|
65503
65532
|
const getImportBinding = (sourceFile, bindingName) => {
|
|
@@ -65528,24 +65557,24 @@ const getImportBinding = (sourceFile, bindingName) => {
|
|
|
65528
65557
|
for (const declaration of statement.declarationList.declarations) {
|
|
65529
65558
|
if (!declaration.initializer) continue;
|
|
65530
65559
|
if (ts.isIdentifier(declaration.name) && declaration.name.text === bindingName) {
|
|
65531
|
-
const directModuleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
65560
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
65532
65561
|
if (directModuleSpecifier) return {
|
|
65533
65562
|
moduleSpecifier: directModuleSpecifier,
|
|
65534
65563
|
exportName: "default",
|
|
65535
65564
|
isNamespace: true
|
|
65536
65565
|
};
|
|
65537
|
-
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier(declaration.initializer.expression) !== null) return {
|
|
65538
|
-
moduleSpecifier: getRequireModuleSpecifier(declaration.initializer.expression) ?? "",
|
|
65566
|
+
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier$1(declaration.initializer.expression) !== null) return {
|
|
65567
|
+
moduleSpecifier: getRequireModuleSpecifier$1(declaration.initializer.expression) ?? "",
|
|
65539
65568
|
exportName: declaration.initializer.name.text,
|
|
65540
65569
|
isNamespace: false
|
|
65541
65570
|
};
|
|
65542
65571
|
}
|
|
65543
65572
|
if (!ts.isObjectBindingPattern(declaration.name)) continue;
|
|
65544
65573
|
const bindingElement = declaration.name.elements.find((element) => ts.isIdentifier(element.name) && element.name.text === bindingName);
|
|
65545
|
-
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
65574
|
+
const moduleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
65546
65575
|
if (bindingElement && moduleSpecifier) return {
|
|
65547
65576
|
moduleSpecifier,
|
|
65548
|
-
exportName: bindingElement.propertyName ? getStaticPropertyName$
|
|
65577
|
+
exportName: bindingElement.propertyName ? getStaticPropertyName$2(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
|
|
65549
65578
|
isNamespace: false
|
|
65550
65579
|
};
|
|
65551
65580
|
}
|
|
@@ -65598,6 +65627,48 @@ const getScopedConfigBinding = (identifier) => {
|
|
|
65598
65627
|
};
|
|
65599
65628
|
};
|
|
65600
65629
|
const isCompilerTransformModule = (moduleSpecifier, exportName) => moduleSpecifier === "babel-plugin-react-compiler" && exportName === "default" || moduleSpecifier === "@vitejs/plugin-react" && exportName === "reactCompilerPreset";
|
|
65630
|
+
const NODE_MODULE_SPECIFIERS = new Set(["module", "node:module"]);
|
|
65631
|
+
const isConstantVariableInitializer = (node) => ts.isExpression(node) && ts.isVariableDeclaration(node.parent) && ts.isVariableDeclarationList(node.parent.parent) && Boolean(node.parent.parent.flags & ts.NodeFlags.Const);
|
|
65632
|
+
const isNodeCreateRequireCall = (node, analysis) => {
|
|
65633
|
+
if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isTypeAssertionExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isAwaitExpression(node)) return isNodeCreateRequireCall(node.expression, analysis);
|
|
65634
|
+
if (!ts.isCallExpression(node)) return false;
|
|
65635
|
+
const target = node.expression;
|
|
65636
|
+
if (ts.isIdentifier(target)) {
|
|
65637
|
+
if (analysis.localBindings.has(target.text) || getScopedConfigBinding(target).wasFound) return false;
|
|
65638
|
+
const importBinding = getImportBinding(analysis.sourceFile, target.text);
|
|
65639
|
+
return Boolean(importBinding && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier) && importBinding.exportName === "createRequire");
|
|
65640
|
+
}
|
|
65641
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return false;
|
|
65642
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "createRequire") return false;
|
|
65643
|
+
const createRequireReceiver = target.expression;
|
|
65644
|
+
if (ts.isCallExpression(createRequireReceiver)) {
|
|
65645
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(createRequireReceiver);
|
|
65646
|
+
if (requiredModuleSpecifier === null || !NODE_MODULE_SPECIFIERS.has(requiredModuleSpecifier) || !ts.isIdentifier(createRequireReceiver.expression)) return false;
|
|
65647
|
+
const requireIdentifier = createRequireReceiver.expression;
|
|
65648
|
+
return !analysis.localBindings.has(requireIdentifier.text) && !getScopedConfigBinding(requireIdentifier).wasFound && !hasTopLevelValueBinding(analysis.sourceFile, requireIdentifier.text);
|
|
65649
|
+
}
|
|
65650
|
+
if (!ts.isIdentifier(createRequireReceiver)) return false;
|
|
65651
|
+
if (analysis.localBindings.has(createRequireReceiver.text) || getScopedConfigBinding(createRequireReceiver).wasFound) return false;
|
|
65652
|
+
const importBinding = getImportBinding(analysis.sourceFile, createRequireReceiver.text);
|
|
65653
|
+
return Boolean(importBinding?.isNamespace && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier));
|
|
65654
|
+
};
|
|
65655
|
+
const getNodeRequireResolveModuleSpecifier = (callExpression, analysis) => {
|
|
65656
|
+
const [moduleSpecifierNode] = callExpression.arguments;
|
|
65657
|
+
if (!moduleSpecifierNode || !ts.isStringLiteralLike(moduleSpecifierNode)) return null;
|
|
65658
|
+
const target = callExpression.expression;
|
|
65659
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
65660
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "resolve") return null;
|
|
65661
|
+
if (isNodeCreateRequireCall(target.expression, analysis)) return moduleSpecifierNode.text;
|
|
65662
|
+
if (!ts.isIdentifier(target.expression)) return null;
|
|
65663
|
+
const resolverIdentifier = target.expression;
|
|
65664
|
+
if (analysis.localBindings.has(resolverIdentifier.text)) return null;
|
|
65665
|
+
const scopedBinding = getScopedConfigBinding(resolverIdentifier);
|
|
65666
|
+
const topLevelBinding = scopedBinding.wasFound ? null : getTopLevelBinding(analysis.sourceFile, resolverIdentifier.text);
|
|
65667
|
+
const resolverInitializer = scopedBinding.wasFound ? scopedBinding.initializer : topLevelBinding;
|
|
65668
|
+
if (resolverInitializer === null && !scopedBinding.wasFound && resolverIdentifier.text === "require" && !hasTopLevelValueBinding(analysis.sourceFile, resolverIdentifier.text) && getImportBinding(analysis.sourceFile, resolverIdentifier.text) === null) return moduleSpecifierNode.text;
|
|
65669
|
+
if (!resolverInitializer || !isConstantVariableInitializer(resolverInitializer) || !isNodeCreateRequireCall(resolverInitializer, analysis)) return null;
|
|
65670
|
+
return moduleSpecifierNode.text;
|
|
65671
|
+
};
|
|
65601
65672
|
const getAssignedPropertyInitializer = (identifier, propertyName) => {
|
|
65602
65673
|
let bindingScope = null;
|
|
65603
65674
|
let currentNode = identifier;
|
|
@@ -65706,7 +65777,7 @@ const getReactCompilerFlagState = (expression, analysis) => {
|
|
|
65706
65777
|
}
|
|
65707
65778
|
if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
|
|
65708
65779
|
for (const property of [...unwrappedExpression.properties].reverse()) {
|
|
65709
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
65780
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
|
|
65710
65781
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
|
|
65711
65782
|
if (ts.isSpreadAssignment(property)) {
|
|
65712
65783
|
const spreadState = getReactCompilerFlagState(property.expression, analysis);
|
|
@@ -65732,8 +65803,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
65732
65803
|
}
|
|
65733
65804
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
|
|
65734
65805
|
for (const property of [...resolvedExpression.properties].reverse()) {
|
|
65735
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
65736
|
-
if (ts.isMethodDeclaration(property) && getStaticPropertyName$
|
|
65806
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return property.initializer;
|
|
65807
|
+
if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return property;
|
|
65737
65808
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return property.name;
|
|
65738
65809
|
if (ts.isSpreadAssignment(property)) {
|
|
65739
65810
|
const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
|
|
@@ -65764,7 +65835,7 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
65764
65835
|
return resolvedExpression.properties.some((property) => {
|
|
65765
65836
|
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
|
|
65766
65837
|
if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
|
|
65767
|
-
const staticPropertyName = getStaticPropertyName$
|
|
65838
|
+
const staticPropertyName = getStaticPropertyName$2(property.name);
|
|
65768
65839
|
return staticPropertyName === null || staticPropertyName === propertyName;
|
|
65769
65840
|
}
|
|
65770
65841
|
return false;
|
|
@@ -65783,7 +65854,7 @@ const getExportedConfigNodes = (sourceFile, exportName) => {
|
|
|
65783
65854
|
continue;
|
|
65784
65855
|
}
|
|
65785
65856
|
if (ts.isExpressionStatement(statement) && isCommonJsConfigExportAssignment(statement.expression, sourceFile) && exportName !== "default" && ts.isObjectLiteralExpression(statement.expression.right)) for (const property of [...statement.expression.right.properties].reverse()) {
|
|
65786
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
65857
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === exportName) {
|
|
65787
65858
|
exportedNodes.push(property.initializer);
|
|
65788
65859
|
break;
|
|
65789
65860
|
}
|
|
@@ -65881,6 +65952,11 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
|
|
|
65881
65952
|
visitReturns(functionNode.body);
|
|
65882
65953
|
return hasCompiler;
|
|
65883
65954
|
};
|
|
65955
|
+
const analyzeImportedConfig = ({ analysis, moduleSpecifier, exportName, allowCompilerTransform, argumentsList }) => {
|
|
65956
|
+
const importedFilePath = resolveImportedConfigFile(analysis.filePath, moduleSpecifier);
|
|
65957
|
+
if (!importedFilePath) return null;
|
|
65958
|
+
return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList);
|
|
65959
|
+
};
|
|
65884
65960
|
const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, isCompilerTransformCollection, excludedPropertyNames) => {
|
|
65885
65961
|
const assignedReactCompiler = getAssignedPropertyInitializer(identifier, "reactCompiler");
|
|
65886
65962
|
if (assignedReactCompiler.initializer && !isStaticallyDisabledConfigExpression(assignedReactCompiler.initializer, analysis)) return true;
|
|
@@ -65901,30 +65977,62 @@ const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, i
|
|
|
65901
65977
|
const importBinding = getImportBinding(analysis.sourceFile, identifier.text);
|
|
65902
65978
|
if (importBinding) {
|
|
65903
65979
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
|
|
65904
|
-
|
|
65905
|
-
|
|
65906
|
-
|
|
65980
|
+
return Boolean(analyzeImportedConfig({
|
|
65981
|
+
analysis,
|
|
65982
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
65983
|
+
exportName: importBinding.exportName,
|
|
65984
|
+
allowCompilerTransform
|
|
65985
|
+
}));
|
|
65907
65986
|
}
|
|
65908
65987
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, identifier.text);
|
|
65909
65988
|
return Boolean(topLevelBinding && analyzeConfigNode(topLevelBinding, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
65910
65989
|
};
|
|
65911
65990
|
const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransform) => {
|
|
65912
65991
|
const target = callExpression.expression;
|
|
65992
|
+
const callableRequiredModuleSpecifier = getRequireModuleSpecifier$1(target);
|
|
65993
|
+
if (callableRequiredModuleSpecifier !== null) {
|
|
65994
|
+
if (ts.isCallExpression(target) && ts.isIdentifier(target.expression) && (analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
65995
|
+
if (allowCompilerTransform && isCompilerTransformModule(callableRequiredModuleSpecifier, "default")) return true;
|
|
65996
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
65997
|
+
analysis,
|
|
65998
|
+
moduleSpecifier: callableRequiredModuleSpecifier,
|
|
65999
|
+
exportName: "default",
|
|
66000
|
+
allowCompilerTransform,
|
|
66001
|
+
argumentsList: callExpression.arguments
|
|
66002
|
+
});
|
|
66003
|
+
if (isLocalModuleSpecifier(callableRequiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66004
|
+
return null;
|
|
66005
|
+
}
|
|
65913
66006
|
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
65914
66007
|
const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
|
|
65915
66008
|
if (propertyName === null) return null;
|
|
65916
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(target.expression);
|
|
66009
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
|
|
65917
66010
|
if (requiredModuleSpecifier !== null) {
|
|
65918
|
-
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
65919
|
-
if (
|
|
65920
|
-
const
|
|
65921
|
-
|
|
66011
|
+
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (analysis.localBindings.has(target.expression.expression.text) || getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66012
|
+
if (allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, propertyName)) return true;
|
|
66013
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66014
|
+
analysis,
|
|
66015
|
+
moduleSpecifier: requiredModuleSpecifier,
|
|
66016
|
+
exportName: propertyName,
|
|
66017
|
+
allowCompilerTransform,
|
|
66018
|
+
argumentsList: callExpression.arguments
|
|
66019
|
+
});
|
|
66020
|
+
if (isLocalModuleSpecifier(requiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66021
|
+
return null;
|
|
65922
66022
|
}
|
|
65923
66023
|
if (!ts.isIdentifier(target.expression)) return null;
|
|
65924
|
-
const importBinding = getImportBinding(analysis.sourceFile, target.expression.text);
|
|
65925
|
-
if (importBinding?.isNamespace
|
|
65926
|
-
|
|
65927
|
-
|
|
66024
|
+
const importBinding = analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound ? null : getImportBinding(analysis.sourceFile, target.expression.text);
|
|
66025
|
+
if (importBinding?.isNamespace) {
|
|
66026
|
+
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, propertyName)) return true;
|
|
66027
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66028
|
+
analysis,
|
|
66029
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66030
|
+
exportName: propertyName,
|
|
66031
|
+
allowCompilerTransform,
|
|
66032
|
+
argumentsList: callExpression.arguments
|
|
66033
|
+
});
|
|
66034
|
+
if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66035
|
+
return null;
|
|
65928
66036
|
}
|
|
65929
66037
|
const selectedProperty = getSelectedObjectProperty(target.expression, propertyName, analysis);
|
|
65930
66038
|
if (selectedProperty === null) return null;
|
|
@@ -65942,25 +66050,29 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65942
66050
|
const reactCompilerFlagState = excludedPropertyNames?.has("reactCompiler") ? null : getReactCompilerFlagState(node, analysis);
|
|
65943
66051
|
if (reactCompilerFlagState?.isEnabled) return true;
|
|
65944
66052
|
for (const [propertyIndex, property] of node.properties.entries()) if (ts.isPropertyAssignment(property)) {
|
|
65945
|
-
const propertyName = getStaticPropertyName$
|
|
66053
|
+
const propertyName = getStaticPropertyName$2(property.name);
|
|
65946
66054
|
if (propertyName && excludedPropertyNames?.has(propertyName)) continue;
|
|
65947
66055
|
if (propertyName === "reactCompiler") continue;
|
|
65948
|
-
if ((propertyName === "plugins" || propertyName === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, propertyName, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$
|
|
66056
|
+
if ((propertyName === "plugins" || propertyName === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, propertyName, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$2(laterProperty.name) === propertyName)) continue;
|
|
65949
66057
|
const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
|
|
65950
|
-
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)
|
|
65951
|
-
|
|
65952
|
-
|
|
66058
|
+
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)) {
|
|
66059
|
+
if (analyzeImportedConfig({
|
|
66060
|
+
analysis,
|
|
66061
|
+
moduleSpecifier: property.initializer.text,
|
|
66062
|
+
exportName: "default",
|
|
66063
|
+
allowCompilerTransform: false
|
|
66064
|
+
})) return true;
|
|
65953
66065
|
}
|
|
65954
66066
|
if (analyzeConfigNode(property.initializer, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
65955
66067
|
} else if (ts.isShorthandPropertyAssignment(property)) {
|
|
65956
66068
|
if (excludedPropertyNames?.has(property.name.text)) continue;
|
|
65957
66069
|
if (property.name.text === "reactCompiler") continue;
|
|
65958
|
-
if ((property.name.text === "plugins" || property.name.text === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, property.name.text, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$
|
|
66070
|
+
if ((property.name.text === "plugins" || property.name.text === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, property.name.text, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$2(laterProperty.name) === property.name.text)) continue;
|
|
65959
66071
|
const propertyAllowsCompilerTransform = property.name.text === "plugins" || property.name.text === "presets";
|
|
65960
66072
|
if (analyzeConfigNode(property.name, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
65961
66073
|
} else if (ts.isSpreadAssignment(property)) {
|
|
65962
66074
|
if (reactCompilerFlagState && getReactCompilerFlagState(property.expression, analysis) !== null) continue;
|
|
65963
|
-
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$
|
|
66075
|
+
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$2(laterProperty.name) === "plugins" || getStaticPropertyName$2(laterProperty.name) === "presets"))) continue;
|
|
65964
66076
|
if (analyzeConfigNode(property.expression, analysis, allowCompilerTransform, false, excludedPropertyNames)) return true;
|
|
65965
66077
|
}
|
|
65966
66078
|
return false;
|
|
@@ -65973,23 +66085,36 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65973
66085
|
});
|
|
65974
66086
|
}
|
|
65975
66087
|
if (ts.isCallExpression(node)) {
|
|
66088
|
+
const resolvedModuleSpecifier = getNodeRequireResolveModuleSpecifier(node, analysis);
|
|
66089
|
+
if (resolvedModuleSpecifier !== null) return allowCompilerTransform && isCompilerTransformModule(resolvedModuleSpecifier, "default");
|
|
65976
66090
|
const callTargetResult = analyzeConfigCallTarget(node, analysis, allowCompilerTransform);
|
|
65977
66091
|
if (callTargetResult !== null) return callTargetResult;
|
|
65978
|
-
const directModuleSpecifier = getRequireModuleSpecifier(node);
|
|
66092
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(node);
|
|
65979
66093
|
const isRequireShadowed = analysis.localBindings.has("require") || ts.isIdentifier(node.expression) && getScopedConfigBinding(node.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require");
|
|
65980
66094
|
if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
65981
66095
|
if (directModuleSpecifier && !isRequireShadowed) {
|
|
65982
66096
|
if (allowCompilerTransform && isCompilerTransformModule(directModuleSpecifier, "default")) return true;
|
|
65983
|
-
if (
|
|
65984
|
-
|
|
65985
|
-
|
|
65986
|
-
|
|
66097
|
+
if (analyzeImportedConfig({
|
|
66098
|
+
analysis,
|
|
66099
|
+
moduleSpecifier: directModuleSpecifier,
|
|
66100
|
+
exportName: "default",
|
|
66101
|
+
allowCompilerTransform
|
|
66102
|
+
})) return true;
|
|
65987
66103
|
}
|
|
65988
66104
|
if (ts.isIdentifier(node.expression)) {
|
|
65989
|
-
|
|
65990
|
-
|
|
65991
|
-
|
|
65992
|
-
|
|
66105
|
+
if (!analysis.localBindings.has(node.expression.text) && !getScopedConfigBinding(node.expression).wasFound) {
|
|
66106
|
+
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66107
|
+
if (importBinding) {
|
|
66108
|
+
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
|
|
66109
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66110
|
+
analysis,
|
|
66111
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66112
|
+
exportName: importBinding.exportName,
|
|
66113
|
+
allowCompilerTransform,
|
|
66114
|
+
argumentsList: node.arguments
|
|
66115
|
+
});
|
|
66116
|
+
if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66117
|
+
}
|
|
65993
66118
|
}
|
|
65994
66119
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, node.expression.text);
|
|
65995
66120
|
if (topLevelBinding && ts.isFunctionLike(topLevelBinding) && analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, node.arguments)) return true;
|
|
@@ -65997,27 +66122,31 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65997
66122
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform) || node.arguments.some((argument) => analyzeConfigNode(argument, analysis, false));
|
|
65998
66123
|
}
|
|
65999
66124
|
if (ts.isPropertyAccessExpression(node)) {
|
|
66000
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(node.expression);
|
|
66125
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
|
|
66001
66126
|
if (requiredModuleSpecifier) {
|
|
66002
|
-
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66003
|
-
if (
|
|
66004
|
-
|
|
66005
|
-
|
|
66006
|
-
|
|
66127
|
+
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (analysis.localBindings.has(node.expression.expression.text) || getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66128
|
+
if (analyzeImportedConfig({
|
|
66129
|
+
analysis,
|
|
66130
|
+
moduleSpecifier: requiredModuleSpecifier,
|
|
66131
|
+
exportName: node.name.text,
|
|
66132
|
+
allowCompilerTransform
|
|
66133
|
+
})) return true;
|
|
66007
66134
|
return allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, node.name.text);
|
|
66008
66135
|
}
|
|
66009
66136
|
if (ts.isIdentifier(node.expression)) {
|
|
66010
|
-
if (analysis.localBindings.has(node.expression.text)) {
|
|
66011
|
-
const
|
|
66012
|
-
return Boolean(
|
|
66137
|
+
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66138
|
+
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
66139
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
|
|
66013
66140
|
}
|
|
66014
66141
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66015
66142
|
if (importBinding?.isNamespace) {
|
|
66016
66143
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.name.text)) return true;
|
|
66017
|
-
if (
|
|
66018
|
-
|
|
66019
|
-
|
|
66020
|
-
|
|
66144
|
+
if (analyzeImportedConfig({
|
|
66145
|
+
analysis,
|
|
66146
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66147
|
+
exportName: node.name.text,
|
|
66148
|
+
allowCompilerTransform
|
|
66149
|
+
})) return true;
|
|
66021
66150
|
return false;
|
|
66022
66151
|
}
|
|
66023
66152
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
@@ -66028,13 +66157,19 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66028
66157
|
}
|
|
66029
66158
|
if (ts.isElementAccessExpression(node) && node.argumentExpression && ts.isStringLiteralLike(node.argumentExpression)) {
|
|
66030
66159
|
if (ts.isIdentifier(node.expression)) {
|
|
66160
|
+
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66161
|
+
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66162
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
|
|
66163
|
+
}
|
|
66031
66164
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66032
66165
|
if (importBinding?.isNamespace) {
|
|
66033
66166
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.argumentExpression.text)) return true;
|
|
66034
|
-
|
|
66035
|
-
|
|
66036
|
-
|
|
66037
|
-
|
|
66167
|
+
return Boolean(analyzeImportedConfig({
|
|
66168
|
+
analysis,
|
|
66169
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66170
|
+
exportName: node.argumentExpression.text,
|
|
66171
|
+
allowCompilerTransform
|
|
66172
|
+
}));
|
|
66038
66173
|
}
|
|
66039
66174
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66040
66175
|
if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
@@ -66072,20 +66207,25 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66072
66207
|
};
|
|
66073
66208
|
const hasCompilerInConfigFile = (filePath) => analyzeConfigModuleExport(filePath, "default", false, 0, /* @__PURE__ */ new Set());
|
|
66074
66209
|
const hasCompilerInConfigFiles = (directory, filenames) => filenames.some((filename) => hasCompilerInConfigFile(Path.join(directory, filename)));
|
|
66075
|
-
const hasCompilerInPackageJsonConfig = (
|
|
66076
|
-
|
|
66210
|
+
const hasCompilerInPackageJsonConfig = (directory, packageJson) => {
|
|
66211
|
+
if (!isPlainObject(packageJson.babel)) return false;
|
|
66212
|
+
const packageJsonPath = Path.join(directory, "package.json");
|
|
66213
|
+
return analyzeConfigSourceFileExport(ts.parseJsonText(packageJsonPath, JSON.stringify(packageJson.babel)), packageJsonPath, "default", false, 0, /* @__PURE__ */ new Set());
|
|
66214
|
+
};
|
|
66215
|
+
const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(directory, packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
|
|
66077
66216
|
const hasCompilerConfigurationInAncestors = (directory) => {
|
|
66078
66217
|
if (isProjectBoundary(directory)) return false;
|
|
66079
66218
|
let ancestorDirectory = Path.dirname(directory);
|
|
66080
66219
|
while (ancestorDirectory !== Path.dirname(ancestorDirectory)) {
|
|
66081
66220
|
const ancestorPackagePath = Path.join(ancestorDirectory, "package.json");
|
|
66082
|
-
|
|
66221
|
+
const ancestorPackageJson = isFile(ancestorPackagePath) ? readPackageJson$1(ancestorPackagePath) : {};
|
|
66222
|
+
if (hasCompilerInPackageJsonConfig(ancestorDirectory, ancestorPackageJson) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
|
|
66083
66223
|
if (isProjectBoundary(ancestorDirectory)) return false;
|
|
66084
66224
|
ancestorDirectory = Path.dirname(ancestorDirectory);
|
|
66085
66225
|
}
|
|
66086
66226
|
return false;
|
|
66087
66227
|
};
|
|
66088
|
-
const detectReactCompiler = (directory, packageJson) => hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
66228
|
+
const detectReactCompiler = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
66089
66229
|
const detectReactCompilerLintPlugin = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_LINT_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_LINT_PACKAGES);
|
|
66090
66230
|
const detectNextjsStaticExport = (directory) => NEXT_CONFIG_FILENAMES.some((filename) => {
|
|
66091
66231
|
const filePath = Path.join(directory, filename);
|
|
@@ -69334,7 +69474,7 @@ const warn = (message) => {
|
|
|
69334
69474
|
runSync(warn$1(message));
|
|
69335
69475
|
};
|
|
69336
69476
|
const CONFIG_BASENAME = "doctor.config";
|
|
69337
|
-
const CONFIG_EXTENSIONS = [
|
|
69477
|
+
const CONFIG_EXTENSIONS$1 = [
|
|
69338
69478
|
"ts",
|
|
69339
69479
|
"mts",
|
|
69340
69480
|
"cts",
|
|
@@ -69438,7 +69578,7 @@ const loadLegacyConfig = (directory) => {
|
|
|
69438
69578
|
};
|
|
69439
69579
|
const loadConfigFromDirectory = async (directory) => {
|
|
69440
69580
|
let sawBrokenConfigFile = false;
|
|
69441
|
-
for (const extension of CONFIG_EXTENSIONS) {
|
|
69581
|
+
for (const extension of CONFIG_EXTENSIONS$1) {
|
|
69442
69582
|
const filePath = Path.join(directory, `${CONFIG_BASENAME}.${extension}`);
|
|
69443
69583
|
if (!isFile(filePath)) continue;
|
|
69444
69584
|
const isDataFile = DATA_CONFIG_EXTENSIONS.has(extension);
|
|
@@ -69497,7 +69637,7 @@ const loadConfigWithSource = (rootDirectory) => {
|
|
|
69497
69637
|
return loadPromise;
|
|
69498
69638
|
};
|
|
69499
69639
|
const directoryHasCurrentConfig = (directory) => {
|
|
69500
|
-
for (const extension of CONFIG_EXTENSIONS) if (isFile(Path.join(directory, `${CONFIG_BASENAME}.${extension}`))) return true;
|
|
69640
|
+
for (const extension of CONFIG_EXTENSIONS$1) if (isFile(Path.join(directory, `${CONFIG_BASENAME}.${extension}`))) return true;
|
|
69501
69641
|
return readEmbeddedPackageJsonConfig(directory) !== null;
|
|
69502
69642
|
};
|
|
69503
69643
|
/**
|
|
@@ -70201,6 +70341,321 @@ const buildReactNativeDiagnostic = (input) => ({
|
|
|
70201
70341
|
column: input.column ?? 0,
|
|
70202
70342
|
category: input.category ?? "Correctness"
|
|
70203
70343
|
});
|
|
70344
|
+
const ANDROID_APP_BUILD_FILE_NAMES = ["build.gradle", "build.gradle.kts"];
|
|
70345
|
+
const BUILD_TYPES_BLOCK_PATTERN = /\bbuildTypes\s*\{/g;
|
|
70346
|
+
const RELEASE_STRING_MARKER = "__RD_RELEASE__";
|
|
70347
|
+
const RELEASE_BLOCK_PATTERNS = [/\brelease\s*\{/g, /\b(?:getByName|named)\s*\(\s*(?:["']release["']|__RD_RELEASE__)\s*\)\s*\{/g];
|
|
70348
|
+
const MINIFY_ASSIGNMENT_PATTERN = /\b(?:isMinifyEnabled|minifyEnabled)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
70349
|
+
const SHRINK_RESOURCES_ASSIGNMENT_PATTERN = /\b(?:isShrinkResources|shrinkResources)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
70350
|
+
const stripGradleComments = (contents) => {
|
|
70351
|
+
let result = "";
|
|
70352
|
+
let index = 0;
|
|
70353
|
+
let quote = null;
|
|
70354
|
+
while (index < contents.length) {
|
|
70355
|
+
const character = contents[index];
|
|
70356
|
+
const nextCharacter = contents[index + 1];
|
|
70357
|
+
if (quote !== null) {
|
|
70358
|
+
result += character;
|
|
70359
|
+
if (character === "\\") {
|
|
70360
|
+
result += nextCharacter ?? "";
|
|
70361
|
+
index += 2;
|
|
70362
|
+
continue;
|
|
70363
|
+
}
|
|
70364
|
+
if (character === quote) quote = null;
|
|
70365
|
+
index += 1;
|
|
70366
|
+
continue;
|
|
70367
|
+
}
|
|
70368
|
+
if (character === "\"" || character === "'") {
|
|
70369
|
+
quote = character;
|
|
70370
|
+
result += character;
|
|
70371
|
+
index += 1;
|
|
70372
|
+
continue;
|
|
70373
|
+
}
|
|
70374
|
+
if (character === "/" && nextCharacter === "/") {
|
|
70375
|
+
while (index < contents.length && contents[index] !== "\n") {
|
|
70376
|
+
result += " ";
|
|
70377
|
+
index += 1;
|
|
70378
|
+
}
|
|
70379
|
+
continue;
|
|
70380
|
+
}
|
|
70381
|
+
if (character === "/" && nextCharacter === "*") {
|
|
70382
|
+
result += " ";
|
|
70383
|
+
index += 2;
|
|
70384
|
+
while (index < contents.length && !(contents[index] === "*" && contents[index + 1] === "/")) {
|
|
70385
|
+
result += contents[index] === "\n" ? "\n" : " ";
|
|
70386
|
+
index += 1;
|
|
70387
|
+
}
|
|
70388
|
+
if (index < contents.length) {
|
|
70389
|
+
result += " ";
|
|
70390
|
+
index += 2;
|
|
70391
|
+
}
|
|
70392
|
+
continue;
|
|
70393
|
+
}
|
|
70394
|
+
result += character;
|
|
70395
|
+
index += 1;
|
|
70396
|
+
}
|
|
70397
|
+
return result;
|
|
70398
|
+
};
|
|
70399
|
+
const maskGradleStrings = (contents) => {
|
|
70400
|
+
let result = "";
|
|
70401
|
+
let index = 0;
|
|
70402
|
+
let quote = null;
|
|
70403
|
+
while (index < contents.length) {
|
|
70404
|
+
const character = contents[index];
|
|
70405
|
+
if (quote === null) {
|
|
70406
|
+
if (character === "\"" || character === "'") {
|
|
70407
|
+
quote = character;
|
|
70408
|
+
result += " ";
|
|
70409
|
+
} else result += character;
|
|
70410
|
+
index += 1;
|
|
70411
|
+
continue;
|
|
70412
|
+
}
|
|
70413
|
+
if (character === "\\") {
|
|
70414
|
+
result += " ";
|
|
70415
|
+
index += 2;
|
|
70416
|
+
continue;
|
|
70417
|
+
}
|
|
70418
|
+
if (character === quote) quote = null;
|
|
70419
|
+
result += character === "\n" ? "\n" : " ";
|
|
70420
|
+
index += 1;
|
|
70421
|
+
}
|
|
70422
|
+
return result;
|
|
70423
|
+
};
|
|
70424
|
+
const findBlockContents = (contents, pattern) => {
|
|
70425
|
+
const blocks = [];
|
|
70426
|
+
pattern.lastIndex = 0;
|
|
70427
|
+
let match = pattern.exec(contents);
|
|
70428
|
+
while (match !== null) {
|
|
70429
|
+
const openingBraceIndex = pattern.lastIndex - 1;
|
|
70430
|
+
let depth = 1;
|
|
70431
|
+
let index = openingBraceIndex + 1;
|
|
70432
|
+
let quote = null;
|
|
70433
|
+
while (index < contents.length && depth > 0) {
|
|
70434
|
+
const character = contents[index];
|
|
70435
|
+
if (quote !== null) {
|
|
70436
|
+
if (character === "\\") {
|
|
70437
|
+
index += 2;
|
|
70438
|
+
continue;
|
|
70439
|
+
}
|
|
70440
|
+
if (character === quote) quote = null;
|
|
70441
|
+
} else if (character === "\"" || character === "'") quote = character;
|
|
70442
|
+
else if (character === "{") depth += 1;
|
|
70443
|
+
else if (character === "}") depth -= 1;
|
|
70444
|
+
index += 1;
|
|
70445
|
+
}
|
|
70446
|
+
if (depth === 0) blocks.push(contents.slice(openingBraceIndex + 1, index - 1));
|
|
70447
|
+
match = pattern.exec(contents);
|
|
70448
|
+
}
|
|
70449
|
+
return blocks;
|
|
70450
|
+
};
|
|
70451
|
+
const getFinalStaticBoolean = (contents, pattern) => {
|
|
70452
|
+
pattern.lastIndex = 0;
|
|
70453
|
+
let finalValue = null;
|
|
70454
|
+
let match = pattern.exec(contents);
|
|
70455
|
+
while (match !== null) {
|
|
70456
|
+
const staticValue = match[1]?.trim().replace(/\)$/, "").trim();
|
|
70457
|
+
if (staticValue === "true") finalValue = true;
|
|
70458
|
+
else if (staticValue === "false") finalValue = false;
|
|
70459
|
+
else finalValue = null;
|
|
70460
|
+
match = pattern.exec(contents);
|
|
70461
|
+
}
|
|
70462
|
+
return finalValue;
|
|
70463
|
+
};
|
|
70464
|
+
const getReleaseBlocks = (contents) => findBlockContents(contents, BUILD_TYPES_BLOCK_PATTERN).flatMap((buildTypesBlock) => RELEASE_BLOCK_PATTERNS.flatMap((pattern) => findBlockContents(buildTypesBlock, pattern)));
|
|
70465
|
+
const readAndroidReleaseShrinking = (rootDirectory) => {
|
|
70466
|
+
for (const buildFileName of ANDROID_APP_BUILD_FILE_NAMES) {
|
|
70467
|
+
const filePath = Path.posix.join("android", "app", buildFileName);
|
|
70468
|
+
const absoluteFilePath = Path.join(rootDirectory, filePath);
|
|
70469
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
70470
|
+
let contents;
|
|
70471
|
+
try {
|
|
70472
|
+
contents = stripGradleComments(NFS.readFileSync(absoluteFilePath, "utf-8"));
|
|
70473
|
+
} catch {
|
|
70474
|
+
return null;
|
|
70475
|
+
}
|
|
70476
|
+
const releaseBlocks = getReleaseBlocks(maskGradleStrings(contents.replace(/(["'])release\1/g, RELEASE_STRING_MARKER)));
|
|
70477
|
+
const [releaseBlock] = releaseBlocks;
|
|
70478
|
+
if (releaseBlock === void 0 || releaseBlocks.length !== 1) return null;
|
|
70479
|
+
const hasDisabledMinification = getFinalStaticBoolean(releaseBlock, MINIFY_ASSIGNMENT_PATTERN) === false;
|
|
70480
|
+
const hasDisabledResourceShrinking = getFinalStaticBoolean(releaseBlock, SHRINK_RESOURCES_ASSIGNMENT_PATTERN) === false;
|
|
70481
|
+
if (!hasDisabledMinification && !hasDisabledResourceShrinking) return null;
|
|
70482
|
+
return {
|
|
70483
|
+
filePath,
|
|
70484
|
+
hasDisabledMinification,
|
|
70485
|
+
hasDisabledResourceShrinking
|
|
70486
|
+
};
|
|
70487
|
+
}
|
|
70488
|
+
return null;
|
|
70489
|
+
};
|
|
70490
|
+
const checkReactNativeAndroidReleaseShrinking = (rootDirectory) => {
|
|
70491
|
+
const releaseShrinking = readAndroidReleaseShrinking(rootDirectory);
|
|
70492
|
+
if (releaseShrinking === null) return [];
|
|
70493
|
+
const disabledFeatures = [releaseShrinking.hasDisabledMinification ? "code minification" : null, releaseShrinking.hasDisabledResourceShrinking ? "resource shrinking" : null].filter((feature) => feature !== null);
|
|
70494
|
+
return [buildReactNativeDiagnostic({
|
|
70495
|
+
filePath: releaseShrinking.filePath,
|
|
70496
|
+
rule: "rn-android-release-shrinking-disabled",
|
|
70497
|
+
category: "Performance",
|
|
70498
|
+
message: `The Android release build explicitly disables ${disabledFeatures.join(" and ")}, leaving unreachable code or resources in the shipped app.`,
|
|
70499
|
+
help: "Enable release code minification and resource shrinking, then test the optimized build and add keep rules for libraries that require them."
|
|
70500
|
+
})];
|
|
70501
|
+
};
|
|
70502
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
70503
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
70504
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
70505
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
70506
|
+
return ts.ScriptKind.JS;
|
|
70507
|
+
};
|
|
70508
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
70509
|
+
let currentExpression = expression;
|
|
70510
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
70511
|
+
return currentExpression;
|
|
70512
|
+
};
|
|
70513
|
+
const BABEL_CONFIG_FILE_NAMES$1 = [
|
|
70514
|
+
"babel.config.js",
|
|
70515
|
+
"babel.config.cjs",
|
|
70516
|
+
"babel.config.mjs",
|
|
70517
|
+
"babel.config.ts",
|
|
70518
|
+
"babel.config.cts",
|
|
70519
|
+
"babel.config.json",
|
|
70520
|
+
".babelrc",
|
|
70521
|
+
".babelrc.js",
|
|
70522
|
+
".babelrc.cjs",
|
|
70523
|
+
".babelrc.mjs",
|
|
70524
|
+
".babelrc.cts",
|
|
70525
|
+
".babelrc.json"
|
|
70526
|
+
];
|
|
70527
|
+
const readUnknownPluginNames = (value) => {
|
|
70528
|
+
if (!Array.isArray(value)) return null;
|
|
70529
|
+
const pluginNames = [];
|
|
70530
|
+
for (const entry of value) {
|
|
70531
|
+
if (typeof entry === "string") {
|
|
70532
|
+
pluginNames.push(entry);
|
|
70533
|
+
continue;
|
|
70534
|
+
}
|
|
70535
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
70536
|
+
pluginNames.push(entry[0]);
|
|
70537
|
+
continue;
|
|
70538
|
+
}
|
|
70539
|
+
return null;
|
|
70540
|
+
}
|
|
70541
|
+
return pluginNames;
|
|
70542
|
+
};
|
|
70543
|
+
const getStaticPropertyName$1 = (propertyName) => {
|
|
70544
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName)) return propertyName.text;
|
|
70545
|
+
return null;
|
|
70546
|
+
};
|
|
70547
|
+
const getStaticPluginName = (expression) => {
|
|
70548
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
70549
|
+
if (ts.isStringLiteralLike(unwrappedExpression)) return unwrappedExpression.text;
|
|
70550
|
+
if (!ts.isArrayLiteralExpression(unwrappedExpression)) return null;
|
|
70551
|
+
const pluginExpression = unwrappedExpression.elements[0];
|
|
70552
|
+
return pluginExpression && ts.isStringLiteralLike(pluginExpression) ? pluginExpression.text : null;
|
|
70553
|
+
};
|
|
70554
|
+
const getPluginNamesFromObject = (objectExpression) => {
|
|
70555
|
+
if (objectExpression.properties.some((property) => ts.isSpreadAssignment(property))) return null;
|
|
70556
|
+
const pluginProperties = objectExpression.properties.filter((property) => ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "plugins");
|
|
70557
|
+
if (pluginProperties.length !== 1) return pluginProperties.length === 0 ? [] : null;
|
|
70558
|
+
const pluginListExpression = unwrapTypescriptExpression(pluginProperties[0].initializer);
|
|
70559
|
+
if (!ts.isArrayLiteralExpression(pluginListExpression)) return null;
|
|
70560
|
+
const pluginNames = [];
|
|
70561
|
+
for (const element of pluginListExpression.elements) {
|
|
70562
|
+
if (ts.isSpreadElement(element)) return null;
|
|
70563
|
+
const pluginName = getStaticPluginName(element);
|
|
70564
|
+
if (pluginName === null) return null;
|
|
70565
|
+
pluginNames.push(pluginName);
|
|
70566
|
+
}
|
|
70567
|
+
return pluginNames;
|
|
70568
|
+
};
|
|
70569
|
+
const isModuleExports = (expression) => ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "module" && expression.name.text === "exports" || ts.isElementAccessExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "module" && expression.argumentExpression !== void 0 && ts.isStringLiteralLike(expression.argumentExpression) && expression.argumentExpression.text === "exports";
|
|
70570
|
+
const getDirectExportedObject = (sourceFile) => {
|
|
70571
|
+
const exportedExpressions = [];
|
|
70572
|
+
for (const statement of sourceFile.statements) {
|
|
70573
|
+
if (ts.isExportAssignment(statement)) {
|
|
70574
|
+
exportedExpressions.push(statement.expression);
|
|
70575
|
+
continue;
|
|
70576
|
+
}
|
|
70577
|
+
if (ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(statement.expression.left)) exportedExpressions.push(statement.expression.right);
|
|
70578
|
+
}
|
|
70579
|
+
if (exportedExpressions.length !== 1) return null;
|
|
70580
|
+
const exportedExpression = unwrapTypescriptExpression(exportedExpressions[0]);
|
|
70581
|
+
return ts.isObjectLiteralExpression(exportedExpression) ? exportedExpression : null;
|
|
70582
|
+
};
|
|
70583
|
+
const parseConfigPluginNames = (filePath, contents) => {
|
|
70584
|
+
try {
|
|
70585
|
+
const parsedJson = JSON.parse(contents);
|
|
70586
|
+
return isPlainObject(parsedJson) ? readUnknownPluginNames(parsedJson.plugins) : null;
|
|
70587
|
+
} catch {
|
|
70588
|
+
if (ts.transpileModule(contents, {
|
|
70589
|
+
fileName: filePath,
|
|
70590
|
+
reportDiagnostics: true,
|
|
70591
|
+
compilerOptions: { allowJs: true }
|
|
70592
|
+
}).diagnostics?.some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error)) return null;
|
|
70593
|
+
const exportedObject = getDirectExportedObject(ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filePath)));
|
|
70594
|
+
return exportedObject === null ? null : getPluginNamesFromObject(exportedObject);
|
|
70595
|
+
}
|
|
70596
|
+
};
|
|
70597
|
+
const readStaticBabelPluginNames = (rootDirectory) => {
|
|
70598
|
+
for (const fileName of BABEL_CONFIG_FILE_NAMES$1) {
|
|
70599
|
+
const absoluteFilePath = Path.join(rootDirectory, fileName);
|
|
70600
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
70601
|
+
try {
|
|
70602
|
+
return {
|
|
70603
|
+
filePath: fileName,
|
|
70604
|
+
pluginNames: parseConfigPluginNames(fileName, NFS.readFileSync(absoluteFilePath, "utf-8"))
|
|
70605
|
+
};
|
|
70606
|
+
} catch {
|
|
70607
|
+
return {
|
|
70608
|
+
filePath: fileName,
|
|
70609
|
+
pluginNames: null
|
|
70610
|
+
};
|
|
70611
|
+
}
|
|
70612
|
+
}
|
|
70613
|
+
const packageJson = readPackageJson$1(Path.join(rootDirectory, "package.json"));
|
|
70614
|
+
if (!isPlainObject(packageJson.babel)) return null;
|
|
70615
|
+
return {
|
|
70616
|
+
filePath: "package.json",
|
|
70617
|
+
pluginNames: readUnknownPluginNames(packageJson.babel.plugins)
|
|
70618
|
+
};
|
|
70619
|
+
};
|
|
70620
|
+
const REACT_COMPILER_PLUGIN_NAMES = new Set(["babel-plugin-react-compiler", "react-compiler"]);
|
|
70621
|
+
const REANIMATED_PLUGIN_NAME = "react-native-reanimated/plugin";
|
|
70622
|
+
const WORKLETS_PLUGIN_NAME = "react-native-worklets/plugin";
|
|
70623
|
+
const checkReactCompilerPluginOrder = (filePath, pluginNames) => {
|
|
70624
|
+
if (pluginNames.findIndex((pluginName) => REACT_COMPILER_PLUGIN_NAMES.has(pluginName)) <= 0) return [];
|
|
70625
|
+
return [buildReactNativeDiagnostic({
|
|
70626
|
+
filePath,
|
|
70627
|
+
rule: "rn-react-compiler-plugin-first",
|
|
70628
|
+
category: "Performance",
|
|
70629
|
+
message: "The React Compiler Babel plugin is not first, so an earlier transform can change component or hook code before the compiler analyzes it.",
|
|
70630
|
+
help: "Move `babel-plugin-react-compiler` to the first entry in the Babel `plugins` array."
|
|
70631
|
+
})];
|
|
70632
|
+
};
|
|
70633
|
+
const checkReanimatedPluginOrder = (project, filePath, pluginNames) => {
|
|
70634
|
+
const reanimatedMajorVersion = project.reanimatedVersion === null || project.reanimatedVersion === void 0 ? null : getLowestDependencyMajor(project.reanimatedVersion);
|
|
70635
|
+
if (reanimatedMajorVersion === null || reanimatedMajorVersion < 4) return [];
|
|
70636
|
+
const diagnostics = [];
|
|
70637
|
+
if (pluginNames.includes(REANIMATED_PLUGIN_NAME)) diagnostics.push(buildReactNativeDiagnostic({
|
|
70638
|
+
filePath,
|
|
70639
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
70640
|
+
category: "Performance",
|
|
70641
|
+
message: "This Reanimated 4 project still uses `react-native-reanimated/plugin`, which was renamed to the Worklets Babel plugin.",
|
|
70642
|
+
help: "Replace it with `react-native-worklets/plugin` and keep that plugin last in the Babel `plugins` array."
|
|
70643
|
+
}));
|
|
70644
|
+
const workletsPluginIndex = pluginNames.lastIndexOf(WORKLETS_PLUGIN_NAME);
|
|
70645
|
+
if (workletsPluginIndex !== -1 && workletsPluginIndex !== pluginNames.length - 1) diagnostics.push(buildReactNativeDiagnostic({
|
|
70646
|
+
filePath,
|
|
70647
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
70648
|
+
category: "Performance",
|
|
70649
|
+
message: "`react-native-worklets/plugin` is not last in the Babel `plugins` array, so later transforms can prevent worklets from being compiled correctly.",
|
|
70650
|
+
help: "Move `react-native-worklets/plugin` to the final entry in the Babel `plugins` array."
|
|
70651
|
+
}));
|
|
70652
|
+
return diagnostics;
|
|
70653
|
+
};
|
|
70654
|
+
const checkReactNativeBabelPluginOrder = (rootDirectory, project) => {
|
|
70655
|
+
const babelPlugins = readStaticBabelPluginNames(rootDirectory);
|
|
70656
|
+
if (babelPlugins === null || babelPlugins.pluginNames === null) return [];
|
|
70657
|
+
return [...checkReactCompilerPluginOrder(babelPlugins.filePath, babelPlugins.pluginNames), ...checkReanimatedPluginOrder(project, babelPlugins.filePath, babelPlugins.pluginNames)];
|
|
70658
|
+
};
|
|
70204
70659
|
const BUILDER_BOB_PACKAGE = "react-native-builder-bob";
|
|
70205
70660
|
const isBuilderBobLibrary = (packageJson) => {
|
|
70206
70661
|
const bobConfig = packageJson[BUILDER_BOB_PACKAGE];
|
|
@@ -70277,7 +70732,12 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
|
70277
70732
|
const isReactNativeProject = (project) => project.framework === "react-native" || project.framework === "expo" || project.hasReactNativeWorkspace || project.expoVersion !== null;
|
|
70278
70733
|
const checkReactNativeProject = (rootDirectory, project) => {
|
|
70279
70734
|
if (!isReactNativeProject(project)) return [];
|
|
70280
|
-
return [
|
|
70735
|
+
return [
|
|
70736
|
+
...checkReactNativeMetroBabelPreset(rootDirectory),
|
|
70737
|
+
...checkReactNativeBabelPluginOrder(rootDirectory, project),
|
|
70738
|
+
...checkReactNativeAndroidReleaseShrinking(rootDirectory),
|
|
70739
|
+
...checkReactNativeLibraryDependencies(rootDirectory)
|
|
70740
|
+
];
|
|
70281
70741
|
};
|
|
70282
70742
|
const RULE_KEY = "no-vulnerable-react-server-components";
|
|
70283
70743
|
const REACT_RSC_ADVISORIES_BY_MINOR = {
|
|
@@ -70428,17 +70888,6 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
70428
70888
|
}
|
|
70429
70889
|
return diagnostics;
|
|
70430
70890
|
};
|
|
70431
|
-
const getTypescriptScriptKind = (fileName) => {
|
|
70432
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
70433
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
70434
|
-
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
70435
|
-
return ts.ScriptKind.JS;
|
|
70436
|
-
};
|
|
70437
|
-
const unwrapTypescriptExpression = (expression) => {
|
|
70438
|
-
let currentExpression = expression;
|
|
70439
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
70440
|
-
return currentExpression;
|
|
70441
|
-
};
|
|
70442
70891
|
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
70443
70892
|
isAnimationFunction: false,
|
|
70444
70893
|
isMotionComponent: false,
|
|
@@ -70994,7 +71443,11 @@ const buildCapabilities = (project) => {
|
|
|
70994
71443
|
capabilities.add(project.framework);
|
|
70995
71444
|
if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
|
|
70996
71445
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
70997
|
-
if (project.expoVersion !== null)
|
|
71446
|
+
if (project.expoVersion !== null) {
|
|
71447
|
+
capabilities.add("expo");
|
|
71448
|
+
const expoSdkMajorVersion = getLowestDependencyMajor(project.expoVersion);
|
|
71449
|
+
if (expoSdkMajorVersion !== null && expoSdkMajorVersion >= 54) capabilities.add("expo:54");
|
|
71450
|
+
}
|
|
70998
71451
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
70999
71452
|
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
71000
71453
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
@@ -71058,6 +71511,11 @@ const buildCapabilities = (project) => {
|
|
|
71058
71511
|
if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
|
|
71059
71512
|
if (project.isPreES2023Target) capabilities.add("pre-es2023");
|
|
71060
71513
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
71514
|
+
if (project.reanimatedVersion !== void 0 && project.reanimatedVersion !== null) {
|
|
71515
|
+
capabilities.add("reanimated");
|
|
71516
|
+
const reanimatedMajorVersion = getLowestDependencyMajor(project.reanimatedVersion);
|
|
71517
|
+
if (reanimatedMajorVersion !== null && reanimatedMajorVersion >= 4) capabilities.add("reanimated:4");
|
|
71518
|
+
}
|
|
71061
71519
|
if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
|
|
71062
71520
|
if (project.styledComponentsVersion) {
|
|
71063
71521
|
capabilities.add("styled-components");
|
|
@@ -72971,7 +73429,11 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
|
|
|
72971
73429
|
const ROOT_DIRECTORY_PLACEHOLDER = "<root>";
|
|
72972
73430
|
const normalizeConfigForHash = (config) => {
|
|
72973
73431
|
const clone = JSON.parse(JSON.stringify(config));
|
|
72974
|
-
if (clone?.settings?.["react-doctor"])
|
|
73432
|
+
if (clone?.settings?.["react-doctor"]) {
|
|
73433
|
+
const reactDoctorSettings = clone.settings["react-doctor"];
|
|
73434
|
+
reactDoctorSettings.rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
|
|
73435
|
+
if (Array.isArray(reactDoctorSettings.unpluginAutoImportRootDirectories)) reactDoctorSettings.unpluginAutoImportRootDirectories = [ROOT_DIRECTORY_PLACEHOLDER];
|
|
73436
|
+
}
|
|
72975
73437
|
if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
|
|
72976
73438
|
return clone;
|
|
72977
73439
|
};
|
|
@@ -73130,13 +73592,14 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
73130
73592
|
}
|
|
73131
73593
|
return enabled;
|
|
73132
73594
|
};
|
|
73133
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
73595
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, runtimeGlobals, unpluginAutoImportGlobalScopes, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
73134
73596
|
const hasIncludedTags = includedTags.size > 0;
|
|
73135
73597
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
73136
73598
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
73137
73599
|
const jsPlugins = [];
|
|
73138
73600
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
73139
73601
|
const capabilities = getCapabilities(project);
|
|
73602
|
+
const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
|
|
73140
73603
|
const enabledReactDoctorRules = {};
|
|
73141
73604
|
for (const registryEntry of REACT_DOCTOR_RULES) {
|
|
73142
73605
|
const rule = reactDoctorPlugin.rules[registryEntry.id];
|
|
@@ -73182,8 +73645,16 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
73182
73645
|
jsPlugins: [...jsPlugins, pluginPath],
|
|
73183
73646
|
settings: { "react-doctor": {
|
|
73184
73647
|
framework: project.framework,
|
|
73185
|
-
rootDirectory:
|
|
73648
|
+
rootDirectory: settingsRootDirectory,
|
|
73186
73649
|
capabilities: [...capabilities].sort(),
|
|
73650
|
+
...runtimeGlobals && runtimeGlobals.length > 0 ? { runtimeGlobals: [...runtimeGlobals] } : {},
|
|
73651
|
+
...unpluginAutoImportGlobalScopes && unpluginAutoImportGlobalScopes.length > 0 ? {
|
|
73652
|
+
unpluginAutoImportRootDirectories: [...new Set([settingsRootDirectory, project.rootDirectory])],
|
|
73653
|
+
unpluginAutoImportGlobalScopes: unpluginAutoImportGlobalScopes.map((scope) => ({
|
|
73654
|
+
directory: scope.directory,
|
|
73655
|
+
names: [...scope.names]
|
|
73656
|
+
}))
|
|
73657
|
+
} : {},
|
|
73187
73658
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
73188
73659
|
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
73189
73660
|
} },
|
|
@@ -73194,6 +73665,245 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
73194
73665
|
}
|
|
73195
73666
|
};
|
|
73196
73667
|
};
|
|
73668
|
+
const AUTO_IMPORT_ADAPTER_PATTERN = /^unplugin-auto-import\/(?:astro|esbuild|rollup|rolldown|rspack|vite|webpack)$/;
|
|
73669
|
+
const CONFIG_BASENAMES = [
|
|
73670
|
+
"astro.config",
|
|
73671
|
+
"esbuild.config",
|
|
73672
|
+
"rollup.config",
|
|
73673
|
+
"rolldown.config",
|
|
73674
|
+
"rspack.config",
|
|
73675
|
+
"vite.config",
|
|
73676
|
+
"webpack.config"
|
|
73677
|
+
];
|
|
73678
|
+
const CONFIG_EXTENSIONS = [
|
|
73679
|
+
".cjs",
|
|
73680
|
+
".cts",
|
|
73681
|
+
".js",
|
|
73682
|
+
".mjs",
|
|
73683
|
+
".mts",
|
|
73684
|
+
".ts"
|
|
73685
|
+
];
|
|
73686
|
+
const CONFIG_FILENAMES = new Set(CONFIG_BASENAMES.flatMap((basename) => CONFIG_EXTENSIONS.map((extension) => `${basename}${extension}`)));
|
|
73687
|
+
const DEFAULT_ESLINT_GLOBALS_PATH = ".eslintrc-auto-import.json";
|
|
73688
|
+
const SUPPORTED_GLOBAL_VALUES = new Set([
|
|
73689
|
+
true,
|
|
73690
|
+
false,
|
|
73691
|
+
"readable",
|
|
73692
|
+
"readonly",
|
|
73693
|
+
"writable",
|
|
73694
|
+
"writeable"
|
|
73695
|
+
]);
|
|
73696
|
+
const getStaticProperty = (objectExpression, propertyName) => objectExpression.properties.find((property) => {
|
|
73697
|
+
if (ts.isSpreadAssignment(property)) return false;
|
|
73698
|
+
const name = ts.isComputedPropertyName(property.name) ? unwrapTypescriptExpression(property.name.expression) : property.name;
|
|
73699
|
+
return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && name.text === propertyName;
|
|
73700
|
+
}) ?? null;
|
|
73701
|
+
const hasNonLiteralComputedProperty = (objectExpression) => objectExpression.properties.some((property) => !ts.isSpreadAssignment(property) && ts.isComputedPropertyName(property.name) && !ts.isStringLiteralLike(unwrapTypescriptExpression(property.name.expression)));
|
|
73702
|
+
const getStaticPropertyAssignment = (objectExpression, propertyName) => {
|
|
73703
|
+
const property = getStaticProperty(objectExpression, propertyName);
|
|
73704
|
+
return property && ts.isPropertyAssignment(property) ? property : null;
|
|
73705
|
+
};
|
|
73706
|
+
const getRequireModuleSpecifier = (expression) => {
|
|
73707
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
73708
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === "default") return getRequireModuleSpecifier(unwrappedExpression.expression);
|
|
73709
|
+
if (!ts.isCallExpression(unwrappedExpression) || !ts.isIdentifier(unwrappedExpression.expression) || unwrappedExpression.expression.text !== "require" || unwrappedExpression.arguments.length !== 1) return null;
|
|
73710
|
+
const moduleSpecifier = unwrappedExpression.arguments[0];
|
|
73711
|
+
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
73712
|
+
};
|
|
73713
|
+
const getRequiredPropertyModuleSpecifier = (expression, propertyName) => {
|
|
73714
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
73715
|
+
return ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === propertyName ? getRequireModuleSpecifier(unwrappedExpression.expression) : null;
|
|
73716
|
+
};
|
|
73717
|
+
const isCommonJsExportAssignment = (node, sourceFile) => ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && (node.left.getText(sourceFile) === "module.exports" || node.left.getText(sourceFile) === "exports.default");
|
|
73718
|
+
const isTopLevelExpression = (node) => {
|
|
73719
|
+
let ancestor = node.parent;
|
|
73720
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
73721
|
+
if (ts.isExpressionStatement(ancestor)) return ts.isSourceFile(ancestor.parent);
|
|
73722
|
+
if (!ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isAwaitExpression(ancestor)) return false;
|
|
73723
|
+
ancestor = ancestor.parent;
|
|
73724
|
+
}
|
|
73725
|
+
return false;
|
|
73726
|
+
};
|
|
73727
|
+
const isInsideActiveConfigProperty = (node, propertyName, sourceFile, esbuildBindings, esbuildNamespaceBindings) => {
|
|
73728
|
+
let ancestor = node.parent;
|
|
73729
|
+
let didFindConfigProperty = false;
|
|
73730
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
73731
|
+
if (!didFindConfigProperty && !ts.isArrayLiteralExpression(ancestor) && !ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isPropertyAssignment(ancestor)) return false;
|
|
73732
|
+
if (ts.isPropertyAssignment(ancestor)) {
|
|
73733
|
+
const isConfigProperty = (ts.isIdentifier(ancestor.name) || ts.isStringLiteralLike(ancestor.name)) && ancestor.name.text === propertyName;
|
|
73734
|
+
if (didFindConfigProperty || !isConfigProperty) return false;
|
|
73735
|
+
if (!ts.isObjectLiteralExpression(ancestor.parent) || ancestor.parent.properties.some(ts.isSpreadAssignment)) return false;
|
|
73736
|
+
didFindConfigProperty = true;
|
|
73737
|
+
ancestor = ancestor.parent;
|
|
73738
|
+
continue;
|
|
73739
|
+
}
|
|
73740
|
+
if (didFindConfigProperty) {
|
|
73741
|
+
if (ts.isExportAssignment(ancestor)) return true;
|
|
73742
|
+
if (isCommonJsExportAssignment(ancestor, sourceFile)) return isTopLevelExpression(ancestor);
|
|
73743
|
+
if (propertyName === "plugins" && ts.isCallExpression(ancestor) && (ts.isIdentifier(ancestor.expression) ? esbuildBindings.has(ancestor.expression.text) : ts.isPropertyAccessExpression(ancestor.expression) && ancestor.expression.name.text === "build" && (ts.isIdentifier(ancestor.expression.expression) && esbuildNamespaceBindings.has(ancestor.expression.expression.text) || getRequireModuleSpecifier(ancestor.expression.expression) === "esbuild"))) return isTopLevelExpression(ancestor);
|
|
73744
|
+
if (!(ts.isObjectLiteralExpression(ancestor) || ts.isParenthesizedExpression(ancestor) || ts.isAsExpression(ancestor) || ts.isSatisfiesExpression(ancestor) || ts.isNonNullExpression(ancestor) || ts.isTypeAssertionExpression(ancestor) || ts.isCallExpression(ancestor) && ts.isIdentifier(ancestor.expression) && ancestor.expression.text === "defineConfig")) return false;
|
|
73745
|
+
}
|
|
73746
|
+
ancestor = ancestor.parent;
|
|
73747
|
+
}
|
|
73748
|
+
return false;
|
|
73749
|
+
};
|
|
73750
|
+
const getGlobalsPathFromActiveAutoImportCall = (callExpression, packageDirectory) => {
|
|
73751
|
+
const optionsExpression = callExpression.arguments[0];
|
|
73752
|
+
if (!optionsExpression) return null;
|
|
73753
|
+
const unwrappedOptions = unwrapTypescriptExpression(optionsExpression);
|
|
73754
|
+
if (!ts.isObjectLiteralExpression(unwrappedOptions)) return null;
|
|
73755
|
+
if (unwrappedOptions.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(unwrappedOptions)) return null;
|
|
73756
|
+
if (getStaticProperty(unwrappedOptions, "include") || getStaticProperty(unwrappedOptions, "exclude")) return null;
|
|
73757
|
+
const eslintrcProperty = getStaticPropertyAssignment(unwrappedOptions, "eslintrc");
|
|
73758
|
+
if (!eslintrcProperty) return null;
|
|
73759
|
+
const eslintrcExpression = unwrapTypescriptExpression(eslintrcProperty.initializer);
|
|
73760
|
+
if (!ts.isObjectLiteralExpression(eslintrcExpression)) return null;
|
|
73761
|
+
if (eslintrcExpression.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(eslintrcExpression)) return null;
|
|
73762
|
+
const enabledProperty = getStaticPropertyAssignment(eslintrcExpression, "enabled");
|
|
73763
|
+
if (!enabledProperty || unwrapTypescriptExpression(enabledProperty.initializer).kind !== ts.SyntaxKind.TrueKeyword) return null;
|
|
73764
|
+
const filepathProperty = getStaticProperty(eslintrcExpression, "filepath");
|
|
73765
|
+
if (!filepathProperty) return Path.join(packageDirectory, DEFAULT_ESLINT_GLOBALS_PATH);
|
|
73766
|
+
if (!ts.isPropertyAssignment(filepathProperty)) return null;
|
|
73767
|
+
const filepathExpression = unwrapTypescriptExpression(filepathProperty.initializer);
|
|
73768
|
+
return ts.isStringLiteralLike(filepathExpression) ? Path.resolve(packageDirectory, filepathExpression.text) : null;
|
|
73769
|
+
};
|
|
73770
|
+
const collectGlobalsPathsFromConfig = (configPath, packageDirectory) => {
|
|
73771
|
+
let sourceText;
|
|
73772
|
+
try {
|
|
73773
|
+
sourceText = NFS.readFileSync(configPath, "utf8");
|
|
73774
|
+
} catch {
|
|
73775
|
+
return {
|
|
73776
|
+
didFindActiveAutoImport: false,
|
|
73777
|
+
globalsPaths: []
|
|
73778
|
+
};
|
|
73779
|
+
}
|
|
73780
|
+
const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true);
|
|
73781
|
+
const autoImportBindings = /* @__PURE__ */ new Map();
|
|
73782
|
+
const esbuildBindings = /* @__PURE__ */ new Set();
|
|
73783
|
+
const esbuildNamespaceBindings = /* @__PURE__ */ new Set();
|
|
73784
|
+
for (const statement of sourceFile.statements) {
|
|
73785
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
73786
|
+
const moduleSpecifier = statement.moduleSpecifier.text;
|
|
73787
|
+
if (AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
73788
|
+
const defaultBinding = statement.importClause?.name;
|
|
73789
|
+
if (defaultBinding) autoImportBindings.set(defaultBinding.text, moduleSpecifier);
|
|
73790
|
+
}
|
|
73791
|
+
if (moduleSpecifier === "esbuild") {
|
|
73792
|
+
const defaultBinding = statement.importClause?.name;
|
|
73793
|
+
if (defaultBinding) esbuildNamespaceBindings.add(defaultBinding.text);
|
|
73794
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
73795
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
73796
|
+
for (const importSpecifier of namedBindings.elements) if ((importSpecifier.propertyName ?? importSpecifier.name).text === "build") esbuildBindings.add(importSpecifier.name.text);
|
|
73797
|
+
}
|
|
73798
|
+
if (namedBindings && ts.isNamespaceImport(namedBindings)) esbuildNamespaceBindings.add(namedBindings.name.text);
|
|
73799
|
+
}
|
|
73800
|
+
}
|
|
73801
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
73802
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
73803
|
+
if (!declaration.initializer) continue;
|
|
73804
|
+
const declarationName = ts.isIdentifier(declaration.name) ? declaration.name.text : null;
|
|
73805
|
+
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
73806
|
+
if (declarationName && moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) autoImportBindings.set(declarationName, moduleSpecifier);
|
|
73807
|
+
if (moduleSpecifier === "esbuild") {
|
|
73808
|
+
if (declarationName) esbuildNamespaceBindings.add(declarationName);
|
|
73809
|
+
if (ts.isObjectBindingPattern(declaration.name)) for (const bindingElement of declaration.name.elements) {
|
|
73810
|
+
const importedName = bindingElement.propertyName ?? bindingElement.name;
|
|
73811
|
+
if (ts.isIdentifier(importedName) && importedName.text === "build" && ts.isIdentifier(bindingElement.name)) esbuildBindings.add(bindingElement.name.text);
|
|
73812
|
+
}
|
|
73813
|
+
}
|
|
73814
|
+
if (declarationName && getRequiredPropertyModuleSpecifier(declaration.initializer, "build") === "esbuild") esbuildBindings.add(declarationName);
|
|
73815
|
+
}
|
|
73816
|
+
}
|
|
73817
|
+
const globalsPaths = /* @__PURE__ */ new Set();
|
|
73818
|
+
let didFindActiveAutoImport = false;
|
|
73819
|
+
let didFindUnsafeActiveAutoImport = false;
|
|
73820
|
+
const visit = (node) => {
|
|
73821
|
+
if (ts.isCallExpression(node)) {
|
|
73822
|
+
const moduleSpecifier = ts.isIdentifier(node.expression) ? autoImportBindings.get(node.expression.text) : getRequireModuleSpecifier(node.expression);
|
|
73823
|
+
if (moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
73824
|
+
if (isInsideActiveConfigProperty(node, moduleSpecifier.endsWith("/astro") ? "integrations" : "plugins", sourceFile, esbuildBindings, esbuildNamespaceBindings)) {
|
|
73825
|
+
didFindActiveAutoImport = true;
|
|
73826
|
+
const globalsPath = getGlobalsPathFromActiveAutoImportCall(node, packageDirectory);
|
|
73827
|
+
if (globalsPath) globalsPaths.add(globalsPath);
|
|
73828
|
+
else didFindUnsafeActiveAutoImport = true;
|
|
73829
|
+
}
|
|
73830
|
+
}
|
|
73831
|
+
}
|
|
73832
|
+
ts.forEachChild(node, visit);
|
|
73833
|
+
};
|
|
73834
|
+
visit(sourceFile);
|
|
73835
|
+
return {
|
|
73836
|
+
didFindActiveAutoImport,
|
|
73837
|
+
globalsPaths: didFindUnsafeActiveAutoImport ? [] : [...globalsPaths]
|
|
73838
|
+
};
|
|
73839
|
+
};
|
|
73840
|
+
const collectGeneratedGlobalNames = (globalsPath, rootDirectory) => {
|
|
73841
|
+
const relativePath = Path.relative(rootDirectory, globalsPath);
|
|
73842
|
+
if (relativePath.startsWith("..") || Path.isAbsolute(relativePath)) return [];
|
|
73843
|
+
const parsed = failOpenReadJson(globalsPath, null);
|
|
73844
|
+
if (!isPlainObject(parsed) || !isPlainObject(parsed.globals)) return [];
|
|
73845
|
+
return Object.entries(parsed.globals).filter((entry) => entry[0].length > 0 && (typeof entry[1] === "boolean" || typeof entry[1] === "string") && SUPPORTED_GLOBAL_VALUES.has(entry[1])).map(([name]) => name).sort();
|
|
73846
|
+
};
|
|
73847
|
+
const findOwningPackageDirectory = (absoluteFilePath, rootDirectory, cache) => {
|
|
73848
|
+
let currentDirectory = Path.dirname(absoluteFilePath);
|
|
73849
|
+
const visitedDirectories = [];
|
|
73850
|
+
while (true) {
|
|
73851
|
+
const cachedDirectory = cache.get(currentDirectory);
|
|
73852
|
+
if (cachedDirectory !== void 0) {
|
|
73853
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, cachedDirectory);
|
|
73854
|
+
return cachedDirectory;
|
|
73855
|
+
}
|
|
73856
|
+
const relativeDirectory = Path.relative(rootDirectory, currentDirectory);
|
|
73857
|
+
if (relativeDirectory.startsWith("..") || Path.isAbsolute(relativeDirectory)) {
|
|
73858
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
73859
|
+
return null;
|
|
73860
|
+
}
|
|
73861
|
+
visitedDirectories.push(currentDirectory);
|
|
73862
|
+
if (NFS.existsSync(Path.join(currentDirectory, "package.json"))) {
|
|
73863
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, currentDirectory);
|
|
73864
|
+
return currentDirectory;
|
|
73865
|
+
}
|
|
73866
|
+
if (currentDirectory === rootDirectory) {
|
|
73867
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
73868
|
+
return null;
|
|
73869
|
+
}
|
|
73870
|
+
currentDirectory = Path.dirname(currentDirectory);
|
|
73871
|
+
}
|
|
73872
|
+
};
|
|
73873
|
+
const collectPackageGlobalNames = (packageDirectory, rootDirectory) => {
|
|
73874
|
+
let directoryEntries;
|
|
73875
|
+
try {
|
|
73876
|
+
directoryEntries = NFS.readdirSync(packageDirectory, { withFileTypes: true });
|
|
73877
|
+
} catch {
|
|
73878
|
+
return [];
|
|
73879
|
+
}
|
|
73880
|
+
const configuredGlobalsPaths = [];
|
|
73881
|
+
for (const entry of directoryEntries) {
|
|
73882
|
+
if (!entry.isFile() && !entry.isSymbolicLink() || !CONFIG_FILENAMES.has(entry.name)) continue;
|
|
73883
|
+
const configGlobalsPaths = collectGlobalsPathsFromConfig(Path.join(packageDirectory, entry.name), packageDirectory);
|
|
73884
|
+
if (configGlobalsPaths.didFindActiveAutoImport) configuredGlobalsPaths.push(configGlobalsPaths.globalsPaths.toSorted());
|
|
73885
|
+
}
|
|
73886
|
+
if (configuredGlobalsPaths.length === 0) return [];
|
|
73887
|
+
const globalsPaths = configuredGlobalsPaths[0];
|
|
73888
|
+
if (configuredGlobalsPaths.some((candidatePaths) => candidatePaths.length !== globalsPaths.length || candidatePaths.some((candidatePath, index) => candidatePath !== globalsPaths[index]))) return [];
|
|
73889
|
+
const names = /* @__PURE__ */ new Set();
|
|
73890
|
+
for (const globalsPath of globalsPaths) for (const name of collectGeneratedGlobalNames(globalsPath, rootDirectory)) names.add(name);
|
|
73891
|
+
return [...names].sort();
|
|
73892
|
+
};
|
|
73893
|
+
const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }) => {
|
|
73894
|
+
const absoluteRootDirectory = Path.resolve(rootDirectory);
|
|
73895
|
+
const packageDirectoryCache = /* @__PURE__ */ new Map();
|
|
73896
|
+
const packageDirectories = /* @__PURE__ */ new Set();
|
|
73897
|
+
for (const candidateFile of candidateFiles) {
|
|
73898
|
+
const packageDirectory = findOwningPackageDirectory(Path.resolve(absoluteRootDirectory, candidateFile), absoluteRootDirectory, packageDirectoryCache);
|
|
73899
|
+
if (packageDirectory) packageDirectories.add(packageDirectory);
|
|
73900
|
+
}
|
|
73901
|
+
const scopes = [...packageDirectories].map((packageDirectory) => ({
|
|
73902
|
+
directory: Path.relative(absoluteRootDirectory, packageDirectory).replaceAll("\\", "/"),
|
|
73903
|
+
names: collectPackageGlobalNames(packageDirectory, absoluteRootDirectory)
|
|
73904
|
+
})).sort((firstScope, secondScope) => firstScope.directory.localeCompare(secondScope.directory));
|
|
73905
|
+
return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
|
|
73906
|
+
};
|
|
73197
73907
|
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
73198
73908
|
const decodeFileDiagnostics = (raw) => {
|
|
73199
73909
|
if (!Array.isArray(raw)) return null;
|
|
@@ -73516,6 +74226,12 @@ const appendReanimatedSharedValueHint = (help, rule, project) => {
|
|
|
73516
74226
|
if (!help) return REANIMATED_SHARED_VALUE_HINT;
|
|
73517
74227
|
return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
|
|
73518
74228
|
};
|
|
74229
|
+
const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
74230
|
+
const boundedOffset = Math.min(Math.max(utf8Offset, 0), sourceBuffer.length);
|
|
74231
|
+
let lineStartOffset = boundedOffset;
|
|
74232
|
+
while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
|
|
74233
|
+
return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
|
|
74234
|
+
};
|
|
73519
74235
|
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
73520
74236
|
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
73521
74237
|
const KNOWN_SECRET_RULES = [
|
|
@@ -74231,7 +74947,7 @@ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORI
|
|
|
74231
74947
|
* with empty text still carry a useful jump target, so they're kept
|
|
74232
74948
|
* with a neutral message.
|
|
74233
74949
|
*/
|
|
74234
|
-
const buildRelatedLocations = (labels, filePath) => {
|
|
74950
|
+
const buildRelatedLocations = (labels, filePath, sourceBuffer) => {
|
|
74235
74951
|
if (labels.length <= 1) return [];
|
|
74236
74952
|
const related = [];
|
|
74237
74953
|
for (let labelIndex = 1; labelIndex < labels.length; labelIndex++) {
|
|
@@ -74239,8 +74955,8 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
74239
74955
|
if (!label?.span) continue;
|
|
74240
74956
|
related.push({
|
|
74241
74957
|
filePath,
|
|
74242
|
-
line: label.span.line ?? 0,
|
|
74243
|
-
column: label.span.column ?? 0,
|
|
74958
|
+
line: sourceBuffer === null ? label.span.line ?? 0 : lineOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
74959
|
+
column: sourceBuffer === null ? label.span.column ?? 0 : columnOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
74244
74960
|
offset: label.span.offset,
|
|
74245
74961
|
length: label.span.length,
|
|
74246
74962
|
message: label.label ?? ""
|
|
@@ -74260,7 +74976,7 @@ const isOxlintOutput = (value) => isRecord$1(value) && Array.isArray(value.diagn
|
|
|
74260
74976
|
* to the first `{`. Raises `OxlintOutputUnparseable` when the
|
|
74261
74977
|
* stdout isn't valid JSON or doesn't carry a `diagnostics` array.
|
|
74262
74978
|
*/
|
|
74263
|
-
const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
74979
|
+
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath) => {
|
|
74264
74980
|
if (!stdout) return [];
|
|
74265
74981
|
const jsonStart = stdout.indexOf("{");
|
|
74266
74982
|
const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
|
|
@@ -74277,8 +74993,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74277
74993
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
74278
74994
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
74279
74995
|
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
74996
|
+
const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
74997
|
+
const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
|
|
74280
74998
|
const readSourceBuffer = (filename) => {
|
|
74281
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
74999
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74282
75000
|
const cached = sourceBufferCache.get(absolutePath);
|
|
74283
75001
|
if (cached !== void 0) return cached;
|
|
74284
75002
|
let sourceBuffer;
|
|
@@ -74291,7 +75009,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74291
75009
|
return sourceBuffer;
|
|
74292
75010
|
};
|
|
74293
75011
|
const readSourceLines = (filename) => {
|
|
74294
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
75012
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74295
75013
|
const cached = sourceLinesCache.get(absolutePath);
|
|
74296
75014
|
if (cached !== void 0) return cached;
|
|
74297
75015
|
const sourceBuffer = readSourceBuffer(filename);
|
|
@@ -74300,27 +75018,30 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74300
75018
|
return sourceLines;
|
|
74301
75019
|
};
|
|
74302
75020
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
74303
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
75021
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74304
75022
|
const cached = minifiedFileCache.get(absolutePath);
|
|
74305
75023
|
if (cached !== void 0) return cached;
|
|
74306
75024
|
const minified = isMinifiedSource(absolutePath);
|
|
74307
75025
|
minifiedFileCache.set(absolutePath, minified);
|
|
74308
75026
|
return minified;
|
|
74309
75027
|
};
|
|
74310
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !(TYPESCRIPT_DECLARATION_FILE_PATTERN.test(diagnostic.filename) && OXLINT_IGNORED_DECLARATION_DIAGNOSTIC_CODES.has(diagnostic.code)) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
75028
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(resolveSourceFilename(diagnostic.filename)) && !(TYPESCRIPT_DECLARATION_FILE_PATTERN.test(diagnostic.filename) && OXLINT_IGNORED_DECLARATION_DIAGNOSTIC_CODES.has(diagnostic.code)) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
74311
75029
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
74312
75030
|
const primaryLabel = diagnostic.labels[0];
|
|
74313
75031
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
74314
|
-
const
|
|
75032
|
+
const mappedSourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
75033
|
+
const normalizedFilePath = (mappedSourceFilename ?? diagnostic.filename).replaceAll("\\", "/");
|
|
74315
75034
|
const primarySpan = primaryLabel?.span;
|
|
74316
75035
|
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
74317
|
-
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
75036
|
+
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath, mappedSourceFilename === void 0 ? null : sourceBuffer);
|
|
74318
75037
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
74319
75038
|
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
74320
75039
|
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
74321
|
-
const
|
|
75040
|
+
const primaryLineNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.line ?? 0;
|
|
75041
|
+
const primaryColumnNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? columnOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.column ?? 0;
|
|
75042
|
+
const primaryLineIndex = primarySpan ? primaryLineNumber - 1 : -1;
|
|
74322
75043
|
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
74323
|
-
const primaryColumnIndex = primarySpan ?
|
|
75044
|
+
const primaryColumnIndex = primarySpan ? primaryColumnNumber - 1 : -1;
|
|
74324
75045
|
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
74325
75046
|
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
74326
75047
|
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
@@ -74333,8 +75054,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74333
75054
|
message: cleaned.message,
|
|
74334
75055
|
help: cleaned.help,
|
|
74335
75056
|
url: diagnostic.url,
|
|
74336
|
-
line:
|
|
74337
|
-
column:
|
|
75057
|
+
line: primaryLineNumber,
|
|
75058
|
+
column: primaryColumnNumber,
|
|
74338
75059
|
...primarySpan ? {
|
|
74339
75060
|
offset: primarySpan.offset,
|
|
74340
75061
|
length: primarySpan.length,
|
|
@@ -74522,7 +75243,11 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
74522
75243
|
* loop with a slimmer config in that case.
|
|
74523
75244
|
*/
|
|
74524
75245
|
const spawnLintBatches = async (input) => {
|
|
74525
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75246
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75247
|
+
const resolveSourcePath = (filePath) => {
|
|
75248
|
+
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
75249
|
+
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
75250
|
+
};
|
|
74526
75251
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
74527
75252
|
let rescueDeadlineEpochMs;
|
|
74528
75253
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
@@ -74542,7 +75267,7 @@ const spawnLintBatches = async (input) => {
|
|
|
74542
75267
|
}
|
|
74543
75268
|
const batchArgs = [...baseArgs, ...batch];
|
|
74544
75269
|
try {
|
|
74545
|
-
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory);
|
|
75270
|
+
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory, sourcePathByLintPath);
|
|
74546
75271
|
} catch (error) {
|
|
74547
75272
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
74548
75273
|
if (isPastDeadline()) {
|
|
@@ -74648,10 +75373,12 @@ const spawnLintBatches = async (input) => {
|
|
|
74648
75373
|
onPartialFailure(buildMessage(`${skippedFiles.slice(0, 3).join(", ")}${skippedFiles.length > 3 ? `, +${skippedFiles.length - 3} more` : ""}`));
|
|
74649
75374
|
};
|
|
74650
75375
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
74651
|
-
|
|
74652
|
-
|
|
75376
|
+
const droppedSourceFiles = [...new Set(droppedFiles.map(resolveSourcePath))];
|
|
75377
|
+
const deadlineSkippedSourceFiles = [...new Set(outcome.deadlineSkippedFiles.map(resolveSourcePath))];
|
|
75378
|
+
reportSkippedFiles(droppedSourceFiles, (fileListPreview) => `${droppedSourceFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
75379
|
+
reportSkippedFiles(deadlineSkippedSourceFiles, (fileListPreview) => `${deadlineSkippedSourceFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
74653
75380
|
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
74654
|
-
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
75381
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)).map(resolveSourcePath))].sort());
|
|
74655
75382
|
return dedupeDiagnostics(diagnostics);
|
|
74656
75383
|
};
|
|
74657
75384
|
let didValidate = false;
|
|
@@ -74750,6 +75477,266 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
|
74750
75477
|
}
|
|
74751
75478
|
return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
|
|
74752
75479
|
};
|
|
75480
|
+
const THREE_MODULE_IMPORT_PATTERN = /\b(?:from\s*|import\s*(?:\(\s*)?|require\s*\(\s*)["']three(?:\/[^"']*)?["']/;
|
|
75481
|
+
const containsThreeModuleImport = (sourceText) => THREE_MODULE_IMPORT_PATTERN.test(sourceText);
|
|
75482
|
+
const COMMENT_OPEN = "<!--";
|
|
75483
|
+
const COMMENT_CLOSE = "-->";
|
|
75484
|
+
const FRONTMATTER_FENCE = "---";
|
|
75485
|
+
const SCRIPT_TAG_NAME = "script";
|
|
75486
|
+
const SCRIPT_OPEN = `<${SCRIPT_TAG_NAME}`;
|
|
75487
|
+
const SCRIPT_CLOSE = `</${SCRIPT_TAG_NAME}`;
|
|
75488
|
+
const TEMPLATE_TAG_NAME = "template";
|
|
75489
|
+
const TEMPLATE_CLOSE = `</${TEMPLATE_TAG_NAME}`;
|
|
75490
|
+
const JAVASCRIPT_MIME_TYPES = new Set([
|
|
75491
|
+
"application/ecmascript",
|
|
75492
|
+
"application/javascript",
|
|
75493
|
+
"application/x-ecmascript",
|
|
75494
|
+
"application/x-javascript",
|
|
75495
|
+
"text/ecmascript",
|
|
75496
|
+
"text/javascript",
|
|
75497
|
+
"text/javascript1.0",
|
|
75498
|
+
"text/javascript1.1",
|
|
75499
|
+
"text/javascript1.2",
|
|
75500
|
+
"text/javascript1.3",
|
|
75501
|
+
"text/javascript1.4",
|
|
75502
|
+
"text/javascript1.5",
|
|
75503
|
+
"text/jscript",
|
|
75504
|
+
"text/livescript",
|
|
75505
|
+
"text/x-ecmascript",
|
|
75506
|
+
"text/x-javascript"
|
|
75507
|
+
]);
|
|
75508
|
+
const RAW_TEXT_TAG_NAMES = new Set([
|
|
75509
|
+
"iframe",
|
|
75510
|
+
"noembed",
|
|
75511
|
+
"noframes",
|
|
75512
|
+
"noscript",
|
|
75513
|
+
"style",
|
|
75514
|
+
"textarea",
|
|
75515
|
+
"title",
|
|
75516
|
+
"xmp"
|
|
75517
|
+
]);
|
|
75518
|
+
const PLAINTEXT_TAG_NAME = "plaintext";
|
|
75519
|
+
const TAG_OPEN_UTF8_BYTE = "<".charCodeAt(0);
|
|
75520
|
+
const TAG_CLOSE_UTF8_BYTE = ">".charCodeAt(0);
|
|
75521
|
+
const SINGLE_QUOTE_UTF8_BYTE = "'".charCodeAt(0);
|
|
75522
|
+
const DOUBLE_QUOTE_UTF8_BYTE = "\"".charCodeAt(0);
|
|
75523
|
+
const ATTRIBUTE_ASSIGNMENT_UTF8_BYTE = "=".charCodeAt(0);
|
|
75524
|
+
const TAG_SELF_CLOSE_UTF8_BYTE = "/".charCodeAt(0);
|
|
75525
|
+
const TAB_UTF8_BYTE = " ".charCodeAt(0);
|
|
75526
|
+
const FORM_FEED_UTF8_BYTE = "\f".charCodeAt(0);
|
|
75527
|
+
const isHtmlWhitespace = (byte) => byte === TAB_UTF8_BYTE || byte === 10 || byte === FORM_FEED_UTF8_BYTE || byte === 13 || byte === 32;
|
|
75528
|
+
const matchesAsciiCaseInsensitive = (sourceBuffer, startByte, expected) => {
|
|
75529
|
+
if (startByte + expected.length > sourceBuffer.length) return false;
|
|
75530
|
+
for (let expectedIndex = 0; expectedIndex < expected.length; expectedIndex++) {
|
|
75531
|
+
const sourceByte = sourceBuffer[startByte + expectedIndex];
|
|
75532
|
+
if (sourceByte === void 0 || String.fromCharCode(sourceByte).toLowerCase() !== expected[expectedIndex]) return false;
|
|
75533
|
+
}
|
|
75534
|
+
return true;
|
|
75535
|
+
};
|
|
75536
|
+
const isTagBoundary = (byte) => byte === TAG_CLOSE_UTF8_BYTE || byte === TAG_SELF_CLOSE_UTF8_BYTE || isHtmlWhitespace(byte);
|
|
75537
|
+
const isPotentialTagStart = (byte) => {
|
|
75538
|
+
if (byte === void 0) return false;
|
|
75539
|
+
return /[A-Za-z!/?]/.test(String.fromCharCode(byte));
|
|
75540
|
+
};
|
|
75541
|
+
const findLineEnd = (sourceBuffer, lineStartByte) => {
|
|
75542
|
+
let byteIndex = lineStartByte;
|
|
75543
|
+
while (byteIndex < sourceBuffer.length && sourceBuffer[byteIndex] !== 10 && sourceBuffer[byteIndex] !== 13) byteIndex++;
|
|
75544
|
+
return byteIndex;
|
|
75545
|
+
};
|
|
75546
|
+
const findNextLineStart = (sourceBuffer, lineStartByte) => {
|
|
75547
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
75548
|
+
if (sourceBuffer[lineEndByte] === 13 && sourceBuffer[lineEndByte + 1] === 10) return lineEndByte + 2;
|
|
75549
|
+
return Math.min(lineEndByte + 1, sourceBuffer.length);
|
|
75550
|
+
};
|
|
75551
|
+
const isFrontmatterFenceLine = (sourceBuffer, lineStartByte) => {
|
|
75552
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, lineStartByte, FRONTMATTER_FENCE)) return false;
|
|
75553
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
75554
|
+
for (let byteIndex = lineStartByte + 3; byteIndex < lineEndByte; byteIndex++) if (!isHtmlWhitespace(sourceBuffer[byteIndex])) return false;
|
|
75555
|
+
return true;
|
|
75556
|
+
};
|
|
75557
|
+
const findFrontmatterEnd = (sourceBuffer) => {
|
|
75558
|
+
if (!isFrontmatterFenceLine(sourceBuffer, 0)) return 0;
|
|
75559
|
+
const openingFenceEndByte = findLineEnd(sourceBuffer, 0);
|
|
75560
|
+
let lineStartByte = findNextLineStart(sourceBuffer, 0);
|
|
75561
|
+
while (lineStartByte < sourceBuffer.length) {
|
|
75562
|
+
if (isFrontmatterFenceLine(sourceBuffer, lineStartByte)) return findLineEnd(sourceBuffer, lineStartByte);
|
|
75563
|
+
lineStartByte = findNextLineStart(sourceBuffer, lineStartByte);
|
|
75564
|
+
}
|
|
75565
|
+
return openingFenceEndByte;
|
|
75566
|
+
};
|
|
75567
|
+
const maskByteRange = (maskedBuffer, startByte, endByte) => {
|
|
75568
|
+
for (let byteIndex = startByte; byteIndex < endByte; byteIndex++) {
|
|
75569
|
+
const byte = maskedBuffer[byteIndex];
|
|
75570
|
+
if (byte !== 10 && byte !== 13) maskedBuffer[byteIndex] = 32;
|
|
75571
|
+
}
|
|
75572
|
+
};
|
|
75573
|
+
const readStartTagName = (sourceBuffer, tagStartByte) => {
|
|
75574
|
+
const firstNameByte = sourceBuffer[tagStartByte + 1];
|
|
75575
|
+
if (firstNameByte === void 0 || !/[A-Za-z]/.test(String.fromCharCode(firstNameByte))) return null;
|
|
75576
|
+
let nameEndByte = tagStartByte + 2;
|
|
75577
|
+
while (nameEndByte < sourceBuffer.length && /[A-Za-z0-9:-]/.test(String.fromCharCode(sourceBuffer[nameEndByte] ?? 32))) nameEndByte++;
|
|
75578
|
+
return sourceBuffer.subarray(tagStartByte + 1, nameEndByte).toString("ascii").toLowerCase();
|
|
75579
|
+
};
|
|
75580
|
+
const findTagEnd = (sourceBuffer, startByte) => {
|
|
75581
|
+
let quoteByte = null;
|
|
75582
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) {
|
|
75583
|
+
const byte = sourceBuffer[byteIndex];
|
|
75584
|
+
if (quoteByte !== null) {
|
|
75585
|
+
if (byte === quoteByte) quoteByte = null;
|
|
75586
|
+
continue;
|
|
75587
|
+
}
|
|
75588
|
+
if (byte === SINGLE_QUOTE_UTF8_BYTE || byte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
75589
|
+
quoteByte = byte;
|
|
75590
|
+
continue;
|
|
75591
|
+
}
|
|
75592
|
+
if (byte === TAG_CLOSE_UTF8_BYTE) return byteIndex;
|
|
75593
|
+
}
|
|
75594
|
+
return sourceBuffer.length;
|
|
75595
|
+
};
|
|
75596
|
+
const parseScriptAttributes = (sourceBuffer, attributesStartByte, tagEndByte) => {
|
|
75597
|
+
let byteIndex = attributesStartByte;
|
|
75598
|
+
let hasSource = false;
|
|
75599
|
+
let language = null;
|
|
75600
|
+
let scriptType = null;
|
|
75601
|
+
while (byteIndex < tagEndByte) {
|
|
75602
|
+
while (byteIndex < tagEndByte && (isHtmlWhitespace(sourceBuffer[byteIndex]) || sourceBuffer[byteIndex] === TAG_SELF_CLOSE_UTF8_BYTE)) byteIndex++;
|
|
75603
|
+
const attributeNameStartByte = byteIndex;
|
|
75604
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== ATTRIBUTE_ASSIGNMENT_UTF8_BYTE && sourceBuffer[byteIndex] !== TAG_SELF_CLOSE_UTF8_BYTE) byteIndex++;
|
|
75605
|
+
const attributeName = sourceBuffer.subarray(attributeNameStartByte, byteIndex).toString("ascii").toLowerCase();
|
|
75606
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
75607
|
+
let attributeValue = "";
|
|
75608
|
+
if (sourceBuffer[byteIndex] === ATTRIBUTE_ASSIGNMENT_UTF8_BYTE) {
|
|
75609
|
+
byteIndex++;
|
|
75610
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
75611
|
+
const quoteByte = sourceBuffer[byteIndex];
|
|
75612
|
+
if (quoteByte === SINGLE_QUOTE_UTF8_BYTE || quoteByte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
75613
|
+
const valueStartByte = byteIndex + 1;
|
|
75614
|
+
byteIndex = valueStartByte;
|
|
75615
|
+
while (byteIndex < tagEndByte && sourceBuffer[byteIndex] !== quoteByte) byteIndex++;
|
|
75616
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
75617
|
+
if (byteIndex < tagEndByte) byteIndex++;
|
|
75618
|
+
} else {
|
|
75619
|
+
const valueStartByte = byteIndex;
|
|
75620
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== TAG_CLOSE_UTF8_BYTE) byteIndex++;
|
|
75621
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
75622
|
+
}
|
|
75623
|
+
}
|
|
75624
|
+
if (attributeName === "src") hasSource = true;
|
|
75625
|
+
else if (attributeName === "type" && scriptType === null) scriptType = attributeValue;
|
|
75626
|
+
else if (attributeName === "language" && language === null) language = attributeValue;
|
|
75627
|
+
}
|
|
75628
|
+
return {
|
|
75629
|
+
hasSource,
|
|
75630
|
+
language,
|
|
75631
|
+
type: scriptType
|
|
75632
|
+
};
|
|
75633
|
+
};
|
|
75634
|
+
const isExecutableScript = (attributes) => {
|
|
75635
|
+
if (attributes.hasSource) return false;
|
|
75636
|
+
const type = attributes.type?.trim().toLowerCase() ?? "";
|
|
75637
|
+
if (type !== "") {
|
|
75638
|
+
const mimeType = type.split(";")[0]?.trim() ?? "";
|
|
75639
|
+
return mimeType === "module" || JAVASCRIPT_MIME_TYPES.has(mimeType);
|
|
75640
|
+
}
|
|
75641
|
+
const language = attributes.language?.trim().toLowerCase() ?? "";
|
|
75642
|
+
return language === "" || JAVASCRIPT_MIME_TYPES.has(`text/${language}`);
|
|
75643
|
+
};
|
|
75644
|
+
const findElementClose = (sourceBuffer, startByte, tagName) => {
|
|
75645
|
+
const closeTagStart = `</${tagName}`;
|
|
75646
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) if (sourceBuffer[byteIndex] === TAG_OPEN_UTF8_BYTE && matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, closeTagStart) && isTagBoundary(sourceBuffer[byteIndex + closeTagStart.length])) return byteIndex;
|
|
75647
|
+
return sourceBuffer.length;
|
|
75648
|
+
};
|
|
75649
|
+
const prepareHtmlScriptSource = (sourceBuffer) => {
|
|
75650
|
+
const frontmatterEndByte = findFrontmatterEnd(sourceBuffer);
|
|
75651
|
+
let maskedBuffer = frontmatterEndByte > 0 ? Buffer.from(sourceBuffer) : null;
|
|
75652
|
+
if (maskedBuffer !== null) maskByteRange(maskedBuffer, 0, frontmatterEndByte);
|
|
75653
|
+
const executableScriptBodies = [];
|
|
75654
|
+
let byteIndex = frontmatterEndByte;
|
|
75655
|
+
let templateDepth = 0;
|
|
75656
|
+
while (byteIndex < sourceBuffer.length) {
|
|
75657
|
+
if (sourceBuffer[byteIndex] !== TAG_OPEN_UTF8_BYTE) {
|
|
75658
|
+
byteIndex++;
|
|
75659
|
+
continue;
|
|
75660
|
+
}
|
|
75661
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, COMMENT_OPEN)) {
|
|
75662
|
+
const commentEndByte = sourceBuffer.indexOf(COMMENT_CLOSE, byteIndex + 4);
|
|
75663
|
+
byteIndex = commentEndByte === -1 ? sourceBuffer.length : commentEndByte + 3;
|
|
75664
|
+
continue;
|
|
75665
|
+
}
|
|
75666
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, TEMPLATE_CLOSE) && isTagBoundary(sourceBuffer[byteIndex + TEMPLATE_CLOSE.length])) {
|
|
75667
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + TEMPLATE_CLOSE.length);
|
|
75668
|
+
if (templateDepth > 0) templateDepth--;
|
|
75669
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
75670
|
+
continue;
|
|
75671
|
+
}
|
|
75672
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, SCRIPT_OPEN) || !isTagBoundary(sourceBuffer[byteIndex + SCRIPT_OPEN.length])) {
|
|
75673
|
+
if (!isPotentialTagStart(sourceBuffer[byteIndex + 1])) {
|
|
75674
|
+
byteIndex++;
|
|
75675
|
+
continue;
|
|
75676
|
+
}
|
|
75677
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + 1);
|
|
75678
|
+
const tagName = readStartTagName(sourceBuffer, byteIndex);
|
|
75679
|
+
if (tagName === PLAINTEXT_TAG_NAME) break;
|
|
75680
|
+
if (tagName === TEMPLATE_TAG_NAME) templateDepth++;
|
|
75681
|
+
if (tagName !== null && RAW_TEXT_TAG_NAMES.has(tagName)) {
|
|
75682
|
+
const closeTagStartByte = findElementClose(sourceBuffer, tagEndByte + 1, tagName);
|
|
75683
|
+
if (closeTagStartByte === sourceBuffer.length) break;
|
|
75684
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, closeTagStartByte + tagName.length + 2);
|
|
75685
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
75686
|
+
continue;
|
|
75687
|
+
}
|
|
75688
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
75689
|
+
continue;
|
|
75690
|
+
}
|
|
75691
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + SCRIPT_OPEN.length);
|
|
75692
|
+
if (tagEndByte === sourceBuffer.length) break;
|
|
75693
|
+
const bodyStartByte = tagEndByte + 1;
|
|
75694
|
+
const bodyEndByte = findElementClose(sourceBuffer, bodyStartByte, SCRIPT_TAG_NAME);
|
|
75695
|
+
const attributes = parseScriptAttributes(sourceBuffer, byteIndex + SCRIPT_OPEN.length, tagEndByte);
|
|
75696
|
+
if (attributes.hasSource || templateDepth > 0) {
|
|
75697
|
+
maskedBuffer ??= Buffer.from(sourceBuffer);
|
|
75698
|
+
maskByteRange(maskedBuffer, bodyStartByte, bodyEndByte);
|
|
75699
|
+
} else if (isExecutableScript(attributes)) executableScriptBodies.push(sourceBuffer.subarray(bodyStartByte, bodyEndByte));
|
|
75700
|
+
if (bodyEndByte === sourceBuffer.length) break;
|
|
75701
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, bodyEndByte + SCRIPT_CLOSE.length);
|
|
75702
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
75703
|
+
}
|
|
75704
|
+
return {
|
|
75705
|
+
executableScriptBodies,
|
|
75706
|
+
lintBuffer: maskedBuffer ?? sourceBuffer
|
|
75707
|
+
};
|
|
75708
|
+
};
|
|
75709
|
+
const prepareHtmlLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
|
|
75710
|
+
const lintFiles = [];
|
|
75711
|
+
const sourcePathByLintPath = /* @__PURE__ */ new Map();
|
|
75712
|
+
const sizeByLintPath = /* @__PURE__ */ new Map();
|
|
75713
|
+
const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
|
|
75714
|
+
let htmlFileIndex = 0;
|
|
75715
|
+
let hasThreeModuleImport = false;
|
|
75716
|
+
for (const candidateFile of candidateFiles) {
|
|
75717
|
+
if (!HTML_FILE_PATTERN.test(candidateFile)) {
|
|
75718
|
+
lintFiles.push(candidateFile);
|
|
75719
|
+
continue;
|
|
75720
|
+
}
|
|
75721
|
+
const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
|
|
75722
|
+
const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
|
|
75723
|
+
const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
|
|
75724
|
+
if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
|
|
75725
|
+
const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
|
|
75726
|
+
NFS.writeFileSync(lintPath, lintBuffer);
|
|
75727
|
+
lintFiles.push(lintPath);
|
|
75728
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
75729
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
75730
|
+
hasThreeModuleImport ||= executableScriptBodies.some((scriptBody) => containsThreeModuleImport(scriptBody.toString("utf8")));
|
|
75731
|
+
htmlFileIndex++;
|
|
75732
|
+
}
|
|
75733
|
+
return {
|
|
75734
|
+
lintFiles,
|
|
75735
|
+
sourcePathByLintPath,
|
|
75736
|
+
sizeByLintPath,
|
|
75737
|
+
hasThreeModuleImport
|
|
75738
|
+
};
|
|
75739
|
+
};
|
|
74753
75740
|
/**
|
|
74754
75741
|
* Atomically (re)writes the generated oxlintrc.json. Used twice in
|
|
74755
75742
|
* the runner: once for the primary scan, once for the
|
|
@@ -74910,6 +75897,8 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
74910
75897
|
const runOxlint = async (options) => {
|
|
74911
75898
|
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
74912
75899
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
75900
|
+
const runtimeGlobals = Array.isArray(userConfig?.runtimeGlobals) ? userConfig.runtimeGlobals.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
75901
|
+
let unpluginAutoImportGlobalScopes = [];
|
|
74913
75902
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
74914
75903
|
validateRuleRegistration();
|
|
74915
75904
|
resetManifestCaches();
|
|
@@ -74923,21 +75912,6 @@ const runOxlint = async (options) => {
|
|
|
74923
75912
|
const pluginPath = resolvePluginPath();
|
|
74924
75913
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
74925
75914
|
const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
74926
|
-
const buildConfig = (overrides) => createOxlintConfig({
|
|
74927
|
-
pluginPath,
|
|
74928
|
-
project,
|
|
74929
|
-
customRulesOnly,
|
|
74930
|
-
extendsPaths: overrides.extendsPaths,
|
|
74931
|
-
ignoredTags,
|
|
74932
|
-
includedTags,
|
|
74933
|
-
includeTagDefaults,
|
|
74934
|
-
serverAuthFunctionNames,
|
|
74935
|
-
severityControls,
|
|
74936
|
-
userPlugins,
|
|
74937
|
-
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
74938
|
-
ruleSelection: overrides.ruleSelection,
|
|
74939
|
-
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
74940
|
-
});
|
|
74941
75915
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
74942
75916
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
74943
75917
|
const configPath = Path.join(configDirectory, "oxlintrc.json");
|
|
@@ -74973,7 +75947,36 @@ const runOxlint = async (options) => {
|
|
|
74973
75947
|
await yieldToEventLoop();
|
|
74974
75948
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
74975
75949
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
75950
|
+
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
75951
|
+
rootDirectory,
|
|
75952
|
+
candidateFiles
|
|
75953
|
+
});
|
|
75954
|
+
const preparedHtmlSources = prepareHtmlLintSources(rootDirectory, configDirectory, candidateFiles);
|
|
75955
|
+
const lintFiles = preparedHtmlSources.lintFiles;
|
|
75956
|
+
const hasHtmlFiles = preparedHtmlSources.sourcePathByLintPath.size > 0;
|
|
75957
|
+
const lintProject = !project.hasThree && preparedHtmlSources.hasThreeModuleImport ? {
|
|
75958
|
+
...project,
|
|
75959
|
+
hasThree: true
|
|
75960
|
+
} : project;
|
|
75961
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
75962
|
+
pluginPath,
|
|
75963
|
+
project: lintProject,
|
|
75964
|
+
customRulesOnly,
|
|
75965
|
+
extendsPaths: overrides.extendsPaths,
|
|
75966
|
+
ignoredTags,
|
|
75967
|
+
includedTags,
|
|
75968
|
+
includeTagDefaults,
|
|
75969
|
+
runtimeGlobals,
|
|
75970
|
+
unpluginAutoImportGlobalScopes,
|
|
75971
|
+
serverAuthFunctionNames,
|
|
75972
|
+
severityControls,
|
|
75973
|
+
userPlugins,
|
|
75974
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
75975
|
+
ruleSelection: overrides.ruleSelection,
|
|
75976
|
+
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
75977
|
+
});
|
|
74976
75978
|
const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
|
|
75979
|
+
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedHtmlSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
|
|
74977
75980
|
const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
|
|
74978
75981
|
baseArgs: passBaseArgs,
|
|
74979
75982
|
files: passFiles,
|
|
@@ -75002,7 +76005,8 @@ const runOxlint = async (options) => {
|
|
|
75002
76005
|
fileBatches: passFileBatches,
|
|
75003
76006
|
rootDirectory,
|
|
75004
76007
|
nodeBinaryPath,
|
|
75005
|
-
project,
|
|
76008
|
+
project: lintProject,
|
|
76009
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
75006
76010
|
onPartialFailure: reportPartialFailure,
|
|
75007
76011
|
onAnalyzedFiles: (filePaths) => {
|
|
75008
76012
|
analyzedFiles = filePaths;
|
|
@@ -75037,7 +76041,7 @@ const runOxlint = async (options) => {
|
|
|
75037
76041
|
};
|
|
75038
76042
|
}
|
|
75039
76043
|
};
|
|
75040
|
-
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0) {
|
|
76044
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasHtmlFiles) {
|
|
75041
76045
|
const rulesetHash = computeRulesetHash({
|
|
75042
76046
|
config: buildConfig({
|
|
75043
76047
|
extendsPaths: [],
|
|
@@ -75195,14 +76199,15 @@ const runOxlint = async (options) => {
|
|
|
75195
76199
|
]);
|
|
75196
76200
|
}
|
|
75197
76201
|
const baseArgs = makeBaseArgs(configPath);
|
|
75198
|
-
const fileBatches = buildFileBatches(baseArgs,
|
|
76202
|
+
const fileBatches = buildFileBatches(baseArgs, lintFiles);
|
|
75199
76203
|
let analyzedFiles = [];
|
|
75200
76204
|
const runBatches = () => spawnLintBatches({
|
|
75201
76205
|
baseArgs,
|
|
75202
76206
|
fileBatches,
|
|
75203
76207
|
rootDirectory,
|
|
75204
76208
|
nodeBinaryPath,
|
|
75205
|
-
project,
|
|
76209
|
+
project: lintProject,
|
|
76210
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
75206
76211
|
onPartialFailure,
|
|
75207
76212
|
onAnalyzedFiles: (filePaths) => {
|
|
75208
76213
|
analyzedFiles = filePaths;
|
|
@@ -77409,7 +78414,7 @@ const makeNoopConsole = () => ({
|
|
|
77409
78414
|
});
|
|
77410
78415
|
//#endregion
|
|
77411
78416
|
//#region src/cli/utils/version.ts
|
|
77412
|
-
const VERSION = "0.9.
|
|
78417
|
+
const VERSION = "0.9.1-dev.1aa6b12";
|
|
77413
78418
|
//#endregion
|
|
77414
78419
|
//#region src/cli/utils/json-mode.ts
|
|
77415
78420
|
let context = null;
|
|
@@ -77767,13 +78772,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
77767
78772
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
77768
78773
|
* standard `SENTRY_RELEASE` override.
|
|
77769
78774
|
*/
|
|
77770
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.
|
|
78775
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.1-dev.1aa6b12`;
|
|
77771
78776
|
/**
|
|
77772
78777
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
77773
78778
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
77774
78779
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
77775
78780
|
*/
|
|
77776
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.
|
|
78781
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.1-dev.1aa6b12") ? "development" : "production");
|
|
77777
78782
|
/**
|
|
77778
78783
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
77779
78784
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -90438,6 +91443,7 @@ const buildScanAttributes = (input) => {
|
|
|
90438
91443
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
90439
91444
|
fileCount: input.result?.scannedFileCount ?? null,
|
|
90440
91445
|
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null,
|
|
91446
|
+
htmlFileCount: input.result?.analyzedFiles?.filter((filePath) => HTML_FILE_PATTERN.test(filePath)).length ?? null,
|
|
90441
91447
|
multilineDiagnosticCount: input.result?.diagnostics.filter((diagnostic) => (diagnostic.endLine ?? diagnostic.line) > diagnostic.line).length ?? null
|
|
90442
91448
|
});
|
|
90443
91449
|
};
|
|
@@ -96468,7 +97474,7 @@ ${formatExampleLines([
|
|
|
96468
97474
|
])}
|
|
96469
97475
|
|
|
96470
97476
|
${highlighter.dim("Scope:")}
|
|
96471
|
-
Runs
|
|
97477
|
+
Runs every rule tagged ${highlighter.info("design")}; all design rules stay opt-in during a general health scan.
|
|
96472
97478
|
Dead-code, supply-chain, external lint-config, custom-plugin, and health-score passes are skipped.
|
|
96473
97479
|
Standard scan flags such as ${highlighter.info("--scope")}, ${highlighter.info("--project")}, ${highlighter.info("--verbose")}, and ${highlighter.info("--json")} still work.
|
|
96474
97480
|
`;
|
|
@@ -96491,7 +97497,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
96491
97497
|
${highlighter.info(CI_URL)}
|
|
96492
97498
|
`;
|
|
96493
97499
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
96494
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
97500
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS and inline HTML script source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
96495
97501
|
program.action(inspectAction);
|
|
96496
97502
|
program.command("design [directory]").description("Run only the focused UI design diagnostics").addHelpText("after", renderDesignHelpEpilog).action((directory, _options, command) => designAction(directory ?? ".", command.optsWithGlobals()));
|
|
96497
97503
|
program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
|
|
@@ -96571,4 +97577,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
96571
97577
|
export { toForwardSlashes as A, highlighter as B, buildRulePriorityMap as C, resolveBlockingLevel as D, formatLearnMoreLine as E, isCiEnvironment as F, sync as G, mergeReactDoctorConfigs as H, DIAGNOSTIC_CATEGORY_BUCKETS as I, void_ as K, Progress as L, isUnicodeSupported as M, METRIC as N, isReactDoctorWorkflowInstalled as O, TUI_REPORT_DETAIL_WIDTH_FRACTION as P, Reporter as R, hasLintHardFailure as S, formatFixRecipeLine as T, resolveScanTarget as U, mapWithConcurrency as V, runPromise as W, canAnimateOnboarding as _, resolveCliInspectOptions as a, buildCodeFrame as b, detectLaunchableAgents as c, launchCliAgent as d, isShareOptedOut as f, doctorFace as g, easeOutCubic as h, selectProjects as i, findNearestPackageDirectory as j, recordCount as k, CLI_AGENT_BINARIES as l, printFooter as m, shouldFailScanGate as n, countUniqueScannedFiles as o, inspect as p, succeed$3 as q, discoverWorkspacePackages as r, setUpGitHubActions as s, exitGracefully as t, copyToClipboard as u, computeProjectedScore as v, buildSortedRuleGroups as w, buildNoScoreMessage as x, formatElapsedTime as y, getCategoryImpact as z };
|
|
96572
97578
|
|
|
96573
97579
|
//# sourceMappingURL=cli.js.map
|
|
96574
|
-
//# debugId=
|
|
97580
|
+
//# debugId=f34e66dd-4b16-53f5-a3af-9844fbc71772
|