react-doctor 0.9.0-dev.db9d300 → 0.9.1-dev.49c5c1e
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 +998 -86
- package/dist/index.d.ts +2 -2
- package/dist/index.js +992 -81
- package/dist/lsp.js +995 -83
- package/package.json +6 -6
package/dist/index.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]="5ad39650-1163-5117-aad5-472963ee3867")}catch(e){}}();
|
|
3
3
|
import { i as __toESM$1, r as __require, t as __commonJSMin$1 } from "./chunk-ChKA3wi6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
@@ -61448,7 +61448,8 @@ var AmbiguousProjectError = class extends Error {
|
|
|
61448
61448
|
}
|
|
61449
61449
|
};
|
|
61450
61450
|
const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
|
|
61451
|
-
const
|
|
61451
|
+
const HTML_FILE_PATTERN = /\.html$/i;
|
|
61452
|
+
const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
61452
61453
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
61453
61454
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
61454
61455
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
@@ -61791,7 +61792,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
61791
61792
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
61792
61793
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
61793
61794
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
61794
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
61795
|
+
const CORE_PACKAGE_VERSION = "0.9.1";
|
|
61795
61796
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
61796
61797
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
61797
61798
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -62182,6 +62183,7 @@ const frameworkMergeRank = (framework) => {
|
|
|
62182
62183
|
return MOBILE_FRAMEWORKS.has(framework) ? 2 : 1;
|
|
62183
62184
|
};
|
|
62184
62185
|
const REACT_COMPILER_LINT_PACKAGES = new Set(["eslint-plugin-react-compiler"]);
|
|
62186
|
+
const REACT_COMPILER_RUNTIME_PACKAGES = new Set(["react-compiler-runtime"]);
|
|
62185
62187
|
const NEXT_CONFIG_FILENAMES = [
|
|
62186
62188
|
"next.config.js",
|
|
62187
62189
|
"next.config.mjs",
|
|
@@ -62284,10 +62286,10 @@ const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
|
62284
62286
|
]).find(isFile) ?? null;
|
|
62285
62287
|
};
|
|
62286
62288
|
const parseConfigSourceFile = (filePath, content) => filePath.endsWith(".json") || Path.basename(filePath) === ".babelrc" ? ts.parseJsonText(filePath, content) : ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
62287
|
-
const getStaticPropertyName$
|
|
62289
|
+
const getStaticPropertyName$2 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
|
|
62288
62290
|
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");
|
|
62289
62291
|
const hasExportModifier = (node) => ts.canHaveModifiers(node) && Boolean(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
|
|
62290
|
-
const getRequireModuleSpecifier = (expression) => {
|
|
62292
|
+
const getRequireModuleSpecifier$1 = (expression) => {
|
|
62291
62293
|
if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "require" || expression.arguments.length !== 1) return null;
|
|
62292
62294
|
const moduleSpecifier = expression.arguments[0];
|
|
62293
62295
|
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
@@ -62300,7 +62302,7 @@ const hasTopLevelValueBinding = (sourceFile, bindingName) => sourceFile.statemen
|
|
|
62300
62302
|
const namedBindings = importClause?.namedBindings;
|
|
62301
62303
|
return namedBindings ? ts.isNamespaceImport(namedBindings) ? namedBindings.name.text === bindingName : namedBindings.elements.some((element) => element.name.text === bindingName) : false;
|
|
62302
62304
|
}
|
|
62303
|
-
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) =>
|
|
62305
|
+
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContainsIdentifier(declaration.name, bindingName));
|
|
62304
62306
|
return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === bindingName;
|
|
62305
62307
|
});
|
|
62306
62308
|
const getImportBinding = (sourceFile, bindingName) => {
|
|
@@ -62331,24 +62333,24 @@ const getImportBinding = (sourceFile, bindingName) => {
|
|
|
62331
62333
|
for (const declaration of statement.declarationList.declarations) {
|
|
62332
62334
|
if (!declaration.initializer) continue;
|
|
62333
62335
|
if (ts.isIdentifier(declaration.name) && declaration.name.text === bindingName) {
|
|
62334
|
-
const directModuleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
62336
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
62335
62337
|
if (directModuleSpecifier) return {
|
|
62336
62338
|
moduleSpecifier: directModuleSpecifier,
|
|
62337
62339
|
exportName: "default",
|
|
62338
62340
|
isNamespace: true
|
|
62339
62341
|
};
|
|
62340
|
-
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier(declaration.initializer.expression) !== null) return {
|
|
62341
|
-
moduleSpecifier: getRequireModuleSpecifier(declaration.initializer.expression) ?? "",
|
|
62342
|
+
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier$1(declaration.initializer.expression) !== null) return {
|
|
62343
|
+
moduleSpecifier: getRequireModuleSpecifier$1(declaration.initializer.expression) ?? "",
|
|
62342
62344
|
exportName: declaration.initializer.name.text,
|
|
62343
62345
|
isNamespace: false
|
|
62344
62346
|
};
|
|
62345
62347
|
}
|
|
62346
62348
|
if (!ts.isObjectBindingPattern(declaration.name)) continue;
|
|
62347
62349
|
const bindingElement = declaration.name.elements.find((element) => ts.isIdentifier(element.name) && element.name.text === bindingName);
|
|
62348
|
-
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
62350
|
+
const moduleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
62349
62351
|
if (bindingElement && moduleSpecifier) return {
|
|
62350
62352
|
moduleSpecifier,
|
|
62351
|
-
exportName: bindingElement.propertyName ? getStaticPropertyName$
|
|
62353
|
+
exportName: bindingElement.propertyName ? getStaticPropertyName$2(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
|
|
62352
62354
|
isNamespace: false
|
|
62353
62355
|
};
|
|
62354
62356
|
}
|
|
@@ -62401,6 +62403,48 @@ const getScopedConfigBinding = (identifier) => {
|
|
|
62401
62403
|
};
|
|
62402
62404
|
};
|
|
62403
62405
|
const isCompilerTransformModule = (moduleSpecifier, exportName) => moduleSpecifier === "babel-plugin-react-compiler" && exportName === "default" || moduleSpecifier === "@vitejs/plugin-react" && exportName === "reactCompilerPreset";
|
|
62406
|
+
const NODE_MODULE_SPECIFIERS = new Set(["module", "node:module"]);
|
|
62407
|
+
const isConstantVariableInitializer = (node) => ts.isExpression(node) && ts.isVariableDeclaration(node.parent) && ts.isVariableDeclarationList(node.parent.parent) && Boolean(node.parent.parent.flags & ts.NodeFlags.Const);
|
|
62408
|
+
const isNodeCreateRequireCall = (node, analysis) => {
|
|
62409
|
+
if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isTypeAssertionExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isAwaitExpression(node)) return isNodeCreateRequireCall(node.expression, analysis);
|
|
62410
|
+
if (!ts.isCallExpression(node)) return false;
|
|
62411
|
+
const target = node.expression;
|
|
62412
|
+
if (ts.isIdentifier(target)) {
|
|
62413
|
+
if (analysis.localBindings.has(target.text) || getScopedConfigBinding(target).wasFound) return false;
|
|
62414
|
+
const importBinding = getImportBinding(analysis.sourceFile, target.text);
|
|
62415
|
+
return Boolean(importBinding && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier) && importBinding.exportName === "createRequire");
|
|
62416
|
+
}
|
|
62417
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return false;
|
|
62418
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "createRequire") return false;
|
|
62419
|
+
const createRequireReceiver = target.expression;
|
|
62420
|
+
if (ts.isCallExpression(createRequireReceiver)) {
|
|
62421
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(createRequireReceiver);
|
|
62422
|
+
if (requiredModuleSpecifier === null || !NODE_MODULE_SPECIFIERS.has(requiredModuleSpecifier) || !ts.isIdentifier(createRequireReceiver.expression)) return false;
|
|
62423
|
+
const requireIdentifier = createRequireReceiver.expression;
|
|
62424
|
+
return !analysis.localBindings.has(requireIdentifier.text) && !getScopedConfigBinding(requireIdentifier).wasFound && !hasTopLevelValueBinding(analysis.sourceFile, requireIdentifier.text);
|
|
62425
|
+
}
|
|
62426
|
+
if (!ts.isIdentifier(createRequireReceiver)) return false;
|
|
62427
|
+
if (analysis.localBindings.has(createRequireReceiver.text) || getScopedConfigBinding(createRequireReceiver).wasFound) return false;
|
|
62428
|
+
const importBinding = getImportBinding(analysis.sourceFile, createRequireReceiver.text);
|
|
62429
|
+
return Boolean(importBinding?.isNamespace && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier));
|
|
62430
|
+
};
|
|
62431
|
+
const getNodeRequireResolveModuleSpecifier = (callExpression, analysis) => {
|
|
62432
|
+
const [moduleSpecifierNode] = callExpression.arguments;
|
|
62433
|
+
if (!moduleSpecifierNode || !ts.isStringLiteralLike(moduleSpecifierNode)) return null;
|
|
62434
|
+
const target = callExpression.expression;
|
|
62435
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
62436
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "resolve") return null;
|
|
62437
|
+
if (isNodeCreateRequireCall(target.expression, analysis)) return moduleSpecifierNode.text;
|
|
62438
|
+
if (!ts.isIdentifier(target.expression)) return null;
|
|
62439
|
+
const resolverIdentifier = target.expression;
|
|
62440
|
+
if (analysis.localBindings.has(resolverIdentifier.text)) return null;
|
|
62441
|
+
const scopedBinding = getScopedConfigBinding(resolverIdentifier);
|
|
62442
|
+
const topLevelBinding = scopedBinding.wasFound ? null : getTopLevelBinding(analysis.sourceFile, resolverIdentifier.text);
|
|
62443
|
+
const resolverInitializer = scopedBinding.wasFound ? scopedBinding.initializer : topLevelBinding;
|
|
62444
|
+
if (resolverInitializer === null && !scopedBinding.wasFound && resolverIdentifier.text === "require" && !hasTopLevelValueBinding(analysis.sourceFile, resolverIdentifier.text) && getImportBinding(analysis.sourceFile, resolverIdentifier.text) === null) return moduleSpecifierNode.text;
|
|
62445
|
+
if (!resolverInitializer || !isConstantVariableInitializer(resolverInitializer) || !isNodeCreateRequireCall(resolverInitializer, analysis)) return null;
|
|
62446
|
+
return moduleSpecifierNode.text;
|
|
62447
|
+
};
|
|
62404
62448
|
const getAssignedPropertyInitializer = (identifier, propertyName) => {
|
|
62405
62449
|
let bindingScope = null;
|
|
62406
62450
|
let currentNode = identifier;
|
|
@@ -62509,7 +62553,7 @@ const getReactCompilerFlagState = (expression, analysis) => {
|
|
|
62509
62553
|
}
|
|
62510
62554
|
if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
|
|
62511
62555
|
for (const property of [...unwrappedExpression.properties].reverse()) {
|
|
62512
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62556
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
|
|
62513
62557
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
|
|
62514
62558
|
if (ts.isSpreadAssignment(property)) {
|
|
62515
62559
|
const spreadState = getReactCompilerFlagState(property.expression, analysis);
|
|
@@ -62535,8 +62579,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
62535
62579
|
}
|
|
62536
62580
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
|
|
62537
62581
|
for (const property of [...resolvedExpression.properties].reverse()) {
|
|
62538
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62539
|
-
if (ts.isMethodDeclaration(property) && getStaticPropertyName$
|
|
62582
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return property.initializer;
|
|
62583
|
+
if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return property;
|
|
62540
62584
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return property.name;
|
|
62541
62585
|
if (ts.isSpreadAssignment(property)) {
|
|
62542
62586
|
const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
|
|
@@ -62567,7 +62611,7 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
62567
62611
|
return resolvedExpression.properties.some((property) => {
|
|
62568
62612
|
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
|
|
62569
62613
|
if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
|
|
62570
|
-
const staticPropertyName = getStaticPropertyName$
|
|
62614
|
+
const staticPropertyName = getStaticPropertyName$2(property.name);
|
|
62571
62615
|
return staticPropertyName === null || staticPropertyName === propertyName;
|
|
62572
62616
|
}
|
|
62573
62617
|
return false;
|
|
@@ -62586,7 +62630,7 @@ const getExportedConfigNodes = (sourceFile, exportName) => {
|
|
|
62586
62630
|
continue;
|
|
62587
62631
|
}
|
|
62588
62632
|
if (ts.isExpressionStatement(statement) && isCommonJsConfigExportAssignment(statement.expression, sourceFile) && exportName !== "default" && ts.isObjectLiteralExpression(statement.expression.right)) for (const property of [...statement.expression.right.properties].reverse()) {
|
|
62589
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62633
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === exportName) {
|
|
62590
62634
|
exportedNodes.push(property.initializer);
|
|
62591
62635
|
break;
|
|
62592
62636
|
}
|
|
@@ -62716,7 +62760,7 @@ const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransfor
|
|
|
62716
62760
|
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
62717
62761
|
const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
|
|
62718
62762
|
if (propertyName === null) return null;
|
|
62719
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(target.expression);
|
|
62763
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
|
|
62720
62764
|
if (requiredModuleSpecifier !== null) {
|
|
62721
62765
|
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
62722
62766
|
if (!requiredModuleSpecifier.startsWith(".")) return null;
|
|
@@ -62745,10 +62789,10 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62745
62789
|
const reactCompilerFlagState = excludedPropertyNames?.has("reactCompiler") ? null : getReactCompilerFlagState(node, analysis);
|
|
62746
62790
|
if (reactCompilerFlagState?.isEnabled) return true;
|
|
62747
62791
|
for (const [propertyIndex, property] of node.properties.entries()) if (ts.isPropertyAssignment(property)) {
|
|
62748
|
-
const propertyName = getStaticPropertyName$
|
|
62792
|
+
const propertyName = getStaticPropertyName$2(property.name);
|
|
62749
62793
|
if (propertyName && excludedPropertyNames?.has(propertyName)) continue;
|
|
62750
62794
|
if (propertyName === "reactCompiler") continue;
|
|
62751
|
-
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$
|
|
62795
|
+
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;
|
|
62752
62796
|
const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
|
|
62753
62797
|
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer) && property.initializer.text.startsWith(".")) {
|
|
62754
62798
|
const extendedFilePath = resolveImportedConfigFile(analysis.filePath, property.initializer.text);
|
|
@@ -62758,12 +62802,12 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62758
62802
|
} else if (ts.isShorthandPropertyAssignment(property)) {
|
|
62759
62803
|
if (excludedPropertyNames?.has(property.name.text)) continue;
|
|
62760
62804
|
if (property.name.text === "reactCompiler") continue;
|
|
62761
|
-
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$
|
|
62805
|
+
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;
|
|
62762
62806
|
const propertyAllowsCompilerTransform = property.name.text === "plugins" || property.name.text === "presets";
|
|
62763
62807
|
if (analyzeConfigNode(property.name, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
62764
62808
|
} else if (ts.isSpreadAssignment(property)) {
|
|
62765
62809
|
if (reactCompilerFlagState && getReactCompilerFlagState(property.expression, analysis) !== null) continue;
|
|
62766
|
-
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$
|
|
62810
|
+
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;
|
|
62767
62811
|
if (analyzeConfigNode(property.expression, analysis, allowCompilerTransform, false, excludedPropertyNames)) return true;
|
|
62768
62812
|
}
|
|
62769
62813
|
return false;
|
|
@@ -62776,9 +62820,11 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62776
62820
|
});
|
|
62777
62821
|
}
|
|
62778
62822
|
if (ts.isCallExpression(node)) {
|
|
62823
|
+
const resolvedModuleSpecifier = getNodeRequireResolveModuleSpecifier(node, analysis);
|
|
62824
|
+
if (resolvedModuleSpecifier !== null) return allowCompilerTransform && isCompilerTransformModule(resolvedModuleSpecifier, "default");
|
|
62779
62825
|
const callTargetResult = analyzeConfigCallTarget(node, analysis, allowCompilerTransform);
|
|
62780
62826
|
if (callTargetResult !== null) return callTargetResult;
|
|
62781
|
-
const directModuleSpecifier = getRequireModuleSpecifier(node);
|
|
62827
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(node);
|
|
62782
62828
|
const isRequireShadowed = analysis.localBindings.has("require") || ts.isIdentifier(node.expression) && getScopedConfigBinding(node.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require");
|
|
62783
62829
|
if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
62784
62830
|
if (directModuleSpecifier && !isRequireShadowed) {
|
|
@@ -62800,7 +62846,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62800
62846
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform) || node.arguments.some((argument) => analyzeConfigNode(argument, analysis, false));
|
|
62801
62847
|
}
|
|
62802
62848
|
if (ts.isPropertyAccessExpression(node)) {
|
|
62803
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(node.expression);
|
|
62849
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
|
|
62804
62850
|
if (requiredModuleSpecifier) {
|
|
62805
62851
|
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
62806
62852
|
if (requiredModuleSpecifier.startsWith(".")) {
|
|
@@ -62888,7 +62934,7 @@ const hasCompilerConfigurationInAncestors = (directory) => {
|
|
|
62888
62934
|
}
|
|
62889
62935
|
return false;
|
|
62890
62936
|
};
|
|
62891
|
-
const detectReactCompiler = (directory, packageJson) => hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
62937
|
+
const detectReactCompiler = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
62892
62938
|
const detectReactCompilerLintPlugin = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_LINT_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_LINT_PACKAGES);
|
|
62893
62939
|
const detectNextjsStaticExport = (directory) => NEXT_CONFIG_FILENAMES.some((filename) => {
|
|
62894
62940
|
const filePath = Path.join(directory, filename);
|
|
@@ -66137,7 +66183,7 @@ const warn = (message) => {
|
|
|
66137
66183
|
runSync(warn$1(message));
|
|
66138
66184
|
};
|
|
66139
66185
|
const CONFIG_BASENAME = "doctor.config";
|
|
66140
|
-
const CONFIG_EXTENSIONS = [
|
|
66186
|
+
const CONFIG_EXTENSIONS$1 = [
|
|
66141
66187
|
"ts",
|
|
66142
66188
|
"mts",
|
|
66143
66189
|
"cts",
|
|
@@ -66241,7 +66287,7 @@ const loadLegacyConfig = (directory) => {
|
|
|
66241
66287
|
};
|
|
66242
66288
|
const loadConfigFromDirectory = async (directory) => {
|
|
66243
66289
|
let sawBrokenConfigFile = false;
|
|
66244
|
-
for (const extension of CONFIG_EXTENSIONS) {
|
|
66290
|
+
for (const extension of CONFIG_EXTENSIONS$1) {
|
|
66245
66291
|
const filePath = Path.join(directory, `${CONFIG_BASENAME}.${extension}`);
|
|
66246
66292
|
if (!isFile(filePath)) continue;
|
|
66247
66293
|
const isDataFile = DATA_CONFIG_EXTENSIONS.has(extension);
|
|
@@ -66976,6 +67022,321 @@ const buildReactNativeDiagnostic = (input) => ({
|
|
|
66976
67022
|
column: input.column ?? 0,
|
|
66977
67023
|
category: input.category ?? "Correctness"
|
|
66978
67024
|
});
|
|
67025
|
+
const ANDROID_APP_BUILD_FILE_NAMES = ["build.gradle", "build.gradle.kts"];
|
|
67026
|
+
const BUILD_TYPES_BLOCK_PATTERN = /\bbuildTypes\s*\{/g;
|
|
67027
|
+
const RELEASE_STRING_MARKER = "__RD_RELEASE__";
|
|
67028
|
+
const RELEASE_BLOCK_PATTERNS = [/\brelease\s*\{/g, /\b(?:getByName|named)\s*\(\s*(?:["']release["']|__RD_RELEASE__)\s*\)\s*\{/g];
|
|
67029
|
+
const MINIFY_ASSIGNMENT_PATTERN = /\b(?:isMinifyEnabled|minifyEnabled)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
67030
|
+
const SHRINK_RESOURCES_ASSIGNMENT_PATTERN = /\b(?:isShrinkResources|shrinkResources)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
67031
|
+
const stripGradleComments = (contents) => {
|
|
67032
|
+
let result = "";
|
|
67033
|
+
let index = 0;
|
|
67034
|
+
let quote = null;
|
|
67035
|
+
while (index < contents.length) {
|
|
67036
|
+
const character = contents[index];
|
|
67037
|
+
const nextCharacter = contents[index + 1];
|
|
67038
|
+
if (quote !== null) {
|
|
67039
|
+
result += character;
|
|
67040
|
+
if (character === "\\") {
|
|
67041
|
+
result += nextCharacter ?? "";
|
|
67042
|
+
index += 2;
|
|
67043
|
+
continue;
|
|
67044
|
+
}
|
|
67045
|
+
if (character === quote) quote = null;
|
|
67046
|
+
index += 1;
|
|
67047
|
+
continue;
|
|
67048
|
+
}
|
|
67049
|
+
if (character === "\"" || character === "'") {
|
|
67050
|
+
quote = character;
|
|
67051
|
+
result += character;
|
|
67052
|
+
index += 1;
|
|
67053
|
+
continue;
|
|
67054
|
+
}
|
|
67055
|
+
if (character === "/" && nextCharacter === "/") {
|
|
67056
|
+
while (index < contents.length && contents[index] !== "\n") {
|
|
67057
|
+
result += " ";
|
|
67058
|
+
index += 1;
|
|
67059
|
+
}
|
|
67060
|
+
continue;
|
|
67061
|
+
}
|
|
67062
|
+
if (character === "/" && nextCharacter === "*") {
|
|
67063
|
+
result += " ";
|
|
67064
|
+
index += 2;
|
|
67065
|
+
while (index < contents.length && !(contents[index] === "*" && contents[index + 1] === "/")) {
|
|
67066
|
+
result += contents[index] === "\n" ? "\n" : " ";
|
|
67067
|
+
index += 1;
|
|
67068
|
+
}
|
|
67069
|
+
if (index < contents.length) {
|
|
67070
|
+
result += " ";
|
|
67071
|
+
index += 2;
|
|
67072
|
+
}
|
|
67073
|
+
continue;
|
|
67074
|
+
}
|
|
67075
|
+
result += character;
|
|
67076
|
+
index += 1;
|
|
67077
|
+
}
|
|
67078
|
+
return result;
|
|
67079
|
+
};
|
|
67080
|
+
const maskGradleStrings = (contents) => {
|
|
67081
|
+
let result = "";
|
|
67082
|
+
let index = 0;
|
|
67083
|
+
let quote = null;
|
|
67084
|
+
while (index < contents.length) {
|
|
67085
|
+
const character = contents[index];
|
|
67086
|
+
if (quote === null) {
|
|
67087
|
+
if (character === "\"" || character === "'") {
|
|
67088
|
+
quote = character;
|
|
67089
|
+
result += " ";
|
|
67090
|
+
} else result += character;
|
|
67091
|
+
index += 1;
|
|
67092
|
+
continue;
|
|
67093
|
+
}
|
|
67094
|
+
if (character === "\\") {
|
|
67095
|
+
result += " ";
|
|
67096
|
+
index += 2;
|
|
67097
|
+
continue;
|
|
67098
|
+
}
|
|
67099
|
+
if (character === quote) quote = null;
|
|
67100
|
+
result += character === "\n" ? "\n" : " ";
|
|
67101
|
+
index += 1;
|
|
67102
|
+
}
|
|
67103
|
+
return result;
|
|
67104
|
+
};
|
|
67105
|
+
const findBlockContents = (contents, pattern) => {
|
|
67106
|
+
const blocks = [];
|
|
67107
|
+
pattern.lastIndex = 0;
|
|
67108
|
+
let match = pattern.exec(contents);
|
|
67109
|
+
while (match !== null) {
|
|
67110
|
+
const openingBraceIndex = pattern.lastIndex - 1;
|
|
67111
|
+
let depth = 1;
|
|
67112
|
+
let index = openingBraceIndex + 1;
|
|
67113
|
+
let quote = null;
|
|
67114
|
+
while (index < contents.length && depth > 0) {
|
|
67115
|
+
const character = contents[index];
|
|
67116
|
+
if (quote !== null) {
|
|
67117
|
+
if (character === "\\") {
|
|
67118
|
+
index += 2;
|
|
67119
|
+
continue;
|
|
67120
|
+
}
|
|
67121
|
+
if (character === quote) quote = null;
|
|
67122
|
+
} else if (character === "\"" || character === "'") quote = character;
|
|
67123
|
+
else if (character === "{") depth += 1;
|
|
67124
|
+
else if (character === "}") depth -= 1;
|
|
67125
|
+
index += 1;
|
|
67126
|
+
}
|
|
67127
|
+
if (depth === 0) blocks.push(contents.slice(openingBraceIndex + 1, index - 1));
|
|
67128
|
+
match = pattern.exec(contents);
|
|
67129
|
+
}
|
|
67130
|
+
return blocks;
|
|
67131
|
+
};
|
|
67132
|
+
const getFinalStaticBoolean = (contents, pattern) => {
|
|
67133
|
+
pattern.lastIndex = 0;
|
|
67134
|
+
let finalValue = null;
|
|
67135
|
+
let match = pattern.exec(contents);
|
|
67136
|
+
while (match !== null) {
|
|
67137
|
+
const staticValue = match[1]?.trim().replace(/\)$/, "").trim();
|
|
67138
|
+
if (staticValue === "true") finalValue = true;
|
|
67139
|
+
else if (staticValue === "false") finalValue = false;
|
|
67140
|
+
else finalValue = null;
|
|
67141
|
+
match = pattern.exec(contents);
|
|
67142
|
+
}
|
|
67143
|
+
return finalValue;
|
|
67144
|
+
};
|
|
67145
|
+
const getReleaseBlocks = (contents) => findBlockContents(contents, BUILD_TYPES_BLOCK_PATTERN).flatMap((buildTypesBlock) => RELEASE_BLOCK_PATTERNS.flatMap((pattern) => findBlockContents(buildTypesBlock, pattern)));
|
|
67146
|
+
const readAndroidReleaseShrinking = (rootDirectory) => {
|
|
67147
|
+
for (const buildFileName of ANDROID_APP_BUILD_FILE_NAMES) {
|
|
67148
|
+
const filePath = Path.posix.join("android", "app", buildFileName);
|
|
67149
|
+
const absoluteFilePath = Path.join(rootDirectory, filePath);
|
|
67150
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
67151
|
+
let contents;
|
|
67152
|
+
try {
|
|
67153
|
+
contents = stripGradleComments(NFS.readFileSync(absoluteFilePath, "utf-8"));
|
|
67154
|
+
} catch {
|
|
67155
|
+
return null;
|
|
67156
|
+
}
|
|
67157
|
+
const releaseBlocks = getReleaseBlocks(maskGradleStrings(contents.replace(/(["'])release\1/g, RELEASE_STRING_MARKER)));
|
|
67158
|
+
const [releaseBlock] = releaseBlocks;
|
|
67159
|
+
if (releaseBlock === void 0 || releaseBlocks.length !== 1) return null;
|
|
67160
|
+
const hasDisabledMinification = getFinalStaticBoolean(releaseBlock, MINIFY_ASSIGNMENT_PATTERN) === false;
|
|
67161
|
+
const hasDisabledResourceShrinking = getFinalStaticBoolean(releaseBlock, SHRINK_RESOURCES_ASSIGNMENT_PATTERN) === false;
|
|
67162
|
+
if (!hasDisabledMinification && !hasDisabledResourceShrinking) return null;
|
|
67163
|
+
return {
|
|
67164
|
+
filePath,
|
|
67165
|
+
hasDisabledMinification,
|
|
67166
|
+
hasDisabledResourceShrinking
|
|
67167
|
+
};
|
|
67168
|
+
}
|
|
67169
|
+
return null;
|
|
67170
|
+
};
|
|
67171
|
+
const checkReactNativeAndroidReleaseShrinking = (rootDirectory) => {
|
|
67172
|
+
const releaseShrinking = readAndroidReleaseShrinking(rootDirectory);
|
|
67173
|
+
if (releaseShrinking === null) return [];
|
|
67174
|
+
const disabledFeatures = [releaseShrinking.hasDisabledMinification ? "code minification" : null, releaseShrinking.hasDisabledResourceShrinking ? "resource shrinking" : null].filter((feature) => feature !== null);
|
|
67175
|
+
return [buildReactNativeDiagnostic({
|
|
67176
|
+
filePath: releaseShrinking.filePath,
|
|
67177
|
+
rule: "rn-android-release-shrinking-disabled",
|
|
67178
|
+
category: "Performance",
|
|
67179
|
+
message: `The Android release build explicitly disables ${disabledFeatures.join(" and ")}, leaving unreachable code or resources in the shipped app.`,
|
|
67180
|
+
help: "Enable release code minification and resource shrinking, then test the optimized build and add keep rules for libraries that require them."
|
|
67181
|
+
})];
|
|
67182
|
+
};
|
|
67183
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
67184
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
67185
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
67186
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
67187
|
+
return ts.ScriptKind.JS;
|
|
67188
|
+
};
|
|
67189
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
67190
|
+
let currentExpression = expression;
|
|
67191
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
67192
|
+
return currentExpression;
|
|
67193
|
+
};
|
|
67194
|
+
const BABEL_CONFIG_FILE_NAMES$1 = [
|
|
67195
|
+
"babel.config.js",
|
|
67196
|
+
"babel.config.cjs",
|
|
67197
|
+
"babel.config.mjs",
|
|
67198
|
+
"babel.config.ts",
|
|
67199
|
+
"babel.config.cts",
|
|
67200
|
+
"babel.config.json",
|
|
67201
|
+
".babelrc",
|
|
67202
|
+
".babelrc.js",
|
|
67203
|
+
".babelrc.cjs",
|
|
67204
|
+
".babelrc.mjs",
|
|
67205
|
+
".babelrc.cts",
|
|
67206
|
+
".babelrc.json"
|
|
67207
|
+
];
|
|
67208
|
+
const readUnknownPluginNames = (value) => {
|
|
67209
|
+
if (!Array.isArray(value)) return null;
|
|
67210
|
+
const pluginNames = [];
|
|
67211
|
+
for (const entry of value) {
|
|
67212
|
+
if (typeof entry === "string") {
|
|
67213
|
+
pluginNames.push(entry);
|
|
67214
|
+
continue;
|
|
67215
|
+
}
|
|
67216
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
67217
|
+
pluginNames.push(entry[0]);
|
|
67218
|
+
continue;
|
|
67219
|
+
}
|
|
67220
|
+
return null;
|
|
67221
|
+
}
|
|
67222
|
+
return pluginNames;
|
|
67223
|
+
};
|
|
67224
|
+
const getStaticPropertyName$1 = (propertyName) => {
|
|
67225
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName)) return propertyName.text;
|
|
67226
|
+
return null;
|
|
67227
|
+
};
|
|
67228
|
+
const getStaticPluginName = (expression) => {
|
|
67229
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
67230
|
+
if (ts.isStringLiteralLike(unwrappedExpression)) return unwrappedExpression.text;
|
|
67231
|
+
if (!ts.isArrayLiteralExpression(unwrappedExpression)) return null;
|
|
67232
|
+
const pluginExpression = unwrappedExpression.elements[0];
|
|
67233
|
+
return pluginExpression && ts.isStringLiteralLike(pluginExpression) ? pluginExpression.text : null;
|
|
67234
|
+
};
|
|
67235
|
+
const getPluginNamesFromObject = (objectExpression) => {
|
|
67236
|
+
if (objectExpression.properties.some((property) => ts.isSpreadAssignment(property))) return null;
|
|
67237
|
+
const pluginProperties = objectExpression.properties.filter((property) => ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "plugins");
|
|
67238
|
+
if (pluginProperties.length !== 1) return pluginProperties.length === 0 ? [] : null;
|
|
67239
|
+
const pluginListExpression = unwrapTypescriptExpression(pluginProperties[0].initializer);
|
|
67240
|
+
if (!ts.isArrayLiteralExpression(pluginListExpression)) return null;
|
|
67241
|
+
const pluginNames = [];
|
|
67242
|
+
for (const element of pluginListExpression.elements) {
|
|
67243
|
+
if (ts.isSpreadElement(element)) return null;
|
|
67244
|
+
const pluginName = getStaticPluginName(element);
|
|
67245
|
+
if (pluginName === null) return null;
|
|
67246
|
+
pluginNames.push(pluginName);
|
|
67247
|
+
}
|
|
67248
|
+
return pluginNames;
|
|
67249
|
+
};
|
|
67250
|
+
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";
|
|
67251
|
+
const getDirectExportedObject = (sourceFile) => {
|
|
67252
|
+
const exportedExpressions = [];
|
|
67253
|
+
for (const statement of sourceFile.statements) {
|
|
67254
|
+
if (ts.isExportAssignment(statement)) {
|
|
67255
|
+
exportedExpressions.push(statement.expression);
|
|
67256
|
+
continue;
|
|
67257
|
+
}
|
|
67258
|
+
if (ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(statement.expression.left)) exportedExpressions.push(statement.expression.right);
|
|
67259
|
+
}
|
|
67260
|
+
if (exportedExpressions.length !== 1) return null;
|
|
67261
|
+
const exportedExpression = unwrapTypescriptExpression(exportedExpressions[0]);
|
|
67262
|
+
return ts.isObjectLiteralExpression(exportedExpression) ? exportedExpression : null;
|
|
67263
|
+
};
|
|
67264
|
+
const parseConfigPluginNames = (filePath, contents) => {
|
|
67265
|
+
try {
|
|
67266
|
+
const parsedJson = JSON.parse(contents);
|
|
67267
|
+
return isPlainObject(parsedJson) ? readUnknownPluginNames(parsedJson.plugins) : null;
|
|
67268
|
+
} catch {
|
|
67269
|
+
if (ts.transpileModule(contents, {
|
|
67270
|
+
fileName: filePath,
|
|
67271
|
+
reportDiagnostics: true,
|
|
67272
|
+
compilerOptions: { allowJs: true }
|
|
67273
|
+
}).diagnostics?.some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error)) return null;
|
|
67274
|
+
const exportedObject = getDirectExportedObject(ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filePath)));
|
|
67275
|
+
return exportedObject === null ? null : getPluginNamesFromObject(exportedObject);
|
|
67276
|
+
}
|
|
67277
|
+
};
|
|
67278
|
+
const readStaticBabelPluginNames = (rootDirectory) => {
|
|
67279
|
+
for (const fileName of BABEL_CONFIG_FILE_NAMES$1) {
|
|
67280
|
+
const absoluteFilePath = Path.join(rootDirectory, fileName);
|
|
67281
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
67282
|
+
try {
|
|
67283
|
+
return {
|
|
67284
|
+
filePath: fileName,
|
|
67285
|
+
pluginNames: parseConfigPluginNames(fileName, NFS.readFileSync(absoluteFilePath, "utf-8"))
|
|
67286
|
+
};
|
|
67287
|
+
} catch {
|
|
67288
|
+
return {
|
|
67289
|
+
filePath: fileName,
|
|
67290
|
+
pluginNames: null
|
|
67291
|
+
};
|
|
67292
|
+
}
|
|
67293
|
+
}
|
|
67294
|
+
const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
|
|
67295
|
+
if (!isPlainObject(packageJson.babel)) return null;
|
|
67296
|
+
return {
|
|
67297
|
+
filePath: "package.json",
|
|
67298
|
+
pluginNames: readUnknownPluginNames(packageJson.babel.plugins)
|
|
67299
|
+
};
|
|
67300
|
+
};
|
|
67301
|
+
const REACT_COMPILER_PLUGIN_NAMES = new Set(["babel-plugin-react-compiler", "react-compiler"]);
|
|
67302
|
+
const REANIMATED_PLUGIN_NAME = "react-native-reanimated/plugin";
|
|
67303
|
+
const WORKLETS_PLUGIN_NAME = "react-native-worklets/plugin";
|
|
67304
|
+
const checkReactCompilerPluginOrder = (filePath, pluginNames) => {
|
|
67305
|
+
if (pluginNames.findIndex((pluginName) => REACT_COMPILER_PLUGIN_NAMES.has(pluginName)) <= 0) return [];
|
|
67306
|
+
return [buildReactNativeDiagnostic({
|
|
67307
|
+
filePath,
|
|
67308
|
+
rule: "rn-react-compiler-plugin-first",
|
|
67309
|
+
category: "Performance",
|
|
67310
|
+
message: "The React Compiler Babel plugin is not first, so an earlier transform can change component or hook code before the compiler analyzes it.",
|
|
67311
|
+
help: "Move `babel-plugin-react-compiler` to the first entry in the Babel `plugins` array."
|
|
67312
|
+
})];
|
|
67313
|
+
};
|
|
67314
|
+
const checkReanimatedPluginOrder = (project, filePath, pluginNames) => {
|
|
67315
|
+
const reanimatedMajorVersion = project.reanimatedVersion === null || project.reanimatedVersion === void 0 ? null : getLowestDependencyMajor(project.reanimatedVersion);
|
|
67316
|
+
if (reanimatedMajorVersion === null || reanimatedMajorVersion < 4) return [];
|
|
67317
|
+
const diagnostics = [];
|
|
67318
|
+
if (pluginNames.includes(REANIMATED_PLUGIN_NAME)) diagnostics.push(buildReactNativeDiagnostic({
|
|
67319
|
+
filePath,
|
|
67320
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
67321
|
+
category: "Performance",
|
|
67322
|
+
message: "This Reanimated 4 project still uses `react-native-reanimated/plugin`, which was renamed to the Worklets Babel plugin.",
|
|
67323
|
+
help: "Replace it with `react-native-worklets/plugin` and keep that plugin last in the Babel `plugins` array."
|
|
67324
|
+
}));
|
|
67325
|
+
const workletsPluginIndex = pluginNames.lastIndexOf(WORKLETS_PLUGIN_NAME);
|
|
67326
|
+
if (workletsPluginIndex !== -1 && workletsPluginIndex !== pluginNames.length - 1) diagnostics.push(buildReactNativeDiagnostic({
|
|
67327
|
+
filePath,
|
|
67328
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
67329
|
+
category: "Performance",
|
|
67330
|
+
message: "`react-native-worklets/plugin` is not last in the Babel `plugins` array, so later transforms can prevent worklets from being compiled correctly.",
|
|
67331
|
+
help: "Move `react-native-worklets/plugin` to the final entry in the Babel `plugins` array."
|
|
67332
|
+
}));
|
|
67333
|
+
return diagnostics;
|
|
67334
|
+
};
|
|
67335
|
+
const checkReactNativeBabelPluginOrder = (rootDirectory, project) => {
|
|
67336
|
+
const babelPlugins = readStaticBabelPluginNames(rootDirectory);
|
|
67337
|
+
if (babelPlugins === null || babelPlugins.pluginNames === null) return [];
|
|
67338
|
+
return [...checkReactCompilerPluginOrder(babelPlugins.filePath, babelPlugins.pluginNames), ...checkReanimatedPluginOrder(project, babelPlugins.filePath, babelPlugins.pluginNames)];
|
|
67339
|
+
};
|
|
66979
67340
|
const BUILDER_BOB_PACKAGE = "react-native-builder-bob";
|
|
66980
67341
|
const isBuilderBobLibrary = (packageJson) => {
|
|
66981
67342
|
const bobConfig = packageJson[BUILDER_BOB_PACKAGE];
|
|
@@ -67052,7 +67413,12 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
|
67052
67413
|
const isReactNativeProject = (project) => project.framework === "react-native" || project.framework === "expo" || project.hasReactNativeWorkspace || project.expoVersion !== null;
|
|
67053
67414
|
const checkReactNativeProject = (rootDirectory, project) => {
|
|
67054
67415
|
if (!isReactNativeProject(project)) return [];
|
|
67055
|
-
return [
|
|
67416
|
+
return [
|
|
67417
|
+
...checkReactNativeMetroBabelPreset(rootDirectory),
|
|
67418
|
+
...checkReactNativeBabelPluginOrder(rootDirectory, project),
|
|
67419
|
+
...checkReactNativeAndroidReleaseShrinking(rootDirectory),
|
|
67420
|
+
...checkReactNativeLibraryDependencies(rootDirectory)
|
|
67421
|
+
];
|
|
67056
67422
|
};
|
|
67057
67423
|
const RULE_KEY = "no-vulnerable-react-server-components";
|
|
67058
67424
|
const REACT_RSC_ADVISORIES_BY_MINOR = {
|
|
@@ -67203,17 +67569,6 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
67203
67569
|
}
|
|
67204
67570
|
return diagnostics;
|
|
67205
67571
|
};
|
|
67206
|
-
const getTypescriptScriptKind = (fileName) => {
|
|
67207
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
67208
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
67209
|
-
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
67210
|
-
return ts.ScriptKind.JS;
|
|
67211
|
-
};
|
|
67212
|
-
const unwrapTypescriptExpression = (expression) => {
|
|
67213
|
-
let currentExpression = expression;
|
|
67214
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
67215
|
-
return currentExpression;
|
|
67216
|
-
};
|
|
67217
67572
|
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
67218
67573
|
isAnimationFunction: false,
|
|
67219
67574
|
isMotionComponent: false,
|
|
@@ -67769,7 +68124,11 @@ const buildCapabilities = (project) => {
|
|
|
67769
68124
|
capabilities.add(project.framework);
|
|
67770
68125
|
if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
|
|
67771
68126
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
67772
|
-
if (project.expoVersion !== null)
|
|
68127
|
+
if (project.expoVersion !== null) {
|
|
68128
|
+
capabilities.add("expo");
|
|
68129
|
+
const expoSdkMajorVersion = getLowestDependencyMajor(project.expoVersion);
|
|
68130
|
+
if (expoSdkMajorVersion !== null && expoSdkMajorVersion >= 54) capabilities.add("expo:54");
|
|
68131
|
+
}
|
|
67773
68132
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
67774
68133
|
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
67775
68134
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
@@ -67833,6 +68192,11 @@ const buildCapabilities = (project) => {
|
|
|
67833
68192
|
if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
|
|
67834
68193
|
if (project.isPreES2023Target) capabilities.add("pre-es2023");
|
|
67835
68194
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
68195
|
+
if (project.reanimatedVersion !== void 0 && project.reanimatedVersion !== null) {
|
|
68196
|
+
capabilities.add("reanimated");
|
|
68197
|
+
const reanimatedMajorVersion = getLowestDependencyMajor(project.reanimatedVersion);
|
|
68198
|
+
if (reanimatedMajorVersion !== null && reanimatedMajorVersion >= 4) capabilities.add("reanimated:4");
|
|
68199
|
+
}
|
|
67836
68200
|
if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
|
|
67837
68201
|
if (project.styledComponentsVersion) {
|
|
67838
68202
|
capabilities.add("styled-components");
|
|
@@ -69730,7 +70094,11 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
|
|
|
69730
70094
|
const ROOT_DIRECTORY_PLACEHOLDER = "<root>";
|
|
69731
70095
|
const normalizeConfigForHash = (config) => {
|
|
69732
70096
|
const clone = JSON.parse(JSON.stringify(config));
|
|
69733
|
-
if (clone?.settings?.["react-doctor"])
|
|
70097
|
+
if (clone?.settings?.["react-doctor"]) {
|
|
70098
|
+
const reactDoctorSettings = clone.settings["react-doctor"];
|
|
70099
|
+
reactDoctorSettings.rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
|
|
70100
|
+
if (Array.isArray(reactDoctorSettings.unpluginAutoImportRootDirectories)) reactDoctorSettings.unpluginAutoImportRootDirectories = [ROOT_DIRECTORY_PLACEHOLDER];
|
|
70101
|
+
}
|
|
69734
70102
|
if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
|
|
69735
70103
|
return clone;
|
|
69736
70104
|
};
|
|
@@ -69889,13 +70257,14 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
69889
70257
|
}
|
|
69890
70258
|
return enabled;
|
|
69891
70259
|
};
|
|
69892
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
70260
|
+
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 }) => {
|
|
69893
70261
|
const hasIncludedTags = includedTags.size > 0;
|
|
69894
70262
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
69895
70263
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
69896
70264
|
const jsPlugins = [];
|
|
69897
70265
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
69898
70266
|
const capabilities = getCapabilities(project);
|
|
70267
|
+
const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
|
|
69899
70268
|
const enabledReactDoctorRules = {};
|
|
69900
70269
|
for (const registryEntry of REACT_DOCTOR_RULES) {
|
|
69901
70270
|
const rule = reactDoctorPlugin.rules[registryEntry.id];
|
|
@@ -69941,8 +70310,16 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
69941
70310
|
jsPlugins: [...jsPlugins, pluginPath],
|
|
69942
70311
|
settings: { "react-doctor": {
|
|
69943
70312
|
framework: project.framework,
|
|
69944
|
-
rootDirectory:
|
|
70313
|
+
rootDirectory: settingsRootDirectory,
|
|
69945
70314
|
capabilities: [...capabilities].sort(),
|
|
70315
|
+
...runtimeGlobals && runtimeGlobals.length > 0 ? { runtimeGlobals: [...runtimeGlobals] } : {},
|
|
70316
|
+
...unpluginAutoImportGlobalScopes && unpluginAutoImportGlobalScopes.length > 0 ? {
|
|
70317
|
+
unpluginAutoImportRootDirectories: [...new Set([settingsRootDirectory, project.rootDirectory])],
|
|
70318
|
+
unpluginAutoImportGlobalScopes: unpluginAutoImportGlobalScopes.map((scope) => ({
|
|
70319
|
+
directory: scope.directory,
|
|
70320
|
+
names: [...scope.names]
|
|
70321
|
+
}))
|
|
70322
|
+
} : {},
|
|
69946
70323
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
69947
70324
|
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
69948
70325
|
} },
|
|
@@ -69953,6 +70330,245 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
69953
70330
|
}
|
|
69954
70331
|
};
|
|
69955
70332
|
};
|
|
70333
|
+
const AUTO_IMPORT_ADAPTER_PATTERN = /^unplugin-auto-import\/(?:astro|esbuild|rollup|rolldown|rspack|vite|webpack)$/;
|
|
70334
|
+
const CONFIG_BASENAMES = [
|
|
70335
|
+
"astro.config",
|
|
70336
|
+
"esbuild.config",
|
|
70337
|
+
"rollup.config",
|
|
70338
|
+
"rolldown.config",
|
|
70339
|
+
"rspack.config",
|
|
70340
|
+
"vite.config",
|
|
70341
|
+
"webpack.config"
|
|
70342
|
+
];
|
|
70343
|
+
const CONFIG_EXTENSIONS = [
|
|
70344
|
+
".cjs",
|
|
70345
|
+
".cts",
|
|
70346
|
+
".js",
|
|
70347
|
+
".mjs",
|
|
70348
|
+
".mts",
|
|
70349
|
+
".ts"
|
|
70350
|
+
];
|
|
70351
|
+
const CONFIG_FILENAMES = new Set(CONFIG_BASENAMES.flatMap((basename) => CONFIG_EXTENSIONS.map((extension) => `${basename}${extension}`)));
|
|
70352
|
+
const DEFAULT_ESLINT_GLOBALS_PATH = ".eslintrc-auto-import.json";
|
|
70353
|
+
const SUPPORTED_GLOBAL_VALUES = new Set([
|
|
70354
|
+
true,
|
|
70355
|
+
false,
|
|
70356
|
+
"readable",
|
|
70357
|
+
"readonly",
|
|
70358
|
+
"writable",
|
|
70359
|
+
"writeable"
|
|
70360
|
+
]);
|
|
70361
|
+
const getStaticProperty = (objectExpression, propertyName) => objectExpression.properties.find((property) => {
|
|
70362
|
+
if (ts.isSpreadAssignment(property)) return false;
|
|
70363
|
+
const name = ts.isComputedPropertyName(property.name) ? unwrapTypescriptExpression(property.name.expression) : property.name;
|
|
70364
|
+
return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && name.text === propertyName;
|
|
70365
|
+
}) ?? null;
|
|
70366
|
+
const hasNonLiteralComputedProperty = (objectExpression) => objectExpression.properties.some((property) => !ts.isSpreadAssignment(property) && ts.isComputedPropertyName(property.name) && !ts.isStringLiteralLike(unwrapTypescriptExpression(property.name.expression)));
|
|
70367
|
+
const getStaticPropertyAssignment = (objectExpression, propertyName) => {
|
|
70368
|
+
const property = getStaticProperty(objectExpression, propertyName);
|
|
70369
|
+
return property && ts.isPropertyAssignment(property) ? property : null;
|
|
70370
|
+
};
|
|
70371
|
+
const getRequireModuleSpecifier = (expression) => {
|
|
70372
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
70373
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === "default") return getRequireModuleSpecifier(unwrappedExpression.expression);
|
|
70374
|
+
if (!ts.isCallExpression(unwrappedExpression) || !ts.isIdentifier(unwrappedExpression.expression) || unwrappedExpression.expression.text !== "require" || unwrappedExpression.arguments.length !== 1) return null;
|
|
70375
|
+
const moduleSpecifier = unwrappedExpression.arguments[0];
|
|
70376
|
+
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
70377
|
+
};
|
|
70378
|
+
const getRequiredPropertyModuleSpecifier = (expression, propertyName) => {
|
|
70379
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
70380
|
+
return ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === propertyName ? getRequireModuleSpecifier(unwrappedExpression.expression) : null;
|
|
70381
|
+
};
|
|
70382
|
+
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");
|
|
70383
|
+
const isTopLevelExpression = (node) => {
|
|
70384
|
+
let ancestor = node.parent;
|
|
70385
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
70386
|
+
if (ts.isExpressionStatement(ancestor)) return ts.isSourceFile(ancestor.parent);
|
|
70387
|
+
if (!ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isAwaitExpression(ancestor)) return false;
|
|
70388
|
+
ancestor = ancestor.parent;
|
|
70389
|
+
}
|
|
70390
|
+
return false;
|
|
70391
|
+
};
|
|
70392
|
+
const isInsideActiveConfigProperty = (node, propertyName, sourceFile, esbuildBindings, esbuildNamespaceBindings) => {
|
|
70393
|
+
let ancestor = node.parent;
|
|
70394
|
+
let didFindConfigProperty = false;
|
|
70395
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
70396
|
+
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;
|
|
70397
|
+
if (ts.isPropertyAssignment(ancestor)) {
|
|
70398
|
+
const isConfigProperty = (ts.isIdentifier(ancestor.name) || ts.isStringLiteralLike(ancestor.name)) && ancestor.name.text === propertyName;
|
|
70399
|
+
if (didFindConfigProperty || !isConfigProperty) return false;
|
|
70400
|
+
if (!ts.isObjectLiteralExpression(ancestor.parent) || ancestor.parent.properties.some(ts.isSpreadAssignment)) return false;
|
|
70401
|
+
didFindConfigProperty = true;
|
|
70402
|
+
ancestor = ancestor.parent;
|
|
70403
|
+
continue;
|
|
70404
|
+
}
|
|
70405
|
+
if (didFindConfigProperty) {
|
|
70406
|
+
if (ts.isExportAssignment(ancestor)) return true;
|
|
70407
|
+
if (isCommonJsExportAssignment(ancestor, sourceFile)) return isTopLevelExpression(ancestor);
|
|
70408
|
+
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);
|
|
70409
|
+
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;
|
|
70410
|
+
}
|
|
70411
|
+
ancestor = ancestor.parent;
|
|
70412
|
+
}
|
|
70413
|
+
return false;
|
|
70414
|
+
};
|
|
70415
|
+
const getGlobalsPathFromActiveAutoImportCall = (callExpression, packageDirectory) => {
|
|
70416
|
+
const optionsExpression = callExpression.arguments[0];
|
|
70417
|
+
if (!optionsExpression) return null;
|
|
70418
|
+
const unwrappedOptions = unwrapTypescriptExpression(optionsExpression);
|
|
70419
|
+
if (!ts.isObjectLiteralExpression(unwrappedOptions)) return null;
|
|
70420
|
+
if (unwrappedOptions.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(unwrappedOptions)) return null;
|
|
70421
|
+
if (getStaticProperty(unwrappedOptions, "include") || getStaticProperty(unwrappedOptions, "exclude")) return null;
|
|
70422
|
+
const eslintrcProperty = getStaticPropertyAssignment(unwrappedOptions, "eslintrc");
|
|
70423
|
+
if (!eslintrcProperty) return null;
|
|
70424
|
+
const eslintrcExpression = unwrapTypescriptExpression(eslintrcProperty.initializer);
|
|
70425
|
+
if (!ts.isObjectLiteralExpression(eslintrcExpression)) return null;
|
|
70426
|
+
if (eslintrcExpression.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(eslintrcExpression)) return null;
|
|
70427
|
+
const enabledProperty = getStaticPropertyAssignment(eslintrcExpression, "enabled");
|
|
70428
|
+
if (!enabledProperty || unwrapTypescriptExpression(enabledProperty.initializer).kind !== ts.SyntaxKind.TrueKeyword) return null;
|
|
70429
|
+
const filepathProperty = getStaticProperty(eslintrcExpression, "filepath");
|
|
70430
|
+
if (!filepathProperty) return Path.join(packageDirectory, DEFAULT_ESLINT_GLOBALS_PATH);
|
|
70431
|
+
if (!ts.isPropertyAssignment(filepathProperty)) return null;
|
|
70432
|
+
const filepathExpression = unwrapTypescriptExpression(filepathProperty.initializer);
|
|
70433
|
+
return ts.isStringLiteralLike(filepathExpression) ? Path.resolve(packageDirectory, filepathExpression.text) : null;
|
|
70434
|
+
};
|
|
70435
|
+
const collectGlobalsPathsFromConfig = (configPath, packageDirectory) => {
|
|
70436
|
+
let sourceText;
|
|
70437
|
+
try {
|
|
70438
|
+
sourceText = NFS.readFileSync(configPath, "utf8");
|
|
70439
|
+
} catch {
|
|
70440
|
+
return {
|
|
70441
|
+
didFindActiveAutoImport: false,
|
|
70442
|
+
globalsPaths: []
|
|
70443
|
+
};
|
|
70444
|
+
}
|
|
70445
|
+
const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true);
|
|
70446
|
+
const autoImportBindings = /* @__PURE__ */ new Map();
|
|
70447
|
+
const esbuildBindings = /* @__PURE__ */ new Set();
|
|
70448
|
+
const esbuildNamespaceBindings = /* @__PURE__ */ new Set();
|
|
70449
|
+
for (const statement of sourceFile.statements) {
|
|
70450
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
70451
|
+
const moduleSpecifier = statement.moduleSpecifier.text;
|
|
70452
|
+
if (AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
70453
|
+
const defaultBinding = statement.importClause?.name;
|
|
70454
|
+
if (defaultBinding) autoImportBindings.set(defaultBinding.text, moduleSpecifier);
|
|
70455
|
+
}
|
|
70456
|
+
if (moduleSpecifier === "esbuild") {
|
|
70457
|
+
const defaultBinding = statement.importClause?.name;
|
|
70458
|
+
if (defaultBinding) esbuildNamespaceBindings.add(defaultBinding.text);
|
|
70459
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
70460
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
70461
|
+
for (const importSpecifier of namedBindings.elements) if ((importSpecifier.propertyName ?? importSpecifier.name).text === "build") esbuildBindings.add(importSpecifier.name.text);
|
|
70462
|
+
}
|
|
70463
|
+
if (namedBindings && ts.isNamespaceImport(namedBindings)) esbuildNamespaceBindings.add(namedBindings.name.text);
|
|
70464
|
+
}
|
|
70465
|
+
}
|
|
70466
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
70467
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
70468
|
+
if (!declaration.initializer) continue;
|
|
70469
|
+
const declarationName = ts.isIdentifier(declaration.name) ? declaration.name.text : null;
|
|
70470
|
+
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
70471
|
+
if (declarationName && moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) autoImportBindings.set(declarationName, moduleSpecifier);
|
|
70472
|
+
if (moduleSpecifier === "esbuild") {
|
|
70473
|
+
if (declarationName) esbuildNamespaceBindings.add(declarationName);
|
|
70474
|
+
if (ts.isObjectBindingPattern(declaration.name)) for (const bindingElement of declaration.name.elements) {
|
|
70475
|
+
const importedName = bindingElement.propertyName ?? bindingElement.name;
|
|
70476
|
+
if (ts.isIdentifier(importedName) && importedName.text === "build" && ts.isIdentifier(bindingElement.name)) esbuildBindings.add(bindingElement.name.text);
|
|
70477
|
+
}
|
|
70478
|
+
}
|
|
70479
|
+
if (declarationName && getRequiredPropertyModuleSpecifier(declaration.initializer, "build") === "esbuild") esbuildBindings.add(declarationName);
|
|
70480
|
+
}
|
|
70481
|
+
}
|
|
70482
|
+
const globalsPaths = /* @__PURE__ */ new Set();
|
|
70483
|
+
let didFindActiveAutoImport = false;
|
|
70484
|
+
let didFindUnsafeActiveAutoImport = false;
|
|
70485
|
+
const visit = (node) => {
|
|
70486
|
+
if (ts.isCallExpression(node)) {
|
|
70487
|
+
const moduleSpecifier = ts.isIdentifier(node.expression) ? autoImportBindings.get(node.expression.text) : getRequireModuleSpecifier(node.expression);
|
|
70488
|
+
if (moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
70489
|
+
if (isInsideActiveConfigProperty(node, moduleSpecifier.endsWith("/astro") ? "integrations" : "plugins", sourceFile, esbuildBindings, esbuildNamespaceBindings)) {
|
|
70490
|
+
didFindActiveAutoImport = true;
|
|
70491
|
+
const globalsPath = getGlobalsPathFromActiveAutoImportCall(node, packageDirectory);
|
|
70492
|
+
if (globalsPath) globalsPaths.add(globalsPath);
|
|
70493
|
+
else didFindUnsafeActiveAutoImport = true;
|
|
70494
|
+
}
|
|
70495
|
+
}
|
|
70496
|
+
}
|
|
70497
|
+
ts.forEachChild(node, visit);
|
|
70498
|
+
};
|
|
70499
|
+
visit(sourceFile);
|
|
70500
|
+
return {
|
|
70501
|
+
didFindActiveAutoImport,
|
|
70502
|
+
globalsPaths: didFindUnsafeActiveAutoImport ? [] : [...globalsPaths]
|
|
70503
|
+
};
|
|
70504
|
+
};
|
|
70505
|
+
const collectGeneratedGlobalNames = (globalsPath, rootDirectory) => {
|
|
70506
|
+
const relativePath = Path.relative(rootDirectory, globalsPath);
|
|
70507
|
+
if (relativePath.startsWith("..") || Path.isAbsolute(relativePath)) return [];
|
|
70508
|
+
const parsed = failOpenReadJson(globalsPath, null);
|
|
70509
|
+
if (!isPlainObject(parsed) || !isPlainObject(parsed.globals)) return [];
|
|
70510
|
+
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();
|
|
70511
|
+
};
|
|
70512
|
+
const findOwningPackageDirectory = (absoluteFilePath, rootDirectory, cache) => {
|
|
70513
|
+
let currentDirectory = Path.dirname(absoluteFilePath);
|
|
70514
|
+
const visitedDirectories = [];
|
|
70515
|
+
while (true) {
|
|
70516
|
+
const cachedDirectory = cache.get(currentDirectory);
|
|
70517
|
+
if (cachedDirectory !== void 0) {
|
|
70518
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, cachedDirectory);
|
|
70519
|
+
return cachedDirectory;
|
|
70520
|
+
}
|
|
70521
|
+
const relativeDirectory = Path.relative(rootDirectory, currentDirectory);
|
|
70522
|
+
if (relativeDirectory.startsWith("..") || Path.isAbsolute(relativeDirectory)) {
|
|
70523
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
70524
|
+
return null;
|
|
70525
|
+
}
|
|
70526
|
+
visitedDirectories.push(currentDirectory);
|
|
70527
|
+
if (NFS.existsSync(Path.join(currentDirectory, "package.json"))) {
|
|
70528
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, currentDirectory);
|
|
70529
|
+
return currentDirectory;
|
|
70530
|
+
}
|
|
70531
|
+
if (currentDirectory === rootDirectory) {
|
|
70532
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
70533
|
+
return null;
|
|
70534
|
+
}
|
|
70535
|
+
currentDirectory = Path.dirname(currentDirectory);
|
|
70536
|
+
}
|
|
70537
|
+
};
|
|
70538
|
+
const collectPackageGlobalNames = (packageDirectory, rootDirectory) => {
|
|
70539
|
+
let directoryEntries;
|
|
70540
|
+
try {
|
|
70541
|
+
directoryEntries = NFS.readdirSync(packageDirectory, { withFileTypes: true });
|
|
70542
|
+
} catch {
|
|
70543
|
+
return [];
|
|
70544
|
+
}
|
|
70545
|
+
const configuredGlobalsPaths = [];
|
|
70546
|
+
for (const entry of directoryEntries) {
|
|
70547
|
+
if (!entry.isFile() && !entry.isSymbolicLink() || !CONFIG_FILENAMES.has(entry.name)) continue;
|
|
70548
|
+
const configGlobalsPaths = collectGlobalsPathsFromConfig(Path.join(packageDirectory, entry.name), packageDirectory);
|
|
70549
|
+
if (configGlobalsPaths.didFindActiveAutoImport) configuredGlobalsPaths.push(configGlobalsPaths.globalsPaths.toSorted());
|
|
70550
|
+
}
|
|
70551
|
+
if (configuredGlobalsPaths.length === 0) return [];
|
|
70552
|
+
const globalsPaths = configuredGlobalsPaths[0];
|
|
70553
|
+
if (configuredGlobalsPaths.some((candidatePaths) => candidatePaths.length !== globalsPaths.length || candidatePaths.some((candidatePath, index) => candidatePath !== globalsPaths[index]))) return [];
|
|
70554
|
+
const names = /* @__PURE__ */ new Set();
|
|
70555
|
+
for (const globalsPath of globalsPaths) for (const name of collectGeneratedGlobalNames(globalsPath, rootDirectory)) names.add(name);
|
|
70556
|
+
return [...names].sort();
|
|
70557
|
+
};
|
|
70558
|
+
const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }) => {
|
|
70559
|
+
const absoluteRootDirectory = Path.resolve(rootDirectory);
|
|
70560
|
+
const packageDirectoryCache = /* @__PURE__ */ new Map();
|
|
70561
|
+
const packageDirectories = /* @__PURE__ */ new Set();
|
|
70562
|
+
for (const candidateFile of candidateFiles) {
|
|
70563
|
+
const packageDirectory = findOwningPackageDirectory(Path.resolve(absoluteRootDirectory, candidateFile), absoluteRootDirectory, packageDirectoryCache);
|
|
70564
|
+
if (packageDirectory) packageDirectories.add(packageDirectory);
|
|
70565
|
+
}
|
|
70566
|
+
const scopes = [...packageDirectories].map((packageDirectory) => ({
|
|
70567
|
+
directory: Path.relative(absoluteRootDirectory, packageDirectory).replaceAll("\\", "/"),
|
|
70568
|
+
names: collectPackageGlobalNames(packageDirectory, absoluteRootDirectory)
|
|
70569
|
+
})).sort((firstScope, secondScope) => firstScope.directory.localeCompare(secondScope.directory));
|
|
70570
|
+
return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
|
|
70571
|
+
};
|
|
69956
70572
|
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
69957
70573
|
const decodeFileDiagnostics = (raw) => {
|
|
69958
70574
|
if (!Array.isArray(raw)) return null;
|
|
@@ -70275,6 +70891,12 @@ const appendReanimatedSharedValueHint = (help, rule, project) => {
|
|
|
70275
70891
|
if (!help) return REANIMATED_SHARED_VALUE_HINT;
|
|
70276
70892
|
return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
|
|
70277
70893
|
};
|
|
70894
|
+
const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
70895
|
+
const boundedOffset = Math.min(Math.max(utf8Offset, 0), sourceBuffer.length);
|
|
70896
|
+
let lineStartOffset = boundedOffset;
|
|
70897
|
+
while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
|
|
70898
|
+
return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
|
|
70899
|
+
};
|
|
70278
70900
|
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
70279
70901
|
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
70280
70902
|
const KNOWN_SECRET_RULES = [
|
|
@@ -70990,7 +71612,7 @@ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORI
|
|
|
70990
71612
|
* with empty text still carry a useful jump target, so they're kept
|
|
70991
71613
|
* with a neutral message.
|
|
70992
71614
|
*/
|
|
70993
|
-
const buildRelatedLocations = (labels, filePath) => {
|
|
71615
|
+
const buildRelatedLocations = (labels, filePath, sourceBuffer) => {
|
|
70994
71616
|
if (labels.length <= 1) return [];
|
|
70995
71617
|
const related = [];
|
|
70996
71618
|
for (let labelIndex = 1; labelIndex < labels.length; labelIndex++) {
|
|
@@ -70998,8 +71620,8 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
70998
71620
|
if (!label?.span) continue;
|
|
70999
71621
|
related.push({
|
|
71000
71622
|
filePath,
|
|
71001
|
-
line: label.span.line ?? 0,
|
|
71002
|
-
column: label.span.column ?? 0,
|
|
71623
|
+
line: sourceBuffer === null ? label.span.line ?? 0 : lineOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
71624
|
+
column: sourceBuffer === null ? label.span.column ?? 0 : columnOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
71003
71625
|
offset: label.span.offset,
|
|
71004
71626
|
length: label.span.length,
|
|
71005
71627
|
message: label.label ?? ""
|
|
@@ -71019,7 +71641,7 @@ const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnos
|
|
|
71019
71641
|
* to the first `{`. Raises `OxlintOutputUnparseable` when the
|
|
71020
71642
|
* stdout isn't valid JSON or doesn't carry a `diagnostics` array.
|
|
71021
71643
|
*/
|
|
71022
|
-
const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
71644
|
+
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath) => {
|
|
71023
71645
|
if (!stdout) return [];
|
|
71024
71646
|
const jsonStart = stdout.indexOf("{");
|
|
71025
71647
|
const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
|
|
@@ -71036,8 +71658,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71036
71658
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
71037
71659
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
71038
71660
|
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
71661
|
+
const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
71662
|
+
const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
|
|
71039
71663
|
const readSourceBuffer = (filename) => {
|
|
71040
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71664
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71041
71665
|
const cached = sourceBufferCache.get(absolutePath);
|
|
71042
71666
|
if (cached !== void 0) return cached;
|
|
71043
71667
|
let sourceBuffer;
|
|
@@ -71050,7 +71674,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71050
71674
|
return sourceBuffer;
|
|
71051
71675
|
};
|
|
71052
71676
|
const readSourceLines = (filename) => {
|
|
71053
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71677
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71054
71678
|
const cached = sourceLinesCache.get(absolutePath);
|
|
71055
71679
|
if (cached !== void 0) return cached;
|
|
71056
71680
|
const sourceBuffer = readSourceBuffer(filename);
|
|
@@ -71059,27 +71683,30 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71059
71683
|
return sourceLines;
|
|
71060
71684
|
};
|
|
71061
71685
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
71062
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71686
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71063
71687
|
const cached = minifiedFileCache.get(absolutePath);
|
|
71064
71688
|
if (cached !== void 0) return cached;
|
|
71065
71689
|
const minified = isMinifiedSource(absolutePath);
|
|
71066
71690
|
minifiedFileCache.set(absolutePath, minified);
|
|
71067
71691
|
return minified;
|
|
71068
71692
|
};
|
|
71069
|
-
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) => {
|
|
71693
|
+
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) => {
|
|
71070
71694
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
71071
71695
|
const primaryLabel = diagnostic.labels[0];
|
|
71072
71696
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
71073
|
-
const
|
|
71697
|
+
const mappedSourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
71698
|
+
const normalizedFilePath = (mappedSourceFilename ?? diagnostic.filename).replaceAll("\\", "/");
|
|
71074
71699
|
const primarySpan = primaryLabel?.span;
|
|
71075
71700
|
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
71076
|
-
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
71701
|
+
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath, mappedSourceFilename === void 0 ? null : sourceBuffer);
|
|
71077
71702
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
71078
71703
|
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
71079
71704
|
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
71080
|
-
const
|
|
71705
|
+
const primaryLineNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.line ?? 0;
|
|
71706
|
+
const primaryColumnNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? columnOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.column ?? 0;
|
|
71707
|
+
const primaryLineIndex = primarySpan ? primaryLineNumber - 1 : -1;
|
|
71081
71708
|
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
71082
|
-
const primaryColumnIndex = primarySpan ?
|
|
71709
|
+
const primaryColumnIndex = primarySpan ? primaryColumnNumber - 1 : -1;
|
|
71083
71710
|
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
71084
71711
|
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
71085
71712
|
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
@@ -71092,8 +71719,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71092
71719
|
message: cleaned.message,
|
|
71093
71720
|
help: cleaned.help,
|
|
71094
71721
|
url: diagnostic.url,
|
|
71095
|
-
line:
|
|
71096
|
-
column:
|
|
71722
|
+
line: primaryLineNumber,
|
|
71723
|
+
column: primaryColumnNumber,
|
|
71097
71724
|
...primarySpan ? {
|
|
71098
71725
|
offset: primarySpan.offset,
|
|
71099
71726
|
length: primarySpan.length,
|
|
@@ -71281,7 +71908,11 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
71281
71908
|
* loop with a slimmer config in that case.
|
|
71282
71909
|
*/
|
|
71283
71910
|
const spawnLintBatches = async (input) => {
|
|
71284
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
71911
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
71912
|
+
const resolveSourcePath = (filePath) => {
|
|
71913
|
+
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
71914
|
+
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
71915
|
+
};
|
|
71285
71916
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
71286
71917
|
let rescueDeadlineEpochMs;
|
|
71287
71918
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
@@ -71301,7 +71932,7 @@ const spawnLintBatches = async (input) => {
|
|
|
71301
71932
|
}
|
|
71302
71933
|
const batchArgs = [...baseArgs, ...batch];
|
|
71303
71934
|
try {
|
|
71304
|
-
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory);
|
|
71935
|
+
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory, sourcePathByLintPath);
|
|
71305
71936
|
} catch (error) {
|
|
71306
71937
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
71307
71938
|
if (isPastDeadline()) {
|
|
@@ -71407,10 +72038,12 @@ const spawnLintBatches = async (input) => {
|
|
|
71407
72038
|
onPartialFailure(buildMessage(`${skippedFiles.slice(0, 3).join(", ")}${skippedFiles.length > 3 ? `, +${skippedFiles.length - 3} more` : ""}`));
|
|
71408
72039
|
};
|
|
71409
72040
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
71410
|
-
|
|
71411
|
-
|
|
72041
|
+
const droppedSourceFiles = [...new Set(droppedFiles.map(resolveSourcePath))];
|
|
72042
|
+
const deadlineSkippedSourceFiles = [...new Set(outcome.deadlineSkippedFiles.map(resolveSourcePath))];
|
|
72043
|
+
reportSkippedFiles(droppedSourceFiles, (fileListPreview) => `${droppedSourceFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
72044
|
+
reportSkippedFiles(deadlineSkippedSourceFiles, (fileListPreview) => `${deadlineSkippedSourceFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
71412
72045
|
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
71413
|
-
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
72046
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)).map(resolveSourcePath))].sort());
|
|
71414
72047
|
return dedupeDiagnostics(diagnostics);
|
|
71415
72048
|
};
|
|
71416
72049
|
let didValidate = false;
|
|
@@ -71509,6 +72142,266 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
|
71509
72142
|
}
|
|
71510
72143
|
return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
|
|
71511
72144
|
};
|
|
72145
|
+
const THREE_MODULE_IMPORT_PATTERN = /\b(?:from\s*|import\s*(?:\(\s*)?|require\s*\(\s*)["']three(?:\/[^"']*)?["']/;
|
|
72146
|
+
const containsThreeModuleImport = (sourceText) => THREE_MODULE_IMPORT_PATTERN.test(sourceText);
|
|
72147
|
+
const COMMENT_OPEN = "<!--";
|
|
72148
|
+
const COMMENT_CLOSE = "-->";
|
|
72149
|
+
const FRONTMATTER_FENCE = "---";
|
|
72150
|
+
const SCRIPT_TAG_NAME = "script";
|
|
72151
|
+
const SCRIPT_OPEN = `<${SCRIPT_TAG_NAME}`;
|
|
72152
|
+
const SCRIPT_CLOSE = `</${SCRIPT_TAG_NAME}`;
|
|
72153
|
+
const TEMPLATE_TAG_NAME = "template";
|
|
72154
|
+
const TEMPLATE_CLOSE = `</${TEMPLATE_TAG_NAME}`;
|
|
72155
|
+
const JAVASCRIPT_MIME_TYPES = new Set([
|
|
72156
|
+
"application/ecmascript",
|
|
72157
|
+
"application/javascript",
|
|
72158
|
+
"application/x-ecmascript",
|
|
72159
|
+
"application/x-javascript",
|
|
72160
|
+
"text/ecmascript",
|
|
72161
|
+
"text/javascript",
|
|
72162
|
+
"text/javascript1.0",
|
|
72163
|
+
"text/javascript1.1",
|
|
72164
|
+
"text/javascript1.2",
|
|
72165
|
+
"text/javascript1.3",
|
|
72166
|
+
"text/javascript1.4",
|
|
72167
|
+
"text/javascript1.5",
|
|
72168
|
+
"text/jscript",
|
|
72169
|
+
"text/livescript",
|
|
72170
|
+
"text/x-ecmascript",
|
|
72171
|
+
"text/x-javascript"
|
|
72172
|
+
]);
|
|
72173
|
+
const RAW_TEXT_TAG_NAMES = new Set([
|
|
72174
|
+
"iframe",
|
|
72175
|
+
"noembed",
|
|
72176
|
+
"noframes",
|
|
72177
|
+
"noscript",
|
|
72178
|
+
"style",
|
|
72179
|
+
"textarea",
|
|
72180
|
+
"title",
|
|
72181
|
+
"xmp"
|
|
72182
|
+
]);
|
|
72183
|
+
const PLAINTEXT_TAG_NAME = "plaintext";
|
|
72184
|
+
const TAG_OPEN_UTF8_BYTE = "<".charCodeAt(0);
|
|
72185
|
+
const TAG_CLOSE_UTF8_BYTE = ">".charCodeAt(0);
|
|
72186
|
+
const SINGLE_QUOTE_UTF8_BYTE = "'".charCodeAt(0);
|
|
72187
|
+
const DOUBLE_QUOTE_UTF8_BYTE = "\"".charCodeAt(0);
|
|
72188
|
+
const ATTRIBUTE_ASSIGNMENT_UTF8_BYTE = "=".charCodeAt(0);
|
|
72189
|
+
const TAG_SELF_CLOSE_UTF8_BYTE = "/".charCodeAt(0);
|
|
72190
|
+
const TAB_UTF8_BYTE = " ".charCodeAt(0);
|
|
72191
|
+
const FORM_FEED_UTF8_BYTE = "\f".charCodeAt(0);
|
|
72192
|
+
const isHtmlWhitespace = (byte) => byte === TAB_UTF8_BYTE || byte === 10 || byte === FORM_FEED_UTF8_BYTE || byte === 13 || byte === 32;
|
|
72193
|
+
const matchesAsciiCaseInsensitive = (sourceBuffer, startByte, expected) => {
|
|
72194
|
+
if (startByte + expected.length > sourceBuffer.length) return false;
|
|
72195
|
+
for (let expectedIndex = 0; expectedIndex < expected.length; expectedIndex++) {
|
|
72196
|
+
const sourceByte = sourceBuffer[startByte + expectedIndex];
|
|
72197
|
+
if (sourceByte === void 0 || String.fromCharCode(sourceByte).toLowerCase() !== expected[expectedIndex]) return false;
|
|
72198
|
+
}
|
|
72199
|
+
return true;
|
|
72200
|
+
};
|
|
72201
|
+
const isTagBoundary = (byte) => byte === TAG_CLOSE_UTF8_BYTE || byte === TAG_SELF_CLOSE_UTF8_BYTE || isHtmlWhitespace(byte);
|
|
72202
|
+
const isPotentialTagStart = (byte) => {
|
|
72203
|
+
if (byte === void 0) return false;
|
|
72204
|
+
return /[A-Za-z!/?]/.test(String.fromCharCode(byte));
|
|
72205
|
+
};
|
|
72206
|
+
const findLineEnd = (sourceBuffer, lineStartByte) => {
|
|
72207
|
+
let byteIndex = lineStartByte;
|
|
72208
|
+
while (byteIndex < sourceBuffer.length && sourceBuffer[byteIndex] !== 10 && sourceBuffer[byteIndex] !== 13) byteIndex++;
|
|
72209
|
+
return byteIndex;
|
|
72210
|
+
};
|
|
72211
|
+
const findNextLineStart = (sourceBuffer, lineStartByte) => {
|
|
72212
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
72213
|
+
if (sourceBuffer[lineEndByte] === 13 && sourceBuffer[lineEndByte + 1] === 10) return lineEndByte + 2;
|
|
72214
|
+
return Math.min(lineEndByte + 1, sourceBuffer.length);
|
|
72215
|
+
};
|
|
72216
|
+
const isFrontmatterFenceLine = (sourceBuffer, lineStartByte) => {
|
|
72217
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, lineStartByte, FRONTMATTER_FENCE)) return false;
|
|
72218
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
72219
|
+
for (let byteIndex = lineStartByte + 3; byteIndex < lineEndByte; byteIndex++) if (!isHtmlWhitespace(sourceBuffer[byteIndex])) return false;
|
|
72220
|
+
return true;
|
|
72221
|
+
};
|
|
72222
|
+
const findFrontmatterEnd = (sourceBuffer) => {
|
|
72223
|
+
if (!isFrontmatterFenceLine(sourceBuffer, 0)) return 0;
|
|
72224
|
+
const openingFenceEndByte = findLineEnd(sourceBuffer, 0);
|
|
72225
|
+
let lineStartByte = findNextLineStart(sourceBuffer, 0);
|
|
72226
|
+
while (lineStartByte < sourceBuffer.length) {
|
|
72227
|
+
if (isFrontmatterFenceLine(sourceBuffer, lineStartByte)) return findLineEnd(sourceBuffer, lineStartByte);
|
|
72228
|
+
lineStartByte = findNextLineStart(sourceBuffer, lineStartByte);
|
|
72229
|
+
}
|
|
72230
|
+
return openingFenceEndByte;
|
|
72231
|
+
};
|
|
72232
|
+
const maskByteRange = (maskedBuffer, startByte, endByte) => {
|
|
72233
|
+
for (let byteIndex = startByte; byteIndex < endByte; byteIndex++) {
|
|
72234
|
+
const byte = maskedBuffer[byteIndex];
|
|
72235
|
+
if (byte !== 10 && byte !== 13) maskedBuffer[byteIndex] = 32;
|
|
72236
|
+
}
|
|
72237
|
+
};
|
|
72238
|
+
const readStartTagName = (sourceBuffer, tagStartByte) => {
|
|
72239
|
+
const firstNameByte = sourceBuffer[tagStartByte + 1];
|
|
72240
|
+
if (firstNameByte === void 0 || !/[A-Za-z]/.test(String.fromCharCode(firstNameByte))) return null;
|
|
72241
|
+
let nameEndByte = tagStartByte + 2;
|
|
72242
|
+
while (nameEndByte < sourceBuffer.length && /[A-Za-z0-9:-]/.test(String.fromCharCode(sourceBuffer[nameEndByte] ?? 32))) nameEndByte++;
|
|
72243
|
+
return sourceBuffer.subarray(tagStartByte + 1, nameEndByte).toString("ascii").toLowerCase();
|
|
72244
|
+
};
|
|
72245
|
+
const findTagEnd = (sourceBuffer, startByte) => {
|
|
72246
|
+
let quoteByte = null;
|
|
72247
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) {
|
|
72248
|
+
const byte = sourceBuffer[byteIndex];
|
|
72249
|
+
if (quoteByte !== null) {
|
|
72250
|
+
if (byte === quoteByte) quoteByte = null;
|
|
72251
|
+
continue;
|
|
72252
|
+
}
|
|
72253
|
+
if (byte === SINGLE_QUOTE_UTF8_BYTE || byte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
72254
|
+
quoteByte = byte;
|
|
72255
|
+
continue;
|
|
72256
|
+
}
|
|
72257
|
+
if (byte === TAG_CLOSE_UTF8_BYTE) return byteIndex;
|
|
72258
|
+
}
|
|
72259
|
+
return sourceBuffer.length;
|
|
72260
|
+
};
|
|
72261
|
+
const parseScriptAttributes = (sourceBuffer, attributesStartByte, tagEndByte) => {
|
|
72262
|
+
let byteIndex = attributesStartByte;
|
|
72263
|
+
let hasSource = false;
|
|
72264
|
+
let language = null;
|
|
72265
|
+
let scriptType = null;
|
|
72266
|
+
while (byteIndex < tagEndByte) {
|
|
72267
|
+
while (byteIndex < tagEndByte && (isHtmlWhitespace(sourceBuffer[byteIndex]) || sourceBuffer[byteIndex] === TAG_SELF_CLOSE_UTF8_BYTE)) byteIndex++;
|
|
72268
|
+
const attributeNameStartByte = byteIndex;
|
|
72269
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== ATTRIBUTE_ASSIGNMENT_UTF8_BYTE && sourceBuffer[byteIndex] !== TAG_SELF_CLOSE_UTF8_BYTE) byteIndex++;
|
|
72270
|
+
const attributeName = sourceBuffer.subarray(attributeNameStartByte, byteIndex).toString("ascii").toLowerCase();
|
|
72271
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
72272
|
+
let attributeValue = "";
|
|
72273
|
+
if (sourceBuffer[byteIndex] === ATTRIBUTE_ASSIGNMENT_UTF8_BYTE) {
|
|
72274
|
+
byteIndex++;
|
|
72275
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
72276
|
+
const quoteByte = sourceBuffer[byteIndex];
|
|
72277
|
+
if (quoteByte === SINGLE_QUOTE_UTF8_BYTE || quoteByte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
72278
|
+
const valueStartByte = byteIndex + 1;
|
|
72279
|
+
byteIndex = valueStartByte;
|
|
72280
|
+
while (byteIndex < tagEndByte && sourceBuffer[byteIndex] !== quoteByte) byteIndex++;
|
|
72281
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
72282
|
+
if (byteIndex < tagEndByte) byteIndex++;
|
|
72283
|
+
} else {
|
|
72284
|
+
const valueStartByte = byteIndex;
|
|
72285
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== TAG_CLOSE_UTF8_BYTE) byteIndex++;
|
|
72286
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
72287
|
+
}
|
|
72288
|
+
}
|
|
72289
|
+
if (attributeName === "src") hasSource = true;
|
|
72290
|
+
else if (attributeName === "type" && scriptType === null) scriptType = attributeValue;
|
|
72291
|
+
else if (attributeName === "language" && language === null) language = attributeValue;
|
|
72292
|
+
}
|
|
72293
|
+
return {
|
|
72294
|
+
hasSource,
|
|
72295
|
+
language,
|
|
72296
|
+
type: scriptType
|
|
72297
|
+
};
|
|
72298
|
+
};
|
|
72299
|
+
const isExecutableScript = (attributes) => {
|
|
72300
|
+
if (attributes.hasSource) return false;
|
|
72301
|
+
const type = attributes.type?.trim().toLowerCase() ?? "";
|
|
72302
|
+
if (type !== "") {
|
|
72303
|
+
const mimeType = type.split(";")[0]?.trim() ?? "";
|
|
72304
|
+
return mimeType === "module" || JAVASCRIPT_MIME_TYPES.has(mimeType);
|
|
72305
|
+
}
|
|
72306
|
+
const language = attributes.language?.trim().toLowerCase() ?? "";
|
|
72307
|
+
return language === "" || JAVASCRIPT_MIME_TYPES.has(`text/${language}`);
|
|
72308
|
+
};
|
|
72309
|
+
const findElementClose = (sourceBuffer, startByte, tagName) => {
|
|
72310
|
+
const closeTagStart = `</${tagName}`;
|
|
72311
|
+
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;
|
|
72312
|
+
return sourceBuffer.length;
|
|
72313
|
+
};
|
|
72314
|
+
const prepareHtmlScriptSource = (sourceBuffer) => {
|
|
72315
|
+
const frontmatterEndByte = findFrontmatterEnd(sourceBuffer);
|
|
72316
|
+
let maskedBuffer = frontmatterEndByte > 0 ? Buffer.from(sourceBuffer) : null;
|
|
72317
|
+
if (maskedBuffer !== null) maskByteRange(maskedBuffer, 0, frontmatterEndByte);
|
|
72318
|
+
const executableScriptBodies = [];
|
|
72319
|
+
let byteIndex = frontmatterEndByte;
|
|
72320
|
+
let templateDepth = 0;
|
|
72321
|
+
while (byteIndex < sourceBuffer.length) {
|
|
72322
|
+
if (sourceBuffer[byteIndex] !== TAG_OPEN_UTF8_BYTE) {
|
|
72323
|
+
byteIndex++;
|
|
72324
|
+
continue;
|
|
72325
|
+
}
|
|
72326
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, COMMENT_OPEN)) {
|
|
72327
|
+
const commentEndByte = sourceBuffer.indexOf(COMMENT_CLOSE, byteIndex + 4);
|
|
72328
|
+
byteIndex = commentEndByte === -1 ? sourceBuffer.length : commentEndByte + 3;
|
|
72329
|
+
continue;
|
|
72330
|
+
}
|
|
72331
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, TEMPLATE_CLOSE) && isTagBoundary(sourceBuffer[byteIndex + TEMPLATE_CLOSE.length])) {
|
|
72332
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + TEMPLATE_CLOSE.length);
|
|
72333
|
+
if (templateDepth > 0) templateDepth--;
|
|
72334
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
72335
|
+
continue;
|
|
72336
|
+
}
|
|
72337
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, SCRIPT_OPEN) || !isTagBoundary(sourceBuffer[byteIndex + SCRIPT_OPEN.length])) {
|
|
72338
|
+
if (!isPotentialTagStart(sourceBuffer[byteIndex + 1])) {
|
|
72339
|
+
byteIndex++;
|
|
72340
|
+
continue;
|
|
72341
|
+
}
|
|
72342
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + 1);
|
|
72343
|
+
const tagName = readStartTagName(sourceBuffer, byteIndex);
|
|
72344
|
+
if (tagName === PLAINTEXT_TAG_NAME) break;
|
|
72345
|
+
if (tagName === TEMPLATE_TAG_NAME) templateDepth++;
|
|
72346
|
+
if (tagName !== null && RAW_TEXT_TAG_NAMES.has(tagName)) {
|
|
72347
|
+
const closeTagStartByte = findElementClose(sourceBuffer, tagEndByte + 1, tagName);
|
|
72348
|
+
if (closeTagStartByte === sourceBuffer.length) break;
|
|
72349
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, closeTagStartByte + tagName.length + 2);
|
|
72350
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
72351
|
+
continue;
|
|
72352
|
+
}
|
|
72353
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
72354
|
+
continue;
|
|
72355
|
+
}
|
|
72356
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + SCRIPT_OPEN.length);
|
|
72357
|
+
if (tagEndByte === sourceBuffer.length) break;
|
|
72358
|
+
const bodyStartByte = tagEndByte + 1;
|
|
72359
|
+
const bodyEndByte = findElementClose(sourceBuffer, bodyStartByte, SCRIPT_TAG_NAME);
|
|
72360
|
+
const attributes = parseScriptAttributes(sourceBuffer, byteIndex + SCRIPT_OPEN.length, tagEndByte);
|
|
72361
|
+
if (attributes.hasSource || templateDepth > 0) {
|
|
72362
|
+
maskedBuffer ??= Buffer.from(sourceBuffer);
|
|
72363
|
+
maskByteRange(maskedBuffer, bodyStartByte, bodyEndByte);
|
|
72364
|
+
} else if (isExecutableScript(attributes)) executableScriptBodies.push(sourceBuffer.subarray(bodyStartByte, bodyEndByte));
|
|
72365
|
+
if (bodyEndByte === sourceBuffer.length) break;
|
|
72366
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, bodyEndByte + SCRIPT_CLOSE.length);
|
|
72367
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
72368
|
+
}
|
|
72369
|
+
return {
|
|
72370
|
+
executableScriptBodies,
|
|
72371
|
+
lintBuffer: maskedBuffer ?? sourceBuffer
|
|
72372
|
+
};
|
|
72373
|
+
};
|
|
72374
|
+
const prepareHtmlLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
|
|
72375
|
+
const lintFiles = [];
|
|
72376
|
+
const sourcePathByLintPath = /* @__PURE__ */ new Map();
|
|
72377
|
+
const sizeByLintPath = /* @__PURE__ */ new Map();
|
|
72378
|
+
const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
|
|
72379
|
+
let htmlFileIndex = 0;
|
|
72380
|
+
let hasThreeModuleImport = false;
|
|
72381
|
+
for (const candidateFile of candidateFiles) {
|
|
72382
|
+
if (!HTML_FILE_PATTERN.test(candidateFile)) {
|
|
72383
|
+
lintFiles.push(candidateFile);
|
|
72384
|
+
continue;
|
|
72385
|
+
}
|
|
72386
|
+
const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
|
|
72387
|
+
const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
|
|
72388
|
+
const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
|
|
72389
|
+
if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
|
|
72390
|
+
const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
|
|
72391
|
+
NFS.writeFileSync(lintPath, lintBuffer);
|
|
72392
|
+
lintFiles.push(lintPath);
|
|
72393
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
72394
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
72395
|
+
hasThreeModuleImport ||= executableScriptBodies.some((scriptBody) => containsThreeModuleImport(scriptBody.toString("utf8")));
|
|
72396
|
+
htmlFileIndex++;
|
|
72397
|
+
}
|
|
72398
|
+
return {
|
|
72399
|
+
lintFiles,
|
|
72400
|
+
sourcePathByLintPath,
|
|
72401
|
+
sizeByLintPath,
|
|
72402
|
+
hasThreeModuleImport
|
|
72403
|
+
};
|
|
72404
|
+
};
|
|
71512
72405
|
/**
|
|
71513
72406
|
* Atomically (re)writes the generated oxlintrc.json. Used twice in
|
|
71514
72407
|
* the runner: once for the primary scan, once for the
|
|
@@ -71669,6 +72562,8 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
71669
72562
|
const runOxlint = async (options) => {
|
|
71670
72563
|
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;
|
|
71671
72564
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
72565
|
+
const runtimeGlobals = Array.isArray(userConfig?.runtimeGlobals) ? userConfig.runtimeGlobals.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
72566
|
+
let unpluginAutoImportGlobalScopes = [];
|
|
71672
72567
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
71673
72568
|
validateRuleRegistration();
|
|
71674
72569
|
resetManifestCaches();
|
|
@@ -71682,21 +72577,6 @@ const runOxlint = async (options) => {
|
|
|
71682
72577
|
const pluginPath = resolvePluginPath();
|
|
71683
72578
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
71684
72579
|
const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
71685
|
-
const buildConfig = (overrides) => createOxlintConfig({
|
|
71686
|
-
pluginPath,
|
|
71687
|
-
project,
|
|
71688
|
-
customRulesOnly,
|
|
71689
|
-
extendsPaths: overrides.extendsPaths,
|
|
71690
|
-
ignoredTags,
|
|
71691
|
-
includedTags,
|
|
71692
|
-
includeTagDefaults,
|
|
71693
|
-
serverAuthFunctionNames,
|
|
71694
|
-
severityControls,
|
|
71695
|
-
userPlugins,
|
|
71696
|
-
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
71697
|
-
ruleSelection: overrides.ruleSelection,
|
|
71698
|
-
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
71699
|
-
});
|
|
71700
72580
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
71701
72581
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
71702
72582
|
const configPath = Path.join(configDirectory, "oxlintrc.json");
|
|
@@ -71732,7 +72612,36 @@ const runOxlint = async (options) => {
|
|
|
71732
72612
|
await yieldToEventLoop();
|
|
71733
72613
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
71734
72614
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
72615
|
+
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
72616
|
+
rootDirectory,
|
|
72617
|
+
candidateFiles
|
|
72618
|
+
});
|
|
72619
|
+
const preparedHtmlSources = prepareHtmlLintSources(rootDirectory, configDirectory, candidateFiles);
|
|
72620
|
+
const lintFiles = preparedHtmlSources.lintFiles;
|
|
72621
|
+
const hasHtmlFiles = preparedHtmlSources.sourcePathByLintPath.size > 0;
|
|
72622
|
+
const lintProject = !project.hasThree && preparedHtmlSources.hasThreeModuleImport ? {
|
|
72623
|
+
...project,
|
|
72624
|
+
hasThree: true
|
|
72625
|
+
} : project;
|
|
72626
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
72627
|
+
pluginPath,
|
|
72628
|
+
project: lintProject,
|
|
72629
|
+
customRulesOnly,
|
|
72630
|
+
extendsPaths: overrides.extendsPaths,
|
|
72631
|
+
ignoredTags,
|
|
72632
|
+
includedTags,
|
|
72633
|
+
includeTagDefaults,
|
|
72634
|
+
runtimeGlobals,
|
|
72635
|
+
unpluginAutoImportGlobalScopes,
|
|
72636
|
+
serverAuthFunctionNames,
|
|
72637
|
+
severityControls,
|
|
72638
|
+
userPlugins,
|
|
72639
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
72640
|
+
ruleSelection: overrides.ruleSelection,
|
|
72641
|
+
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
72642
|
+
});
|
|
71735
72643
|
const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
|
|
72644
|
+
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedHtmlSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
|
|
71736
72645
|
const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
|
|
71737
72646
|
baseArgs: passBaseArgs,
|
|
71738
72647
|
files: passFiles,
|
|
@@ -71761,7 +72670,8 @@ const runOxlint = async (options) => {
|
|
|
71761
72670
|
fileBatches: passFileBatches,
|
|
71762
72671
|
rootDirectory,
|
|
71763
72672
|
nodeBinaryPath,
|
|
71764
|
-
project,
|
|
72673
|
+
project: lintProject,
|
|
72674
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
71765
72675
|
onPartialFailure: reportPartialFailure,
|
|
71766
72676
|
onAnalyzedFiles: (filePaths) => {
|
|
71767
72677
|
analyzedFiles = filePaths;
|
|
@@ -71796,7 +72706,7 @@ const runOxlint = async (options) => {
|
|
|
71796
72706
|
};
|
|
71797
72707
|
}
|
|
71798
72708
|
};
|
|
71799
|
-
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0) {
|
|
72709
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasHtmlFiles) {
|
|
71800
72710
|
const rulesetHash = computeRulesetHash({
|
|
71801
72711
|
config: buildConfig({
|
|
71802
72712
|
extendsPaths: [],
|
|
@@ -71954,14 +72864,15 @@ const runOxlint = async (options) => {
|
|
|
71954
72864
|
]);
|
|
71955
72865
|
}
|
|
71956
72866
|
const baseArgs = makeBaseArgs(configPath);
|
|
71957
|
-
const fileBatches = buildFileBatches(baseArgs,
|
|
72867
|
+
const fileBatches = buildFileBatches(baseArgs, lintFiles);
|
|
71958
72868
|
let analyzedFiles = [];
|
|
71959
72869
|
const runBatches = () => spawnLintBatches({
|
|
71960
72870
|
baseArgs,
|
|
71961
72871
|
fileBatches,
|
|
71962
72872
|
rootDirectory,
|
|
71963
72873
|
nodeBinaryPath,
|
|
71964
|
-
project,
|
|
72874
|
+
project: lintProject,
|
|
72875
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
71965
72876
|
onPartialFailure,
|
|
71966
72877
|
onAnalyzedFiles: (filePaths) => {
|
|
71967
72878
|
analyzedFiles = filePaths;
|
|
@@ -73883,4 +74794,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
73883
74794
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
73884
74795
|
|
|
73885
74796
|
//# sourceMappingURL=index.js.map
|
|
73886
|
-
//# debugId=
|
|
74797
|
+
//# debugId=5ad39650-1163-5117-aad5-472963ee3867
|