react-doctor 0.9.0 → 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 +999 -87
- 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/lsp.js
CHANGED
|
@@ -61478,7 +61478,8 @@ var AmbiguousProjectError = class extends Error {
|
|
|
61478
61478
|
}
|
|
61479
61479
|
};
|
|
61480
61480
|
const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
|
|
61481
|
-
const
|
|
61481
|
+
const HTML_FILE_PATTERN = /\.html$/i;
|
|
61482
|
+
const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
61482
61483
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
61483
61484
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
61484
61485
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
@@ -61844,7 +61845,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
61844
61845
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
61845
61846
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
61846
61847
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
61847
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
61848
|
+
const CORE_PACKAGE_VERSION = "0.9.1";
|
|
61848
61849
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
61849
61850
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
61850
61851
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -62235,6 +62236,7 @@ const frameworkMergeRank = (framework) => {
|
|
|
62235
62236
|
return MOBILE_FRAMEWORKS.has(framework) ? 2 : 1;
|
|
62236
62237
|
};
|
|
62237
62238
|
const REACT_COMPILER_LINT_PACKAGES = new Set(["eslint-plugin-react-compiler"]);
|
|
62239
|
+
const REACT_COMPILER_RUNTIME_PACKAGES = new Set(["react-compiler-runtime"]);
|
|
62238
62240
|
const NEXT_CONFIG_FILENAMES = [
|
|
62239
62241
|
"next.config.js",
|
|
62240
62242
|
"next.config.mjs",
|
|
@@ -62337,10 +62339,10 @@ const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
|
62337
62339
|
]).find(isFile) ?? null;
|
|
62338
62340
|
};
|
|
62339
62341
|
const parseConfigSourceFile = (filePath, content) => filePath.endsWith(".json") || Path.basename(filePath) === ".babelrc" ? ts.parseJsonText(filePath, content) : ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
62340
|
-
const getStaticPropertyName$
|
|
62342
|
+
const getStaticPropertyName$2 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
|
|
62341
62343
|
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");
|
|
62342
62344
|
const hasExportModifier = (node) => ts.canHaveModifiers(node) && Boolean(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
|
|
62343
|
-
const getRequireModuleSpecifier = (expression) => {
|
|
62345
|
+
const getRequireModuleSpecifier$1 = (expression) => {
|
|
62344
62346
|
if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "require" || expression.arguments.length !== 1) return null;
|
|
62345
62347
|
const moduleSpecifier = expression.arguments[0];
|
|
62346
62348
|
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
@@ -62353,7 +62355,7 @@ const hasTopLevelValueBinding = (sourceFile, bindingName) => sourceFile.statemen
|
|
|
62353
62355
|
const namedBindings = importClause?.namedBindings;
|
|
62354
62356
|
return namedBindings ? ts.isNamespaceImport(namedBindings) ? namedBindings.name.text === bindingName : namedBindings.elements.some((element) => element.name.text === bindingName) : false;
|
|
62355
62357
|
}
|
|
62356
|
-
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) =>
|
|
62358
|
+
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContainsIdentifier(declaration.name, bindingName));
|
|
62357
62359
|
return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === bindingName;
|
|
62358
62360
|
});
|
|
62359
62361
|
const getImportBinding = (sourceFile, bindingName) => {
|
|
@@ -62384,24 +62386,24 @@ const getImportBinding = (sourceFile, bindingName) => {
|
|
|
62384
62386
|
for (const declaration of statement.declarationList.declarations) {
|
|
62385
62387
|
if (!declaration.initializer) continue;
|
|
62386
62388
|
if (ts.isIdentifier(declaration.name) && declaration.name.text === bindingName) {
|
|
62387
|
-
const directModuleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
62389
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
62388
62390
|
if (directModuleSpecifier) return {
|
|
62389
62391
|
moduleSpecifier: directModuleSpecifier,
|
|
62390
62392
|
exportName: "default",
|
|
62391
62393
|
isNamespace: true
|
|
62392
62394
|
};
|
|
62393
|
-
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier(declaration.initializer.expression) !== null) return {
|
|
62394
|
-
moduleSpecifier: getRequireModuleSpecifier(declaration.initializer.expression) ?? "",
|
|
62395
|
+
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier$1(declaration.initializer.expression) !== null) return {
|
|
62396
|
+
moduleSpecifier: getRequireModuleSpecifier$1(declaration.initializer.expression) ?? "",
|
|
62395
62397
|
exportName: declaration.initializer.name.text,
|
|
62396
62398
|
isNamespace: false
|
|
62397
62399
|
};
|
|
62398
62400
|
}
|
|
62399
62401
|
if (!ts.isObjectBindingPattern(declaration.name)) continue;
|
|
62400
62402
|
const bindingElement = declaration.name.elements.find((element) => ts.isIdentifier(element.name) && element.name.text === bindingName);
|
|
62401
|
-
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
62403
|
+
const moduleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
62402
62404
|
if (bindingElement && moduleSpecifier) return {
|
|
62403
62405
|
moduleSpecifier,
|
|
62404
|
-
exportName: bindingElement.propertyName ? getStaticPropertyName$
|
|
62406
|
+
exportName: bindingElement.propertyName ? getStaticPropertyName$2(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
|
|
62405
62407
|
isNamespace: false
|
|
62406
62408
|
};
|
|
62407
62409
|
}
|
|
@@ -62454,6 +62456,48 @@ const getScopedConfigBinding = (identifier) => {
|
|
|
62454
62456
|
};
|
|
62455
62457
|
};
|
|
62456
62458
|
const isCompilerTransformModule = (moduleSpecifier, exportName) => moduleSpecifier === "babel-plugin-react-compiler" && exportName === "default" || moduleSpecifier === "@vitejs/plugin-react" && exportName === "reactCompilerPreset";
|
|
62459
|
+
const NODE_MODULE_SPECIFIERS = new Set(["module", "node:module"]);
|
|
62460
|
+
const isConstantVariableInitializer = (node) => ts.isExpression(node) && ts.isVariableDeclaration(node.parent) && ts.isVariableDeclarationList(node.parent.parent) && Boolean(node.parent.parent.flags & ts.NodeFlags.Const);
|
|
62461
|
+
const isNodeCreateRequireCall = (node, analysis) => {
|
|
62462
|
+
if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isTypeAssertionExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isAwaitExpression(node)) return isNodeCreateRequireCall(node.expression, analysis);
|
|
62463
|
+
if (!ts.isCallExpression(node)) return false;
|
|
62464
|
+
const target = node.expression;
|
|
62465
|
+
if (ts.isIdentifier(target)) {
|
|
62466
|
+
if (analysis.localBindings.has(target.text) || getScopedConfigBinding(target).wasFound) return false;
|
|
62467
|
+
const importBinding = getImportBinding(analysis.sourceFile, target.text);
|
|
62468
|
+
return Boolean(importBinding && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier) && importBinding.exportName === "createRequire");
|
|
62469
|
+
}
|
|
62470
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return false;
|
|
62471
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "createRequire") return false;
|
|
62472
|
+
const createRequireReceiver = target.expression;
|
|
62473
|
+
if (ts.isCallExpression(createRequireReceiver)) {
|
|
62474
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(createRequireReceiver);
|
|
62475
|
+
if (requiredModuleSpecifier === null || !NODE_MODULE_SPECIFIERS.has(requiredModuleSpecifier) || !ts.isIdentifier(createRequireReceiver.expression)) return false;
|
|
62476
|
+
const requireIdentifier = createRequireReceiver.expression;
|
|
62477
|
+
return !analysis.localBindings.has(requireIdentifier.text) && !getScopedConfigBinding(requireIdentifier).wasFound && !hasTopLevelValueBinding(analysis.sourceFile, requireIdentifier.text);
|
|
62478
|
+
}
|
|
62479
|
+
if (!ts.isIdentifier(createRequireReceiver)) return false;
|
|
62480
|
+
if (analysis.localBindings.has(createRequireReceiver.text) || getScopedConfigBinding(createRequireReceiver).wasFound) return false;
|
|
62481
|
+
const importBinding = getImportBinding(analysis.sourceFile, createRequireReceiver.text);
|
|
62482
|
+
return Boolean(importBinding?.isNamespace && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier));
|
|
62483
|
+
};
|
|
62484
|
+
const getNodeRequireResolveModuleSpecifier = (callExpression, analysis) => {
|
|
62485
|
+
const [moduleSpecifierNode] = callExpression.arguments;
|
|
62486
|
+
if (!moduleSpecifierNode || !ts.isStringLiteralLike(moduleSpecifierNode)) return null;
|
|
62487
|
+
const target = callExpression.expression;
|
|
62488
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
62489
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "resolve") return null;
|
|
62490
|
+
if (isNodeCreateRequireCall(target.expression, analysis)) return moduleSpecifierNode.text;
|
|
62491
|
+
if (!ts.isIdentifier(target.expression)) return null;
|
|
62492
|
+
const resolverIdentifier = target.expression;
|
|
62493
|
+
if (analysis.localBindings.has(resolverIdentifier.text)) return null;
|
|
62494
|
+
const scopedBinding = getScopedConfigBinding(resolverIdentifier);
|
|
62495
|
+
const topLevelBinding = scopedBinding.wasFound ? null : getTopLevelBinding(analysis.sourceFile, resolverIdentifier.text);
|
|
62496
|
+
const resolverInitializer = scopedBinding.wasFound ? scopedBinding.initializer : topLevelBinding;
|
|
62497
|
+
if (resolverInitializer === null && !scopedBinding.wasFound && resolverIdentifier.text === "require" && !hasTopLevelValueBinding(analysis.sourceFile, resolverIdentifier.text) && getImportBinding(analysis.sourceFile, resolverIdentifier.text) === null) return moduleSpecifierNode.text;
|
|
62498
|
+
if (!resolverInitializer || !isConstantVariableInitializer(resolverInitializer) || !isNodeCreateRequireCall(resolverInitializer, analysis)) return null;
|
|
62499
|
+
return moduleSpecifierNode.text;
|
|
62500
|
+
};
|
|
62457
62501
|
const getAssignedPropertyInitializer = (identifier, propertyName) => {
|
|
62458
62502
|
let bindingScope = null;
|
|
62459
62503
|
let currentNode = identifier;
|
|
@@ -62562,7 +62606,7 @@ const getReactCompilerFlagState = (expression, analysis) => {
|
|
|
62562
62606
|
}
|
|
62563
62607
|
if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
|
|
62564
62608
|
for (const property of [...unwrappedExpression.properties].reverse()) {
|
|
62565
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62609
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
|
|
62566
62610
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
|
|
62567
62611
|
if (ts.isSpreadAssignment(property)) {
|
|
62568
62612
|
const spreadState = getReactCompilerFlagState(property.expression, analysis);
|
|
@@ -62588,8 +62632,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
62588
62632
|
}
|
|
62589
62633
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
|
|
62590
62634
|
for (const property of [...resolvedExpression.properties].reverse()) {
|
|
62591
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62592
|
-
if (ts.isMethodDeclaration(property) && getStaticPropertyName$
|
|
62635
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return property.initializer;
|
|
62636
|
+
if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return property;
|
|
62593
62637
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return property.name;
|
|
62594
62638
|
if (ts.isSpreadAssignment(property)) {
|
|
62595
62639
|
const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
|
|
@@ -62620,7 +62664,7 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
62620
62664
|
return resolvedExpression.properties.some((property) => {
|
|
62621
62665
|
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
|
|
62622
62666
|
if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
|
|
62623
|
-
const staticPropertyName = getStaticPropertyName$
|
|
62667
|
+
const staticPropertyName = getStaticPropertyName$2(property.name);
|
|
62624
62668
|
return staticPropertyName === null || staticPropertyName === propertyName;
|
|
62625
62669
|
}
|
|
62626
62670
|
return false;
|
|
@@ -62639,7 +62683,7 @@ const getExportedConfigNodes = (sourceFile, exportName) => {
|
|
|
62639
62683
|
continue;
|
|
62640
62684
|
}
|
|
62641
62685
|
if (ts.isExpressionStatement(statement) && isCommonJsConfigExportAssignment(statement.expression, sourceFile) && exportName !== "default" && ts.isObjectLiteralExpression(statement.expression.right)) for (const property of [...statement.expression.right.properties].reverse()) {
|
|
62642
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
62686
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === exportName) {
|
|
62643
62687
|
exportedNodes.push(property.initializer);
|
|
62644
62688
|
break;
|
|
62645
62689
|
}
|
|
@@ -62769,7 +62813,7 @@ const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransfor
|
|
|
62769
62813
|
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
62770
62814
|
const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
|
|
62771
62815
|
if (propertyName === null) return null;
|
|
62772
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(target.expression);
|
|
62816
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
|
|
62773
62817
|
if (requiredModuleSpecifier !== null) {
|
|
62774
62818
|
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
62775
62819
|
if (!requiredModuleSpecifier.startsWith(".")) return null;
|
|
@@ -62798,10 +62842,10 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62798
62842
|
const reactCompilerFlagState = excludedPropertyNames?.has("reactCompiler") ? null : getReactCompilerFlagState(node, analysis);
|
|
62799
62843
|
if (reactCompilerFlagState?.isEnabled) return true;
|
|
62800
62844
|
for (const [propertyIndex, property] of node.properties.entries()) if (ts.isPropertyAssignment(property)) {
|
|
62801
|
-
const propertyName = getStaticPropertyName$
|
|
62845
|
+
const propertyName = getStaticPropertyName$2(property.name);
|
|
62802
62846
|
if (propertyName && excludedPropertyNames?.has(propertyName)) continue;
|
|
62803
62847
|
if (propertyName === "reactCompiler") continue;
|
|
62804
|
-
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$
|
|
62848
|
+
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;
|
|
62805
62849
|
const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
|
|
62806
62850
|
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer) && property.initializer.text.startsWith(".")) {
|
|
62807
62851
|
const extendedFilePath = resolveImportedConfigFile(analysis.filePath, property.initializer.text);
|
|
@@ -62811,12 +62855,12 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62811
62855
|
} else if (ts.isShorthandPropertyAssignment(property)) {
|
|
62812
62856
|
if (excludedPropertyNames?.has(property.name.text)) continue;
|
|
62813
62857
|
if (property.name.text === "reactCompiler") continue;
|
|
62814
|
-
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$
|
|
62858
|
+
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;
|
|
62815
62859
|
const propertyAllowsCompilerTransform = property.name.text === "plugins" || property.name.text === "presets";
|
|
62816
62860
|
if (analyzeConfigNode(property.name, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
62817
62861
|
} else if (ts.isSpreadAssignment(property)) {
|
|
62818
62862
|
if (reactCompilerFlagState && getReactCompilerFlagState(property.expression, analysis) !== null) continue;
|
|
62819
|
-
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$
|
|
62863
|
+
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;
|
|
62820
62864
|
if (analyzeConfigNode(property.expression, analysis, allowCompilerTransform, false, excludedPropertyNames)) return true;
|
|
62821
62865
|
}
|
|
62822
62866
|
return false;
|
|
@@ -62829,9 +62873,11 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62829
62873
|
});
|
|
62830
62874
|
}
|
|
62831
62875
|
if (ts.isCallExpression(node)) {
|
|
62876
|
+
const resolvedModuleSpecifier = getNodeRequireResolveModuleSpecifier(node, analysis);
|
|
62877
|
+
if (resolvedModuleSpecifier !== null) return allowCompilerTransform && isCompilerTransformModule(resolvedModuleSpecifier, "default");
|
|
62832
62878
|
const callTargetResult = analyzeConfigCallTarget(node, analysis, allowCompilerTransform);
|
|
62833
62879
|
if (callTargetResult !== null) return callTargetResult;
|
|
62834
|
-
const directModuleSpecifier = getRequireModuleSpecifier(node);
|
|
62880
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(node);
|
|
62835
62881
|
const isRequireShadowed = analysis.localBindings.has("require") || ts.isIdentifier(node.expression) && getScopedConfigBinding(node.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require");
|
|
62836
62882
|
if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
62837
62883
|
if (directModuleSpecifier && !isRequireShadowed) {
|
|
@@ -62853,7 +62899,7 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
62853
62899
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform) || node.arguments.some((argument) => analyzeConfigNode(argument, analysis, false));
|
|
62854
62900
|
}
|
|
62855
62901
|
if (ts.isPropertyAccessExpression(node)) {
|
|
62856
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(node.expression);
|
|
62902
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
|
|
62857
62903
|
if (requiredModuleSpecifier) {
|
|
62858
62904
|
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
62859
62905
|
if (requiredModuleSpecifier.startsWith(".")) {
|
|
@@ -62941,7 +62987,7 @@ const hasCompilerConfigurationInAncestors = (directory) => {
|
|
|
62941
62987
|
}
|
|
62942
62988
|
return false;
|
|
62943
62989
|
};
|
|
62944
|
-
const detectReactCompiler = (directory, packageJson) => hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
62990
|
+
const detectReactCompiler = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_RUNTIME_PACKAGES) || hasCompilerConfiguration(directory, packageJson) || hasCompilerConfigurationInAncestors(directory);
|
|
62945
62991
|
const detectReactCompilerLintPlugin = (directory, packageJson) => hasCompilerPackage(packageJson, REACT_COMPILER_LINT_PACKAGES) || hasCompilerPackageInAncestors(directory, REACT_COMPILER_LINT_PACKAGES);
|
|
62946
62992
|
const detectNextjsStaticExport = (directory) => NEXT_CONFIG_FILENAMES.some((filename) => {
|
|
62947
62993
|
const filePath = Path.join(directory, filename);
|
|
@@ -66164,7 +66210,7 @@ const warn = (message) => {
|
|
|
66164
66210
|
runSync(warn$1(message));
|
|
66165
66211
|
};
|
|
66166
66212
|
const CONFIG_BASENAME = "doctor.config";
|
|
66167
|
-
const CONFIG_EXTENSIONS = [
|
|
66213
|
+
const CONFIG_EXTENSIONS$1 = [
|
|
66168
66214
|
"ts",
|
|
66169
66215
|
"mts",
|
|
66170
66216
|
"cts",
|
|
@@ -66268,7 +66314,7 @@ const loadLegacyConfig = (directory) => {
|
|
|
66268
66314
|
};
|
|
66269
66315
|
const loadConfigFromDirectory = async (directory) => {
|
|
66270
66316
|
let sawBrokenConfigFile = false;
|
|
66271
|
-
for (const extension of CONFIG_EXTENSIONS) {
|
|
66317
|
+
for (const extension of CONFIG_EXTENSIONS$1) {
|
|
66272
66318
|
const filePath = Path.join(directory, `${CONFIG_BASENAME}.${extension}`);
|
|
66273
66319
|
if (!isFile(filePath)) continue;
|
|
66274
66320
|
const isDataFile = DATA_CONFIG_EXTENSIONS.has(extension);
|
|
@@ -66955,6 +67001,321 @@ const buildReactNativeDiagnostic = (input) => ({
|
|
|
66955
67001
|
column: input.column ?? 0,
|
|
66956
67002
|
category: input.category ?? "Correctness"
|
|
66957
67003
|
});
|
|
67004
|
+
const ANDROID_APP_BUILD_FILE_NAMES = ["build.gradle", "build.gradle.kts"];
|
|
67005
|
+
const BUILD_TYPES_BLOCK_PATTERN = /\bbuildTypes\s*\{/g;
|
|
67006
|
+
const RELEASE_STRING_MARKER = "__RD_RELEASE__";
|
|
67007
|
+
const RELEASE_BLOCK_PATTERNS = [/\brelease\s*\{/g, /\b(?:getByName|named)\s*\(\s*(?:["']release["']|__RD_RELEASE__)\s*\)\s*\{/g];
|
|
67008
|
+
const MINIFY_ASSIGNMENT_PATTERN = /\b(?:isMinifyEnabled|minifyEnabled)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
67009
|
+
const SHRINK_RESOURCES_ASSIGNMENT_PATTERN = /\b(?:isShrinkResources|shrinkResources)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
67010
|
+
const stripGradleComments = (contents) => {
|
|
67011
|
+
let result = "";
|
|
67012
|
+
let index = 0;
|
|
67013
|
+
let quote = null;
|
|
67014
|
+
while (index < contents.length) {
|
|
67015
|
+
const character = contents[index];
|
|
67016
|
+
const nextCharacter = contents[index + 1];
|
|
67017
|
+
if (quote !== null) {
|
|
67018
|
+
result += character;
|
|
67019
|
+
if (character === "\\") {
|
|
67020
|
+
result += nextCharacter ?? "";
|
|
67021
|
+
index += 2;
|
|
67022
|
+
continue;
|
|
67023
|
+
}
|
|
67024
|
+
if (character === quote) quote = null;
|
|
67025
|
+
index += 1;
|
|
67026
|
+
continue;
|
|
67027
|
+
}
|
|
67028
|
+
if (character === "\"" || character === "'") {
|
|
67029
|
+
quote = character;
|
|
67030
|
+
result += character;
|
|
67031
|
+
index += 1;
|
|
67032
|
+
continue;
|
|
67033
|
+
}
|
|
67034
|
+
if (character === "/" && nextCharacter === "/") {
|
|
67035
|
+
while (index < contents.length && contents[index] !== "\n") {
|
|
67036
|
+
result += " ";
|
|
67037
|
+
index += 1;
|
|
67038
|
+
}
|
|
67039
|
+
continue;
|
|
67040
|
+
}
|
|
67041
|
+
if (character === "/" && nextCharacter === "*") {
|
|
67042
|
+
result += " ";
|
|
67043
|
+
index += 2;
|
|
67044
|
+
while (index < contents.length && !(contents[index] === "*" && contents[index + 1] === "/")) {
|
|
67045
|
+
result += contents[index] === "\n" ? "\n" : " ";
|
|
67046
|
+
index += 1;
|
|
67047
|
+
}
|
|
67048
|
+
if (index < contents.length) {
|
|
67049
|
+
result += " ";
|
|
67050
|
+
index += 2;
|
|
67051
|
+
}
|
|
67052
|
+
continue;
|
|
67053
|
+
}
|
|
67054
|
+
result += character;
|
|
67055
|
+
index += 1;
|
|
67056
|
+
}
|
|
67057
|
+
return result;
|
|
67058
|
+
};
|
|
67059
|
+
const maskGradleStrings = (contents) => {
|
|
67060
|
+
let result = "";
|
|
67061
|
+
let index = 0;
|
|
67062
|
+
let quote = null;
|
|
67063
|
+
while (index < contents.length) {
|
|
67064
|
+
const character = contents[index];
|
|
67065
|
+
if (quote === null) {
|
|
67066
|
+
if (character === "\"" || character === "'") {
|
|
67067
|
+
quote = character;
|
|
67068
|
+
result += " ";
|
|
67069
|
+
} else result += character;
|
|
67070
|
+
index += 1;
|
|
67071
|
+
continue;
|
|
67072
|
+
}
|
|
67073
|
+
if (character === "\\") {
|
|
67074
|
+
result += " ";
|
|
67075
|
+
index += 2;
|
|
67076
|
+
continue;
|
|
67077
|
+
}
|
|
67078
|
+
if (character === quote) quote = null;
|
|
67079
|
+
result += character === "\n" ? "\n" : " ";
|
|
67080
|
+
index += 1;
|
|
67081
|
+
}
|
|
67082
|
+
return result;
|
|
67083
|
+
};
|
|
67084
|
+
const findBlockContents = (contents, pattern) => {
|
|
67085
|
+
const blocks = [];
|
|
67086
|
+
pattern.lastIndex = 0;
|
|
67087
|
+
let match = pattern.exec(contents);
|
|
67088
|
+
while (match !== null) {
|
|
67089
|
+
const openingBraceIndex = pattern.lastIndex - 1;
|
|
67090
|
+
let depth = 1;
|
|
67091
|
+
let index = openingBraceIndex + 1;
|
|
67092
|
+
let quote = null;
|
|
67093
|
+
while (index < contents.length && depth > 0) {
|
|
67094
|
+
const character = contents[index];
|
|
67095
|
+
if (quote !== null) {
|
|
67096
|
+
if (character === "\\") {
|
|
67097
|
+
index += 2;
|
|
67098
|
+
continue;
|
|
67099
|
+
}
|
|
67100
|
+
if (character === quote) quote = null;
|
|
67101
|
+
} else if (character === "\"" || character === "'") quote = character;
|
|
67102
|
+
else if (character === "{") depth += 1;
|
|
67103
|
+
else if (character === "}") depth -= 1;
|
|
67104
|
+
index += 1;
|
|
67105
|
+
}
|
|
67106
|
+
if (depth === 0) blocks.push(contents.slice(openingBraceIndex + 1, index - 1));
|
|
67107
|
+
match = pattern.exec(contents);
|
|
67108
|
+
}
|
|
67109
|
+
return blocks;
|
|
67110
|
+
};
|
|
67111
|
+
const getFinalStaticBoolean = (contents, pattern) => {
|
|
67112
|
+
pattern.lastIndex = 0;
|
|
67113
|
+
let finalValue = null;
|
|
67114
|
+
let match = pattern.exec(contents);
|
|
67115
|
+
while (match !== null) {
|
|
67116
|
+
const staticValue = match[1]?.trim().replace(/\)$/, "").trim();
|
|
67117
|
+
if (staticValue === "true") finalValue = true;
|
|
67118
|
+
else if (staticValue === "false") finalValue = false;
|
|
67119
|
+
else finalValue = null;
|
|
67120
|
+
match = pattern.exec(contents);
|
|
67121
|
+
}
|
|
67122
|
+
return finalValue;
|
|
67123
|
+
};
|
|
67124
|
+
const getReleaseBlocks = (contents) => findBlockContents(contents, BUILD_TYPES_BLOCK_PATTERN).flatMap((buildTypesBlock) => RELEASE_BLOCK_PATTERNS.flatMap((pattern) => findBlockContents(buildTypesBlock, pattern)));
|
|
67125
|
+
const readAndroidReleaseShrinking = (rootDirectory) => {
|
|
67126
|
+
for (const buildFileName of ANDROID_APP_BUILD_FILE_NAMES) {
|
|
67127
|
+
const filePath = Path.posix.join("android", "app", buildFileName);
|
|
67128
|
+
const absoluteFilePath = Path.join(rootDirectory, filePath);
|
|
67129
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
67130
|
+
let contents;
|
|
67131
|
+
try {
|
|
67132
|
+
contents = stripGradleComments(NFS.readFileSync(absoluteFilePath, "utf-8"));
|
|
67133
|
+
} catch {
|
|
67134
|
+
return null;
|
|
67135
|
+
}
|
|
67136
|
+
const releaseBlocks = getReleaseBlocks(maskGradleStrings(contents.replace(/(["'])release\1/g, RELEASE_STRING_MARKER)));
|
|
67137
|
+
const [releaseBlock] = releaseBlocks;
|
|
67138
|
+
if (releaseBlock === void 0 || releaseBlocks.length !== 1) return null;
|
|
67139
|
+
const hasDisabledMinification = getFinalStaticBoolean(releaseBlock, MINIFY_ASSIGNMENT_PATTERN) === false;
|
|
67140
|
+
const hasDisabledResourceShrinking = getFinalStaticBoolean(releaseBlock, SHRINK_RESOURCES_ASSIGNMENT_PATTERN) === false;
|
|
67141
|
+
if (!hasDisabledMinification && !hasDisabledResourceShrinking) return null;
|
|
67142
|
+
return {
|
|
67143
|
+
filePath,
|
|
67144
|
+
hasDisabledMinification,
|
|
67145
|
+
hasDisabledResourceShrinking
|
|
67146
|
+
};
|
|
67147
|
+
}
|
|
67148
|
+
return null;
|
|
67149
|
+
};
|
|
67150
|
+
const checkReactNativeAndroidReleaseShrinking = (rootDirectory) => {
|
|
67151
|
+
const releaseShrinking = readAndroidReleaseShrinking(rootDirectory);
|
|
67152
|
+
if (releaseShrinking === null) return [];
|
|
67153
|
+
const disabledFeatures = [releaseShrinking.hasDisabledMinification ? "code minification" : null, releaseShrinking.hasDisabledResourceShrinking ? "resource shrinking" : null].filter((feature) => feature !== null);
|
|
67154
|
+
return [buildReactNativeDiagnostic({
|
|
67155
|
+
filePath: releaseShrinking.filePath,
|
|
67156
|
+
rule: "rn-android-release-shrinking-disabled",
|
|
67157
|
+
category: "Performance",
|
|
67158
|
+
message: `The Android release build explicitly disables ${disabledFeatures.join(" and ")}, leaving unreachable code or resources in the shipped app.`,
|
|
67159
|
+
help: "Enable release code minification and resource shrinking, then test the optimized build and add keep rules for libraries that require them."
|
|
67160
|
+
})];
|
|
67161
|
+
};
|
|
67162
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
67163
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
67164
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
67165
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
67166
|
+
return ts.ScriptKind.JS;
|
|
67167
|
+
};
|
|
67168
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
67169
|
+
let currentExpression = expression;
|
|
67170
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
67171
|
+
return currentExpression;
|
|
67172
|
+
};
|
|
67173
|
+
const BABEL_CONFIG_FILE_NAMES$1 = [
|
|
67174
|
+
"babel.config.js",
|
|
67175
|
+
"babel.config.cjs",
|
|
67176
|
+
"babel.config.mjs",
|
|
67177
|
+
"babel.config.ts",
|
|
67178
|
+
"babel.config.cts",
|
|
67179
|
+
"babel.config.json",
|
|
67180
|
+
".babelrc",
|
|
67181
|
+
".babelrc.js",
|
|
67182
|
+
".babelrc.cjs",
|
|
67183
|
+
".babelrc.mjs",
|
|
67184
|
+
".babelrc.cts",
|
|
67185
|
+
".babelrc.json"
|
|
67186
|
+
];
|
|
67187
|
+
const readUnknownPluginNames = (value) => {
|
|
67188
|
+
if (!Array.isArray(value)) return null;
|
|
67189
|
+
const pluginNames = [];
|
|
67190
|
+
for (const entry of value) {
|
|
67191
|
+
if (typeof entry === "string") {
|
|
67192
|
+
pluginNames.push(entry);
|
|
67193
|
+
continue;
|
|
67194
|
+
}
|
|
67195
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
67196
|
+
pluginNames.push(entry[0]);
|
|
67197
|
+
continue;
|
|
67198
|
+
}
|
|
67199
|
+
return null;
|
|
67200
|
+
}
|
|
67201
|
+
return pluginNames;
|
|
67202
|
+
};
|
|
67203
|
+
const getStaticPropertyName$1 = (propertyName) => {
|
|
67204
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName)) return propertyName.text;
|
|
67205
|
+
return null;
|
|
67206
|
+
};
|
|
67207
|
+
const getStaticPluginName = (expression) => {
|
|
67208
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
67209
|
+
if (ts.isStringLiteralLike(unwrappedExpression)) return unwrappedExpression.text;
|
|
67210
|
+
if (!ts.isArrayLiteralExpression(unwrappedExpression)) return null;
|
|
67211
|
+
const pluginExpression = unwrappedExpression.elements[0];
|
|
67212
|
+
return pluginExpression && ts.isStringLiteralLike(pluginExpression) ? pluginExpression.text : null;
|
|
67213
|
+
};
|
|
67214
|
+
const getPluginNamesFromObject = (objectExpression) => {
|
|
67215
|
+
if (objectExpression.properties.some((property) => ts.isSpreadAssignment(property))) return null;
|
|
67216
|
+
const pluginProperties = objectExpression.properties.filter((property) => ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "plugins");
|
|
67217
|
+
if (pluginProperties.length !== 1) return pluginProperties.length === 0 ? [] : null;
|
|
67218
|
+
const pluginListExpression = unwrapTypescriptExpression(pluginProperties[0].initializer);
|
|
67219
|
+
if (!ts.isArrayLiteralExpression(pluginListExpression)) return null;
|
|
67220
|
+
const pluginNames = [];
|
|
67221
|
+
for (const element of pluginListExpression.elements) {
|
|
67222
|
+
if (ts.isSpreadElement(element)) return null;
|
|
67223
|
+
const pluginName = getStaticPluginName(element);
|
|
67224
|
+
if (pluginName === null) return null;
|
|
67225
|
+
pluginNames.push(pluginName);
|
|
67226
|
+
}
|
|
67227
|
+
return pluginNames;
|
|
67228
|
+
};
|
|
67229
|
+
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";
|
|
67230
|
+
const getDirectExportedObject = (sourceFile) => {
|
|
67231
|
+
const exportedExpressions = [];
|
|
67232
|
+
for (const statement of sourceFile.statements) {
|
|
67233
|
+
if (ts.isExportAssignment(statement)) {
|
|
67234
|
+
exportedExpressions.push(statement.expression);
|
|
67235
|
+
continue;
|
|
67236
|
+
}
|
|
67237
|
+
if (ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(statement.expression.left)) exportedExpressions.push(statement.expression.right);
|
|
67238
|
+
}
|
|
67239
|
+
if (exportedExpressions.length !== 1) return null;
|
|
67240
|
+
const exportedExpression = unwrapTypescriptExpression(exportedExpressions[0]);
|
|
67241
|
+
return ts.isObjectLiteralExpression(exportedExpression) ? exportedExpression : null;
|
|
67242
|
+
};
|
|
67243
|
+
const parseConfigPluginNames = (filePath, contents) => {
|
|
67244
|
+
try {
|
|
67245
|
+
const parsedJson = JSON.parse(contents);
|
|
67246
|
+
return isPlainObject(parsedJson) ? readUnknownPluginNames(parsedJson.plugins) : null;
|
|
67247
|
+
} catch {
|
|
67248
|
+
if (ts.transpileModule(contents, {
|
|
67249
|
+
fileName: filePath,
|
|
67250
|
+
reportDiagnostics: true,
|
|
67251
|
+
compilerOptions: { allowJs: true }
|
|
67252
|
+
}).diagnostics?.some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error)) return null;
|
|
67253
|
+
const exportedObject = getDirectExportedObject(ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filePath)));
|
|
67254
|
+
return exportedObject === null ? null : getPluginNamesFromObject(exportedObject);
|
|
67255
|
+
}
|
|
67256
|
+
};
|
|
67257
|
+
const readStaticBabelPluginNames = (rootDirectory) => {
|
|
67258
|
+
for (const fileName of BABEL_CONFIG_FILE_NAMES$1) {
|
|
67259
|
+
const absoluteFilePath = Path.join(rootDirectory, fileName);
|
|
67260
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
67261
|
+
try {
|
|
67262
|
+
return {
|
|
67263
|
+
filePath: fileName,
|
|
67264
|
+
pluginNames: parseConfigPluginNames(fileName, NFS.readFileSync(absoluteFilePath, "utf-8"))
|
|
67265
|
+
};
|
|
67266
|
+
} catch {
|
|
67267
|
+
return {
|
|
67268
|
+
filePath: fileName,
|
|
67269
|
+
pluginNames: null
|
|
67270
|
+
};
|
|
67271
|
+
}
|
|
67272
|
+
}
|
|
67273
|
+
const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
|
|
67274
|
+
if (!isPlainObject(packageJson.babel)) return null;
|
|
67275
|
+
return {
|
|
67276
|
+
filePath: "package.json",
|
|
67277
|
+
pluginNames: readUnknownPluginNames(packageJson.babel.plugins)
|
|
67278
|
+
};
|
|
67279
|
+
};
|
|
67280
|
+
const REACT_COMPILER_PLUGIN_NAMES = new Set(["babel-plugin-react-compiler", "react-compiler"]);
|
|
67281
|
+
const REANIMATED_PLUGIN_NAME = "react-native-reanimated/plugin";
|
|
67282
|
+
const WORKLETS_PLUGIN_NAME = "react-native-worklets/plugin";
|
|
67283
|
+
const checkReactCompilerPluginOrder = (filePath, pluginNames) => {
|
|
67284
|
+
if (pluginNames.findIndex((pluginName) => REACT_COMPILER_PLUGIN_NAMES.has(pluginName)) <= 0) return [];
|
|
67285
|
+
return [buildReactNativeDiagnostic({
|
|
67286
|
+
filePath,
|
|
67287
|
+
rule: "rn-react-compiler-plugin-first",
|
|
67288
|
+
category: "Performance",
|
|
67289
|
+
message: "The React Compiler Babel plugin is not first, so an earlier transform can change component or hook code before the compiler analyzes it.",
|
|
67290
|
+
help: "Move `babel-plugin-react-compiler` to the first entry in the Babel `plugins` array."
|
|
67291
|
+
})];
|
|
67292
|
+
};
|
|
67293
|
+
const checkReanimatedPluginOrder = (project, filePath, pluginNames) => {
|
|
67294
|
+
const reanimatedMajorVersion = project.reanimatedVersion === null || project.reanimatedVersion === void 0 ? null : getLowestDependencyMajor(project.reanimatedVersion);
|
|
67295
|
+
if (reanimatedMajorVersion === null || reanimatedMajorVersion < 4) return [];
|
|
67296
|
+
const diagnostics = [];
|
|
67297
|
+
if (pluginNames.includes(REANIMATED_PLUGIN_NAME)) diagnostics.push(buildReactNativeDiagnostic({
|
|
67298
|
+
filePath,
|
|
67299
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
67300
|
+
category: "Performance",
|
|
67301
|
+
message: "This Reanimated 4 project still uses `react-native-reanimated/plugin`, which was renamed to the Worklets Babel plugin.",
|
|
67302
|
+
help: "Replace it with `react-native-worklets/plugin` and keep that plugin last in the Babel `plugins` array."
|
|
67303
|
+
}));
|
|
67304
|
+
const workletsPluginIndex = pluginNames.lastIndexOf(WORKLETS_PLUGIN_NAME);
|
|
67305
|
+
if (workletsPluginIndex !== -1 && workletsPluginIndex !== pluginNames.length - 1) diagnostics.push(buildReactNativeDiagnostic({
|
|
67306
|
+
filePath,
|
|
67307
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
67308
|
+
category: "Performance",
|
|
67309
|
+
message: "`react-native-worklets/plugin` is not last in the Babel `plugins` array, so later transforms can prevent worklets from being compiled correctly.",
|
|
67310
|
+
help: "Move `react-native-worklets/plugin` to the final entry in the Babel `plugins` array."
|
|
67311
|
+
}));
|
|
67312
|
+
return diagnostics;
|
|
67313
|
+
};
|
|
67314
|
+
const checkReactNativeBabelPluginOrder = (rootDirectory, project) => {
|
|
67315
|
+
const babelPlugins = readStaticBabelPluginNames(rootDirectory);
|
|
67316
|
+
if (babelPlugins === null || babelPlugins.pluginNames === null) return [];
|
|
67317
|
+
return [...checkReactCompilerPluginOrder(babelPlugins.filePath, babelPlugins.pluginNames), ...checkReanimatedPluginOrder(project, babelPlugins.filePath, babelPlugins.pluginNames)];
|
|
67318
|
+
};
|
|
66958
67319
|
const BUILDER_BOB_PACKAGE = "react-native-builder-bob";
|
|
66959
67320
|
const isBuilderBobLibrary = (packageJson) => {
|
|
66960
67321
|
const bobConfig = packageJson[BUILDER_BOB_PACKAGE];
|
|
@@ -67031,7 +67392,12 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
|
67031
67392
|
const isReactNativeProject = (project) => project.framework === "react-native" || project.framework === "expo" || project.hasReactNativeWorkspace || project.expoVersion !== null;
|
|
67032
67393
|
const checkReactNativeProject = (rootDirectory, project) => {
|
|
67033
67394
|
if (!isReactNativeProject(project)) return [];
|
|
67034
|
-
return [
|
|
67395
|
+
return [
|
|
67396
|
+
...checkReactNativeMetroBabelPreset(rootDirectory),
|
|
67397
|
+
...checkReactNativeBabelPluginOrder(rootDirectory, project),
|
|
67398
|
+
...checkReactNativeAndroidReleaseShrinking(rootDirectory),
|
|
67399
|
+
...checkReactNativeLibraryDependencies(rootDirectory)
|
|
67400
|
+
];
|
|
67035
67401
|
};
|
|
67036
67402
|
const RULE_KEY = "no-vulnerable-react-server-components";
|
|
67037
67403
|
const REACT_RSC_ADVISORIES_BY_MINOR = {
|
|
@@ -67182,17 +67548,6 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
67182
67548
|
}
|
|
67183
67549
|
return diagnostics;
|
|
67184
67550
|
};
|
|
67185
|
-
const getTypescriptScriptKind = (fileName) => {
|
|
67186
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
67187
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
67188
|
-
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
67189
|
-
return ts.ScriptKind.JS;
|
|
67190
|
-
};
|
|
67191
|
-
const unwrapTypescriptExpression = (expression) => {
|
|
67192
|
-
let currentExpression = expression;
|
|
67193
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
67194
|
-
return currentExpression;
|
|
67195
|
-
};
|
|
67196
67551
|
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
67197
67552
|
isAnimationFunction: false,
|
|
67198
67553
|
isMotionComponent: false,
|
|
@@ -67748,7 +68103,11 @@ const buildCapabilities = (project) => {
|
|
|
67748
68103
|
capabilities.add(project.framework);
|
|
67749
68104
|
if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
|
|
67750
68105
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
67751
|
-
if (project.expoVersion !== null)
|
|
68106
|
+
if (project.expoVersion !== null) {
|
|
68107
|
+
capabilities.add("expo");
|
|
68108
|
+
const expoSdkMajorVersion = getLowestDependencyMajor(project.expoVersion);
|
|
68109
|
+
if (expoSdkMajorVersion !== null && expoSdkMajorVersion >= 54) capabilities.add("expo:54");
|
|
68110
|
+
}
|
|
67752
68111
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
67753
68112
|
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
67754
68113
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
@@ -67812,6 +68171,11 @@ const buildCapabilities = (project) => {
|
|
|
67812
68171
|
if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
|
|
67813
68172
|
if (project.isPreES2023Target) capabilities.add("pre-es2023");
|
|
67814
68173
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
68174
|
+
if (project.reanimatedVersion !== void 0 && project.reanimatedVersion !== null) {
|
|
68175
|
+
capabilities.add("reanimated");
|
|
68176
|
+
const reanimatedMajorVersion = getLowestDependencyMajor(project.reanimatedVersion);
|
|
68177
|
+
if (reanimatedMajorVersion !== null && reanimatedMajorVersion >= 4) capabilities.add("reanimated:4");
|
|
68178
|
+
}
|
|
67815
68179
|
if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
|
|
67816
68180
|
if (project.styledComponentsVersion) {
|
|
67817
68181
|
capabilities.add("styled-components");
|
|
@@ -69709,7 +70073,11 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
|
|
|
69709
70073
|
const ROOT_DIRECTORY_PLACEHOLDER = "<root>";
|
|
69710
70074
|
const normalizeConfigForHash = (config) => {
|
|
69711
70075
|
const clone = JSON.parse(JSON.stringify(config));
|
|
69712
|
-
if (clone?.settings?.["react-doctor"])
|
|
70076
|
+
if (clone?.settings?.["react-doctor"]) {
|
|
70077
|
+
const reactDoctorSettings = clone.settings["react-doctor"];
|
|
70078
|
+
reactDoctorSettings.rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
|
|
70079
|
+
if (Array.isArray(reactDoctorSettings.unpluginAutoImportRootDirectories)) reactDoctorSettings.unpluginAutoImportRootDirectories = [ROOT_DIRECTORY_PLACEHOLDER];
|
|
70080
|
+
}
|
|
69713
70081
|
if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
|
|
69714
70082
|
return clone;
|
|
69715
70083
|
};
|
|
@@ -69868,13 +70236,14 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
69868
70236
|
}
|
|
69869
70237
|
return enabled;
|
|
69870
70238
|
};
|
|
69871
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
70239
|
+
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 }) => {
|
|
69872
70240
|
const hasIncludedTags = includedTags.size > 0;
|
|
69873
70241
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
69874
70242
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
69875
70243
|
const jsPlugins = [];
|
|
69876
70244
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
69877
70245
|
const capabilities = getCapabilities(project);
|
|
70246
|
+
const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
|
|
69878
70247
|
const enabledReactDoctorRules = {};
|
|
69879
70248
|
for (const registryEntry of REACT_DOCTOR_RULES) {
|
|
69880
70249
|
const rule = reactDoctorPlugin.rules[registryEntry.id];
|
|
@@ -69920,8 +70289,16 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
69920
70289
|
jsPlugins: [...jsPlugins, pluginPath],
|
|
69921
70290
|
settings: { "react-doctor": {
|
|
69922
70291
|
framework: project.framework,
|
|
69923
|
-
rootDirectory:
|
|
70292
|
+
rootDirectory: settingsRootDirectory,
|
|
69924
70293
|
capabilities: [...capabilities].sort(),
|
|
70294
|
+
...runtimeGlobals && runtimeGlobals.length > 0 ? { runtimeGlobals: [...runtimeGlobals] } : {},
|
|
70295
|
+
...unpluginAutoImportGlobalScopes && unpluginAutoImportGlobalScopes.length > 0 ? {
|
|
70296
|
+
unpluginAutoImportRootDirectories: [...new Set([settingsRootDirectory, project.rootDirectory])],
|
|
70297
|
+
unpluginAutoImportGlobalScopes: unpluginAutoImportGlobalScopes.map((scope) => ({
|
|
70298
|
+
directory: scope.directory,
|
|
70299
|
+
names: [...scope.names]
|
|
70300
|
+
}))
|
|
70301
|
+
} : {},
|
|
69925
70302
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
69926
70303
|
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
69927
70304
|
} },
|
|
@@ -69932,6 +70309,245 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
69932
70309
|
}
|
|
69933
70310
|
};
|
|
69934
70311
|
};
|
|
70312
|
+
const AUTO_IMPORT_ADAPTER_PATTERN = /^unplugin-auto-import\/(?:astro|esbuild|rollup|rolldown|rspack|vite|webpack)$/;
|
|
70313
|
+
const CONFIG_BASENAMES = [
|
|
70314
|
+
"astro.config",
|
|
70315
|
+
"esbuild.config",
|
|
70316
|
+
"rollup.config",
|
|
70317
|
+
"rolldown.config",
|
|
70318
|
+
"rspack.config",
|
|
70319
|
+
"vite.config",
|
|
70320
|
+
"webpack.config"
|
|
70321
|
+
];
|
|
70322
|
+
const CONFIG_EXTENSIONS = [
|
|
70323
|
+
".cjs",
|
|
70324
|
+
".cts",
|
|
70325
|
+
".js",
|
|
70326
|
+
".mjs",
|
|
70327
|
+
".mts",
|
|
70328
|
+
".ts"
|
|
70329
|
+
];
|
|
70330
|
+
const CONFIG_FILENAMES = new Set(CONFIG_BASENAMES.flatMap((basename) => CONFIG_EXTENSIONS.map((extension) => `${basename}${extension}`)));
|
|
70331
|
+
const DEFAULT_ESLINT_GLOBALS_PATH = ".eslintrc-auto-import.json";
|
|
70332
|
+
const SUPPORTED_GLOBAL_VALUES = new Set([
|
|
70333
|
+
true,
|
|
70334
|
+
false,
|
|
70335
|
+
"readable",
|
|
70336
|
+
"readonly",
|
|
70337
|
+
"writable",
|
|
70338
|
+
"writeable"
|
|
70339
|
+
]);
|
|
70340
|
+
const getStaticProperty = (objectExpression, propertyName) => objectExpression.properties.find((property) => {
|
|
70341
|
+
if (ts.isSpreadAssignment(property)) return false;
|
|
70342
|
+
const name = ts.isComputedPropertyName(property.name) ? unwrapTypescriptExpression(property.name.expression) : property.name;
|
|
70343
|
+
return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && name.text === propertyName;
|
|
70344
|
+
}) ?? null;
|
|
70345
|
+
const hasNonLiteralComputedProperty = (objectExpression) => objectExpression.properties.some((property) => !ts.isSpreadAssignment(property) && ts.isComputedPropertyName(property.name) && !ts.isStringLiteralLike(unwrapTypescriptExpression(property.name.expression)));
|
|
70346
|
+
const getStaticPropertyAssignment = (objectExpression, propertyName) => {
|
|
70347
|
+
const property = getStaticProperty(objectExpression, propertyName);
|
|
70348
|
+
return property && ts.isPropertyAssignment(property) ? property : null;
|
|
70349
|
+
};
|
|
70350
|
+
const getRequireModuleSpecifier = (expression) => {
|
|
70351
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
70352
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === "default") return getRequireModuleSpecifier(unwrappedExpression.expression);
|
|
70353
|
+
if (!ts.isCallExpression(unwrappedExpression) || !ts.isIdentifier(unwrappedExpression.expression) || unwrappedExpression.expression.text !== "require" || unwrappedExpression.arguments.length !== 1) return null;
|
|
70354
|
+
const moduleSpecifier = unwrappedExpression.arguments[0];
|
|
70355
|
+
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
70356
|
+
};
|
|
70357
|
+
const getRequiredPropertyModuleSpecifier = (expression, propertyName) => {
|
|
70358
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
70359
|
+
return ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === propertyName ? getRequireModuleSpecifier(unwrappedExpression.expression) : null;
|
|
70360
|
+
};
|
|
70361
|
+
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");
|
|
70362
|
+
const isTopLevelExpression = (node) => {
|
|
70363
|
+
let ancestor = node.parent;
|
|
70364
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
70365
|
+
if (ts.isExpressionStatement(ancestor)) return ts.isSourceFile(ancestor.parent);
|
|
70366
|
+
if (!ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isAwaitExpression(ancestor)) return false;
|
|
70367
|
+
ancestor = ancestor.parent;
|
|
70368
|
+
}
|
|
70369
|
+
return false;
|
|
70370
|
+
};
|
|
70371
|
+
const isInsideActiveConfigProperty = (node, propertyName, sourceFile, esbuildBindings, esbuildNamespaceBindings) => {
|
|
70372
|
+
let ancestor = node.parent;
|
|
70373
|
+
let didFindConfigProperty = false;
|
|
70374
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
70375
|
+
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;
|
|
70376
|
+
if (ts.isPropertyAssignment(ancestor)) {
|
|
70377
|
+
const isConfigProperty = (ts.isIdentifier(ancestor.name) || ts.isStringLiteralLike(ancestor.name)) && ancestor.name.text === propertyName;
|
|
70378
|
+
if (didFindConfigProperty || !isConfigProperty) return false;
|
|
70379
|
+
if (!ts.isObjectLiteralExpression(ancestor.parent) || ancestor.parent.properties.some(ts.isSpreadAssignment)) return false;
|
|
70380
|
+
didFindConfigProperty = true;
|
|
70381
|
+
ancestor = ancestor.parent;
|
|
70382
|
+
continue;
|
|
70383
|
+
}
|
|
70384
|
+
if (didFindConfigProperty) {
|
|
70385
|
+
if (ts.isExportAssignment(ancestor)) return true;
|
|
70386
|
+
if (isCommonJsExportAssignment(ancestor, sourceFile)) return isTopLevelExpression(ancestor);
|
|
70387
|
+
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);
|
|
70388
|
+
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;
|
|
70389
|
+
}
|
|
70390
|
+
ancestor = ancestor.parent;
|
|
70391
|
+
}
|
|
70392
|
+
return false;
|
|
70393
|
+
};
|
|
70394
|
+
const getGlobalsPathFromActiveAutoImportCall = (callExpression, packageDirectory) => {
|
|
70395
|
+
const optionsExpression = callExpression.arguments[0];
|
|
70396
|
+
if (!optionsExpression) return null;
|
|
70397
|
+
const unwrappedOptions = unwrapTypescriptExpression(optionsExpression);
|
|
70398
|
+
if (!ts.isObjectLiteralExpression(unwrappedOptions)) return null;
|
|
70399
|
+
if (unwrappedOptions.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(unwrappedOptions)) return null;
|
|
70400
|
+
if (getStaticProperty(unwrappedOptions, "include") || getStaticProperty(unwrappedOptions, "exclude")) return null;
|
|
70401
|
+
const eslintrcProperty = getStaticPropertyAssignment(unwrappedOptions, "eslintrc");
|
|
70402
|
+
if (!eslintrcProperty) return null;
|
|
70403
|
+
const eslintrcExpression = unwrapTypescriptExpression(eslintrcProperty.initializer);
|
|
70404
|
+
if (!ts.isObjectLiteralExpression(eslintrcExpression)) return null;
|
|
70405
|
+
if (eslintrcExpression.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(eslintrcExpression)) return null;
|
|
70406
|
+
const enabledProperty = getStaticPropertyAssignment(eslintrcExpression, "enabled");
|
|
70407
|
+
if (!enabledProperty || unwrapTypescriptExpression(enabledProperty.initializer).kind !== ts.SyntaxKind.TrueKeyword) return null;
|
|
70408
|
+
const filepathProperty = getStaticProperty(eslintrcExpression, "filepath");
|
|
70409
|
+
if (!filepathProperty) return Path.join(packageDirectory, DEFAULT_ESLINT_GLOBALS_PATH);
|
|
70410
|
+
if (!ts.isPropertyAssignment(filepathProperty)) return null;
|
|
70411
|
+
const filepathExpression = unwrapTypescriptExpression(filepathProperty.initializer);
|
|
70412
|
+
return ts.isStringLiteralLike(filepathExpression) ? Path.resolve(packageDirectory, filepathExpression.text) : null;
|
|
70413
|
+
};
|
|
70414
|
+
const collectGlobalsPathsFromConfig = (configPath, packageDirectory) => {
|
|
70415
|
+
let sourceText;
|
|
70416
|
+
try {
|
|
70417
|
+
sourceText = NFS.readFileSync(configPath, "utf8");
|
|
70418
|
+
} catch {
|
|
70419
|
+
return {
|
|
70420
|
+
didFindActiveAutoImport: false,
|
|
70421
|
+
globalsPaths: []
|
|
70422
|
+
};
|
|
70423
|
+
}
|
|
70424
|
+
const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true);
|
|
70425
|
+
const autoImportBindings = /* @__PURE__ */ new Map();
|
|
70426
|
+
const esbuildBindings = /* @__PURE__ */ new Set();
|
|
70427
|
+
const esbuildNamespaceBindings = /* @__PURE__ */ new Set();
|
|
70428
|
+
for (const statement of sourceFile.statements) {
|
|
70429
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
70430
|
+
const moduleSpecifier = statement.moduleSpecifier.text;
|
|
70431
|
+
if (AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
70432
|
+
const defaultBinding = statement.importClause?.name;
|
|
70433
|
+
if (defaultBinding) autoImportBindings.set(defaultBinding.text, moduleSpecifier);
|
|
70434
|
+
}
|
|
70435
|
+
if (moduleSpecifier === "esbuild") {
|
|
70436
|
+
const defaultBinding = statement.importClause?.name;
|
|
70437
|
+
if (defaultBinding) esbuildNamespaceBindings.add(defaultBinding.text);
|
|
70438
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
70439
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
70440
|
+
for (const importSpecifier of namedBindings.elements) if ((importSpecifier.propertyName ?? importSpecifier.name).text === "build") esbuildBindings.add(importSpecifier.name.text);
|
|
70441
|
+
}
|
|
70442
|
+
if (namedBindings && ts.isNamespaceImport(namedBindings)) esbuildNamespaceBindings.add(namedBindings.name.text);
|
|
70443
|
+
}
|
|
70444
|
+
}
|
|
70445
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
70446
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
70447
|
+
if (!declaration.initializer) continue;
|
|
70448
|
+
const declarationName = ts.isIdentifier(declaration.name) ? declaration.name.text : null;
|
|
70449
|
+
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
70450
|
+
if (declarationName && moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) autoImportBindings.set(declarationName, moduleSpecifier);
|
|
70451
|
+
if (moduleSpecifier === "esbuild") {
|
|
70452
|
+
if (declarationName) esbuildNamespaceBindings.add(declarationName);
|
|
70453
|
+
if (ts.isObjectBindingPattern(declaration.name)) for (const bindingElement of declaration.name.elements) {
|
|
70454
|
+
const importedName = bindingElement.propertyName ?? bindingElement.name;
|
|
70455
|
+
if (ts.isIdentifier(importedName) && importedName.text === "build" && ts.isIdentifier(bindingElement.name)) esbuildBindings.add(bindingElement.name.text);
|
|
70456
|
+
}
|
|
70457
|
+
}
|
|
70458
|
+
if (declarationName && getRequiredPropertyModuleSpecifier(declaration.initializer, "build") === "esbuild") esbuildBindings.add(declarationName);
|
|
70459
|
+
}
|
|
70460
|
+
}
|
|
70461
|
+
const globalsPaths = /* @__PURE__ */ new Set();
|
|
70462
|
+
let didFindActiveAutoImport = false;
|
|
70463
|
+
let didFindUnsafeActiveAutoImport = false;
|
|
70464
|
+
const visit = (node) => {
|
|
70465
|
+
if (ts.isCallExpression(node)) {
|
|
70466
|
+
const moduleSpecifier = ts.isIdentifier(node.expression) ? autoImportBindings.get(node.expression.text) : getRequireModuleSpecifier(node.expression);
|
|
70467
|
+
if (moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
70468
|
+
if (isInsideActiveConfigProperty(node, moduleSpecifier.endsWith("/astro") ? "integrations" : "plugins", sourceFile, esbuildBindings, esbuildNamespaceBindings)) {
|
|
70469
|
+
didFindActiveAutoImport = true;
|
|
70470
|
+
const globalsPath = getGlobalsPathFromActiveAutoImportCall(node, packageDirectory);
|
|
70471
|
+
if (globalsPath) globalsPaths.add(globalsPath);
|
|
70472
|
+
else didFindUnsafeActiveAutoImport = true;
|
|
70473
|
+
}
|
|
70474
|
+
}
|
|
70475
|
+
}
|
|
70476
|
+
ts.forEachChild(node, visit);
|
|
70477
|
+
};
|
|
70478
|
+
visit(sourceFile);
|
|
70479
|
+
return {
|
|
70480
|
+
didFindActiveAutoImport,
|
|
70481
|
+
globalsPaths: didFindUnsafeActiveAutoImport ? [] : [...globalsPaths]
|
|
70482
|
+
};
|
|
70483
|
+
};
|
|
70484
|
+
const collectGeneratedGlobalNames = (globalsPath, rootDirectory) => {
|
|
70485
|
+
const relativePath = Path.relative(rootDirectory, globalsPath);
|
|
70486
|
+
if (relativePath.startsWith("..") || Path.isAbsolute(relativePath)) return [];
|
|
70487
|
+
const parsed = failOpenReadJson(globalsPath, null);
|
|
70488
|
+
if (!isPlainObject(parsed) || !isPlainObject(parsed.globals)) return [];
|
|
70489
|
+
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();
|
|
70490
|
+
};
|
|
70491
|
+
const findOwningPackageDirectory = (absoluteFilePath, rootDirectory, cache) => {
|
|
70492
|
+
let currentDirectory = Path.dirname(absoluteFilePath);
|
|
70493
|
+
const visitedDirectories = [];
|
|
70494
|
+
while (true) {
|
|
70495
|
+
const cachedDirectory = cache.get(currentDirectory);
|
|
70496
|
+
if (cachedDirectory !== void 0) {
|
|
70497
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, cachedDirectory);
|
|
70498
|
+
return cachedDirectory;
|
|
70499
|
+
}
|
|
70500
|
+
const relativeDirectory = Path.relative(rootDirectory, currentDirectory);
|
|
70501
|
+
if (relativeDirectory.startsWith("..") || Path.isAbsolute(relativeDirectory)) {
|
|
70502
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
70503
|
+
return null;
|
|
70504
|
+
}
|
|
70505
|
+
visitedDirectories.push(currentDirectory);
|
|
70506
|
+
if (NFS.existsSync(Path.join(currentDirectory, "package.json"))) {
|
|
70507
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, currentDirectory);
|
|
70508
|
+
return currentDirectory;
|
|
70509
|
+
}
|
|
70510
|
+
if (currentDirectory === rootDirectory) {
|
|
70511
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
70512
|
+
return null;
|
|
70513
|
+
}
|
|
70514
|
+
currentDirectory = Path.dirname(currentDirectory);
|
|
70515
|
+
}
|
|
70516
|
+
};
|
|
70517
|
+
const collectPackageGlobalNames = (packageDirectory, rootDirectory) => {
|
|
70518
|
+
let directoryEntries;
|
|
70519
|
+
try {
|
|
70520
|
+
directoryEntries = NFS.readdirSync(packageDirectory, { withFileTypes: true });
|
|
70521
|
+
} catch {
|
|
70522
|
+
return [];
|
|
70523
|
+
}
|
|
70524
|
+
const configuredGlobalsPaths = [];
|
|
70525
|
+
for (const entry of directoryEntries) {
|
|
70526
|
+
if (!entry.isFile() && !entry.isSymbolicLink() || !CONFIG_FILENAMES.has(entry.name)) continue;
|
|
70527
|
+
const configGlobalsPaths = collectGlobalsPathsFromConfig(Path.join(packageDirectory, entry.name), packageDirectory);
|
|
70528
|
+
if (configGlobalsPaths.didFindActiveAutoImport) configuredGlobalsPaths.push(configGlobalsPaths.globalsPaths.toSorted());
|
|
70529
|
+
}
|
|
70530
|
+
if (configuredGlobalsPaths.length === 0) return [];
|
|
70531
|
+
const globalsPaths = configuredGlobalsPaths[0];
|
|
70532
|
+
if (configuredGlobalsPaths.some((candidatePaths) => candidatePaths.length !== globalsPaths.length || candidatePaths.some((candidatePath, index) => candidatePath !== globalsPaths[index]))) return [];
|
|
70533
|
+
const names = /* @__PURE__ */ new Set();
|
|
70534
|
+
for (const globalsPath of globalsPaths) for (const name of collectGeneratedGlobalNames(globalsPath, rootDirectory)) names.add(name);
|
|
70535
|
+
return [...names].sort();
|
|
70536
|
+
};
|
|
70537
|
+
const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }) => {
|
|
70538
|
+
const absoluteRootDirectory = Path.resolve(rootDirectory);
|
|
70539
|
+
const packageDirectoryCache = /* @__PURE__ */ new Map();
|
|
70540
|
+
const packageDirectories = /* @__PURE__ */ new Set();
|
|
70541
|
+
for (const candidateFile of candidateFiles) {
|
|
70542
|
+
const packageDirectory = findOwningPackageDirectory(Path.resolve(absoluteRootDirectory, candidateFile), absoluteRootDirectory, packageDirectoryCache);
|
|
70543
|
+
if (packageDirectory) packageDirectories.add(packageDirectory);
|
|
70544
|
+
}
|
|
70545
|
+
const scopes = [...packageDirectories].map((packageDirectory) => ({
|
|
70546
|
+
directory: Path.relative(absoluteRootDirectory, packageDirectory).replaceAll("\\", "/"),
|
|
70547
|
+
names: collectPackageGlobalNames(packageDirectory, absoluteRootDirectory)
|
|
70548
|
+
})).sort((firstScope, secondScope) => firstScope.directory.localeCompare(secondScope.directory));
|
|
70549
|
+
return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
|
|
70550
|
+
};
|
|
69935
70551
|
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
69936
70552
|
const decodeFileDiagnostics = (raw) => {
|
|
69937
70553
|
if (!Array.isArray(raw)) return null;
|
|
@@ -70254,6 +70870,12 @@ const appendReanimatedSharedValueHint = (help, rule, project) => {
|
|
|
70254
70870
|
if (!help) return REANIMATED_SHARED_VALUE_HINT;
|
|
70255
70871
|
return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
|
|
70256
70872
|
};
|
|
70873
|
+
const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
70874
|
+
const boundedOffset = Math.min(Math.max(utf8Offset, 0), sourceBuffer.length);
|
|
70875
|
+
let lineStartOffset = boundedOffset;
|
|
70876
|
+
while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
|
|
70877
|
+
return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
|
|
70878
|
+
};
|
|
70257
70879
|
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
70258
70880
|
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
70259
70881
|
const KNOWN_SECRET_RULES = [
|
|
@@ -70969,7 +71591,7 @@ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORI
|
|
|
70969
71591
|
* with empty text still carry a useful jump target, so they're kept
|
|
70970
71592
|
* with a neutral message.
|
|
70971
71593
|
*/
|
|
70972
|
-
const buildRelatedLocations = (labels, filePath) => {
|
|
71594
|
+
const buildRelatedLocations = (labels, filePath, sourceBuffer) => {
|
|
70973
71595
|
if (labels.length <= 1) return [];
|
|
70974
71596
|
const related = [];
|
|
70975
71597
|
for (let labelIndex = 1; labelIndex < labels.length; labelIndex++) {
|
|
@@ -70977,8 +71599,8 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
70977
71599
|
if (!label?.span) continue;
|
|
70978
71600
|
related.push({
|
|
70979
71601
|
filePath,
|
|
70980
|
-
line: label.span.line ?? 0,
|
|
70981
|
-
column: label.span.column ?? 0,
|
|
71602
|
+
line: sourceBuffer === null ? label.span.line ?? 0 : lineOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
71603
|
+
column: sourceBuffer === null ? label.span.column ?? 0 : columnOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
70982
71604
|
offset: label.span.offset,
|
|
70983
71605
|
length: label.span.length,
|
|
70984
71606
|
message: label.label ?? ""
|
|
@@ -70998,7 +71620,7 @@ const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnos
|
|
|
70998
71620
|
* to the first `{`. Raises `OxlintOutputUnparseable` when the
|
|
70999
71621
|
* stdout isn't valid JSON or doesn't carry a `diagnostics` array.
|
|
71000
71622
|
*/
|
|
71001
|
-
const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
71623
|
+
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath) => {
|
|
71002
71624
|
if (!stdout) return [];
|
|
71003
71625
|
const jsonStart = stdout.indexOf("{");
|
|
71004
71626
|
const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
|
|
@@ -71015,8 +71637,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71015
71637
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
71016
71638
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
71017
71639
|
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
71640
|
+
const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
71641
|
+
const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
|
|
71018
71642
|
const readSourceBuffer = (filename) => {
|
|
71019
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71643
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71020
71644
|
const cached = sourceBufferCache.get(absolutePath);
|
|
71021
71645
|
if (cached !== void 0) return cached;
|
|
71022
71646
|
let sourceBuffer;
|
|
@@ -71029,7 +71653,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71029
71653
|
return sourceBuffer;
|
|
71030
71654
|
};
|
|
71031
71655
|
const readSourceLines = (filename) => {
|
|
71032
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71656
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71033
71657
|
const cached = sourceLinesCache.get(absolutePath);
|
|
71034
71658
|
if (cached !== void 0) return cached;
|
|
71035
71659
|
const sourceBuffer = readSourceBuffer(filename);
|
|
@@ -71038,27 +71662,30 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71038
71662
|
return sourceLines;
|
|
71039
71663
|
};
|
|
71040
71664
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
71041
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
71665
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
71042
71666
|
const cached = minifiedFileCache.get(absolutePath);
|
|
71043
71667
|
if (cached !== void 0) return cached;
|
|
71044
71668
|
const minified = isMinifiedSource(absolutePath);
|
|
71045
71669
|
minifiedFileCache.set(absolutePath, minified);
|
|
71046
71670
|
return minified;
|
|
71047
71671
|
};
|
|
71048
|
-
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) => {
|
|
71672
|
+
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) => {
|
|
71049
71673
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
71050
71674
|
const primaryLabel = diagnostic.labels[0];
|
|
71051
71675
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
71052
|
-
const
|
|
71676
|
+
const mappedSourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
71677
|
+
const normalizedFilePath = (mappedSourceFilename ?? diagnostic.filename).replaceAll("\\", "/");
|
|
71053
71678
|
const primarySpan = primaryLabel?.span;
|
|
71054
71679
|
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
71055
|
-
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
71680
|
+
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath, mappedSourceFilename === void 0 ? null : sourceBuffer);
|
|
71056
71681
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
71057
71682
|
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
71058
71683
|
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
71059
|
-
const
|
|
71684
|
+
const primaryLineNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.line ?? 0;
|
|
71685
|
+
const primaryColumnNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? columnOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.column ?? 0;
|
|
71686
|
+
const primaryLineIndex = primarySpan ? primaryLineNumber - 1 : -1;
|
|
71060
71687
|
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
71061
|
-
const primaryColumnIndex = primarySpan ?
|
|
71688
|
+
const primaryColumnIndex = primarySpan ? primaryColumnNumber - 1 : -1;
|
|
71062
71689
|
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
71063
71690
|
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
71064
71691
|
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
@@ -71071,8 +71698,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
71071
71698
|
message: cleaned.message,
|
|
71072
71699
|
help: cleaned.help,
|
|
71073
71700
|
url: diagnostic.url,
|
|
71074
|
-
line:
|
|
71075
|
-
column:
|
|
71701
|
+
line: primaryLineNumber,
|
|
71702
|
+
column: primaryColumnNumber,
|
|
71076
71703
|
...primarySpan ? {
|
|
71077
71704
|
offset: primarySpan.offset,
|
|
71078
71705
|
length: primarySpan.length,
|
|
@@ -71260,7 +71887,11 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
71260
71887
|
* loop with a slimmer config in that case.
|
|
71261
71888
|
*/
|
|
71262
71889
|
const spawnLintBatches = async (input) => {
|
|
71263
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
71890
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
71891
|
+
const resolveSourcePath = (filePath) => {
|
|
71892
|
+
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
71893
|
+
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
71894
|
+
};
|
|
71264
71895
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
71265
71896
|
let rescueDeadlineEpochMs;
|
|
71266
71897
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
@@ -71280,7 +71911,7 @@ const spawnLintBatches = async (input) => {
|
|
|
71280
71911
|
}
|
|
71281
71912
|
const batchArgs = [...baseArgs, ...batch];
|
|
71282
71913
|
try {
|
|
71283
|
-
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory);
|
|
71914
|
+
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory, sourcePathByLintPath);
|
|
71284
71915
|
} catch (error) {
|
|
71285
71916
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
71286
71917
|
if (isPastDeadline()) {
|
|
@@ -71386,10 +72017,12 @@ const spawnLintBatches = async (input) => {
|
|
|
71386
72017
|
onPartialFailure(buildMessage(`${skippedFiles.slice(0, 3).join(", ")}${skippedFiles.length > 3 ? `, +${skippedFiles.length - 3} more` : ""}`));
|
|
71387
72018
|
};
|
|
71388
72019
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
71389
|
-
|
|
71390
|
-
|
|
72020
|
+
const droppedSourceFiles = [...new Set(droppedFiles.map(resolveSourcePath))];
|
|
72021
|
+
const deadlineSkippedSourceFiles = [...new Set(outcome.deadlineSkippedFiles.map(resolveSourcePath))];
|
|
72022
|
+
reportSkippedFiles(droppedSourceFiles, (fileListPreview) => `${droppedSourceFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
72023
|
+
reportSkippedFiles(deadlineSkippedSourceFiles, (fileListPreview) => `${deadlineSkippedSourceFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
71391
72024
|
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
71392
|
-
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
72025
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)).map(resolveSourcePath))].sort());
|
|
71393
72026
|
return dedupeDiagnostics(diagnostics);
|
|
71394
72027
|
};
|
|
71395
72028
|
let didValidate = false;
|
|
@@ -71488,6 +72121,266 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
|
71488
72121
|
}
|
|
71489
72122
|
return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
|
|
71490
72123
|
};
|
|
72124
|
+
const THREE_MODULE_IMPORT_PATTERN = /\b(?:from\s*|import\s*(?:\(\s*)?|require\s*\(\s*)["']three(?:\/[^"']*)?["']/;
|
|
72125
|
+
const containsThreeModuleImport = (sourceText) => THREE_MODULE_IMPORT_PATTERN.test(sourceText);
|
|
72126
|
+
const COMMENT_OPEN = "<!--";
|
|
72127
|
+
const COMMENT_CLOSE = "-->";
|
|
72128
|
+
const FRONTMATTER_FENCE = "---";
|
|
72129
|
+
const SCRIPT_TAG_NAME = "script";
|
|
72130
|
+
const SCRIPT_OPEN = `<${SCRIPT_TAG_NAME}`;
|
|
72131
|
+
const SCRIPT_CLOSE = `</${SCRIPT_TAG_NAME}`;
|
|
72132
|
+
const TEMPLATE_TAG_NAME = "template";
|
|
72133
|
+
const TEMPLATE_CLOSE = `</${TEMPLATE_TAG_NAME}`;
|
|
72134
|
+
const JAVASCRIPT_MIME_TYPES = new Set([
|
|
72135
|
+
"application/ecmascript",
|
|
72136
|
+
"application/javascript",
|
|
72137
|
+
"application/x-ecmascript",
|
|
72138
|
+
"application/x-javascript",
|
|
72139
|
+
"text/ecmascript",
|
|
72140
|
+
"text/javascript",
|
|
72141
|
+
"text/javascript1.0",
|
|
72142
|
+
"text/javascript1.1",
|
|
72143
|
+
"text/javascript1.2",
|
|
72144
|
+
"text/javascript1.3",
|
|
72145
|
+
"text/javascript1.4",
|
|
72146
|
+
"text/javascript1.5",
|
|
72147
|
+
"text/jscript",
|
|
72148
|
+
"text/livescript",
|
|
72149
|
+
"text/x-ecmascript",
|
|
72150
|
+
"text/x-javascript"
|
|
72151
|
+
]);
|
|
72152
|
+
const RAW_TEXT_TAG_NAMES = new Set([
|
|
72153
|
+
"iframe",
|
|
72154
|
+
"noembed",
|
|
72155
|
+
"noframes",
|
|
72156
|
+
"noscript",
|
|
72157
|
+
"style",
|
|
72158
|
+
"textarea",
|
|
72159
|
+
"title",
|
|
72160
|
+
"xmp"
|
|
72161
|
+
]);
|
|
72162
|
+
const PLAINTEXT_TAG_NAME = "plaintext";
|
|
72163
|
+
const TAG_OPEN_UTF8_BYTE = "<".charCodeAt(0);
|
|
72164
|
+
const TAG_CLOSE_UTF8_BYTE = ">".charCodeAt(0);
|
|
72165
|
+
const SINGLE_QUOTE_UTF8_BYTE = "'".charCodeAt(0);
|
|
72166
|
+
const DOUBLE_QUOTE_UTF8_BYTE = "\"".charCodeAt(0);
|
|
72167
|
+
const ATTRIBUTE_ASSIGNMENT_UTF8_BYTE = "=".charCodeAt(0);
|
|
72168
|
+
const TAG_SELF_CLOSE_UTF8_BYTE = "/".charCodeAt(0);
|
|
72169
|
+
const TAB_UTF8_BYTE = " ".charCodeAt(0);
|
|
72170
|
+
const FORM_FEED_UTF8_BYTE = "\f".charCodeAt(0);
|
|
72171
|
+
const isHtmlWhitespace = (byte) => byte === TAB_UTF8_BYTE || byte === 10 || byte === FORM_FEED_UTF8_BYTE || byte === 13 || byte === 32;
|
|
72172
|
+
const matchesAsciiCaseInsensitive = (sourceBuffer, startByte, expected) => {
|
|
72173
|
+
if (startByte + expected.length > sourceBuffer.length) return false;
|
|
72174
|
+
for (let expectedIndex = 0; expectedIndex < expected.length; expectedIndex++) {
|
|
72175
|
+
const sourceByte = sourceBuffer[startByte + expectedIndex];
|
|
72176
|
+
if (sourceByte === void 0 || String.fromCharCode(sourceByte).toLowerCase() !== expected[expectedIndex]) return false;
|
|
72177
|
+
}
|
|
72178
|
+
return true;
|
|
72179
|
+
};
|
|
72180
|
+
const isTagBoundary = (byte) => byte === TAG_CLOSE_UTF8_BYTE || byte === TAG_SELF_CLOSE_UTF8_BYTE || isHtmlWhitespace(byte);
|
|
72181
|
+
const isPotentialTagStart = (byte) => {
|
|
72182
|
+
if (byte === void 0) return false;
|
|
72183
|
+
return /[A-Za-z!/?]/.test(String.fromCharCode(byte));
|
|
72184
|
+
};
|
|
72185
|
+
const findLineEnd = (sourceBuffer, lineStartByte) => {
|
|
72186
|
+
let byteIndex = lineStartByte;
|
|
72187
|
+
while (byteIndex < sourceBuffer.length && sourceBuffer[byteIndex] !== 10 && sourceBuffer[byteIndex] !== 13) byteIndex++;
|
|
72188
|
+
return byteIndex;
|
|
72189
|
+
};
|
|
72190
|
+
const findNextLineStart = (sourceBuffer, lineStartByte) => {
|
|
72191
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
72192
|
+
if (sourceBuffer[lineEndByte] === 13 && sourceBuffer[lineEndByte + 1] === 10) return lineEndByte + 2;
|
|
72193
|
+
return Math.min(lineEndByte + 1, sourceBuffer.length);
|
|
72194
|
+
};
|
|
72195
|
+
const isFrontmatterFenceLine = (sourceBuffer, lineStartByte) => {
|
|
72196
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, lineStartByte, FRONTMATTER_FENCE)) return false;
|
|
72197
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
72198
|
+
for (let byteIndex = lineStartByte + 3; byteIndex < lineEndByte; byteIndex++) if (!isHtmlWhitespace(sourceBuffer[byteIndex])) return false;
|
|
72199
|
+
return true;
|
|
72200
|
+
};
|
|
72201
|
+
const findFrontmatterEnd = (sourceBuffer) => {
|
|
72202
|
+
if (!isFrontmatterFenceLine(sourceBuffer, 0)) return 0;
|
|
72203
|
+
const openingFenceEndByte = findLineEnd(sourceBuffer, 0);
|
|
72204
|
+
let lineStartByte = findNextLineStart(sourceBuffer, 0);
|
|
72205
|
+
while (lineStartByte < sourceBuffer.length) {
|
|
72206
|
+
if (isFrontmatterFenceLine(sourceBuffer, lineStartByte)) return findLineEnd(sourceBuffer, lineStartByte);
|
|
72207
|
+
lineStartByte = findNextLineStart(sourceBuffer, lineStartByte);
|
|
72208
|
+
}
|
|
72209
|
+
return openingFenceEndByte;
|
|
72210
|
+
};
|
|
72211
|
+
const maskByteRange = (maskedBuffer, startByte, endByte) => {
|
|
72212
|
+
for (let byteIndex = startByte; byteIndex < endByte; byteIndex++) {
|
|
72213
|
+
const byte = maskedBuffer[byteIndex];
|
|
72214
|
+
if (byte !== 10 && byte !== 13) maskedBuffer[byteIndex] = 32;
|
|
72215
|
+
}
|
|
72216
|
+
};
|
|
72217
|
+
const readStartTagName = (sourceBuffer, tagStartByte) => {
|
|
72218
|
+
const firstNameByte = sourceBuffer[tagStartByte + 1];
|
|
72219
|
+
if (firstNameByte === void 0 || !/[A-Za-z]/.test(String.fromCharCode(firstNameByte))) return null;
|
|
72220
|
+
let nameEndByte = tagStartByte + 2;
|
|
72221
|
+
while (nameEndByte < sourceBuffer.length && /[A-Za-z0-9:-]/.test(String.fromCharCode(sourceBuffer[nameEndByte] ?? 32))) nameEndByte++;
|
|
72222
|
+
return sourceBuffer.subarray(tagStartByte + 1, nameEndByte).toString("ascii").toLowerCase();
|
|
72223
|
+
};
|
|
72224
|
+
const findTagEnd = (sourceBuffer, startByte) => {
|
|
72225
|
+
let quoteByte = null;
|
|
72226
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) {
|
|
72227
|
+
const byte = sourceBuffer[byteIndex];
|
|
72228
|
+
if (quoteByte !== null) {
|
|
72229
|
+
if (byte === quoteByte) quoteByte = null;
|
|
72230
|
+
continue;
|
|
72231
|
+
}
|
|
72232
|
+
if (byte === SINGLE_QUOTE_UTF8_BYTE || byte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
72233
|
+
quoteByte = byte;
|
|
72234
|
+
continue;
|
|
72235
|
+
}
|
|
72236
|
+
if (byte === TAG_CLOSE_UTF8_BYTE) return byteIndex;
|
|
72237
|
+
}
|
|
72238
|
+
return sourceBuffer.length;
|
|
72239
|
+
};
|
|
72240
|
+
const parseScriptAttributes = (sourceBuffer, attributesStartByte, tagEndByte) => {
|
|
72241
|
+
let byteIndex = attributesStartByte;
|
|
72242
|
+
let hasSource = false;
|
|
72243
|
+
let language = null;
|
|
72244
|
+
let scriptType = null;
|
|
72245
|
+
while (byteIndex < tagEndByte) {
|
|
72246
|
+
while (byteIndex < tagEndByte && (isHtmlWhitespace(sourceBuffer[byteIndex]) || sourceBuffer[byteIndex] === TAG_SELF_CLOSE_UTF8_BYTE)) byteIndex++;
|
|
72247
|
+
const attributeNameStartByte = byteIndex;
|
|
72248
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== ATTRIBUTE_ASSIGNMENT_UTF8_BYTE && sourceBuffer[byteIndex] !== TAG_SELF_CLOSE_UTF8_BYTE) byteIndex++;
|
|
72249
|
+
const attributeName = sourceBuffer.subarray(attributeNameStartByte, byteIndex).toString("ascii").toLowerCase();
|
|
72250
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
72251
|
+
let attributeValue = "";
|
|
72252
|
+
if (sourceBuffer[byteIndex] === ATTRIBUTE_ASSIGNMENT_UTF8_BYTE) {
|
|
72253
|
+
byteIndex++;
|
|
72254
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
72255
|
+
const quoteByte = sourceBuffer[byteIndex];
|
|
72256
|
+
if (quoteByte === SINGLE_QUOTE_UTF8_BYTE || quoteByte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
72257
|
+
const valueStartByte = byteIndex + 1;
|
|
72258
|
+
byteIndex = valueStartByte;
|
|
72259
|
+
while (byteIndex < tagEndByte && sourceBuffer[byteIndex] !== quoteByte) byteIndex++;
|
|
72260
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
72261
|
+
if (byteIndex < tagEndByte) byteIndex++;
|
|
72262
|
+
} else {
|
|
72263
|
+
const valueStartByte = byteIndex;
|
|
72264
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== TAG_CLOSE_UTF8_BYTE) byteIndex++;
|
|
72265
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
72266
|
+
}
|
|
72267
|
+
}
|
|
72268
|
+
if (attributeName === "src") hasSource = true;
|
|
72269
|
+
else if (attributeName === "type" && scriptType === null) scriptType = attributeValue;
|
|
72270
|
+
else if (attributeName === "language" && language === null) language = attributeValue;
|
|
72271
|
+
}
|
|
72272
|
+
return {
|
|
72273
|
+
hasSource,
|
|
72274
|
+
language,
|
|
72275
|
+
type: scriptType
|
|
72276
|
+
};
|
|
72277
|
+
};
|
|
72278
|
+
const isExecutableScript = (attributes) => {
|
|
72279
|
+
if (attributes.hasSource) return false;
|
|
72280
|
+
const type = attributes.type?.trim().toLowerCase() ?? "";
|
|
72281
|
+
if (type !== "") {
|
|
72282
|
+
const mimeType = type.split(";")[0]?.trim() ?? "";
|
|
72283
|
+
return mimeType === "module" || JAVASCRIPT_MIME_TYPES.has(mimeType);
|
|
72284
|
+
}
|
|
72285
|
+
const language = attributes.language?.trim().toLowerCase() ?? "";
|
|
72286
|
+
return language === "" || JAVASCRIPT_MIME_TYPES.has(`text/${language}`);
|
|
72287
|
+
};
|
|
72288
|
+
const findElementClose = (sourceBuffer, startByte, tagName) => {
|
|
72289
|
+
const closeTagStart = `</${tagName}`;
|
|
72290
|
+
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;
|
|
72291
|
+
return sourceBuffer.length;
|
|
72292
|
+
};
|
|
72293
|
+
const prepareHtmlScriptSource = (sourceBuffer) => {
|
|
72294
|
+
const frontmatterEndByte = findFrontmatterEnd(sourceBuffer);
|
|
72295
|
+
let maskedBuffer = frontmatterEndByte > 0 ? Buffer.from(sourceBuffer) : null;
|
|
72296
|
+
if (maskedBuffer !== null) maskByteRange(maskedBuffer, 0, frontmatterEndByte);
|
|
72297
|
+
const executableScriptBodies = [];
|
|
72298
|
+
let byteIndex = frontmatterEndByte;
|
|
72299
|
+
let templateDepth = 0;
|
|
72300
|
+
while (byteIndex < sourceBuffer.length) {
|
|
72301
|
+
if (sourceBuffer[byteIndex] !== TAG_OPEN_UTF8_BYTE) {
|
|
72302
|
+
byteIndex++;
|
|
72303
|
+
continue;
|
|
72304
|
+
}
|
|
72305
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, COMMENT_OPEN)) {
|
|
72306
|
+
const commentEndByte = sourceBuffer.indexOf(COMMENT_CLOSE, byteIndex + 4);
|
|
72307
|
+
byteIndex = commentEndByte === -1 ? sourceBuffer.length : commentEndByte + 3;
|
|
72308
|
+
continue;
|
|
72309
|
+
}
|
|
72310
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, TEMPLATE_CLOSE) && isTagBoundary(sourceBuffer[byteIndex + TEMPLATE_CLOSE.length])) {
|
|
72311
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + TEMPLATE_CLOSE.length);
|
|
72312
|
+
if (templateDepth > 0) templateDepth--;
|
|
72313
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
72314
|
+
continue;
|
|
72315
|
+
}
|
|
72316
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, SCRIPT_OPEN) || !isTagBoundary(sourceBuffer[byteIndex + SCRIPT_OPEN.length])) {
|
|
72317
|
+
if (!isPotentialTagStart(sourceBuffer[byteIndex + 1])) {
|
|
72318
|
+
byteIndex++;
|
|
72319
|
+
continue;
|
|
72320
|
+
}
|
|
72321
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + 1);
|
|
72322
|
+
const tagName = readStartTagName(sourceBuffer, byteIndex);
|
|
72323
|
+
if (tagName === PLAINTEXT_TAG_NAME) break;
|
|
72324
|
+
if (tagName === TEMPLATE_TAG_NAME) templateDepth++;
|
|
72325
|
+
if (tagName !== null && RAW_TEXT_TAG_NAMES.has(tagName)) {
|
|
72326
|
+
const closeTagStartByte = findElementClose(sourceBuffer, tagEndByte + 1, tagName);
|
|
72327
|
+
if (closeTagStartByte === sourceBuffer.length) break;
|
|
72328
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, closeTagStartByte + tagName.length + 2);
|
|
72329
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
72330
|
+
continue;
|
|
72331
|
+
}
|
|
72332
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
72333
|
+
continue;
|
|
72334
|
+
}
|
|
72335
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + SCRIPT_OPEN.length);
|
|
72336
|
+
if (tagEndByte === sourceBuffer.length) break;
|
|
72337
|
+
const bodyStartByte = tagEndByte + 1;
|
|
72338
|
+
const bodyEndByte = findElementClose(sourceBuffer, bodyStartByte, SCRIPT_TAG_NAME);
|
|
72339
|
+
const attributes = parseScriptAttributes(sourceBuffer, byteIndex + SCRIPT_OPEN.length, tagEndByte);
|
|
72340
|
+
if (attributes.hasSource || templateDepth > 0) {
|
|
72341
|
+
maskedBuffer ??= Buffer.from(sourceBuffer);
|
|
72342
|
+
maskByteRange(maskedBuffer, bodyStartByte, bodyEndByte);
|
|
72343
|
+
} else if (isExecutableScript(attributes)) executableScriptBodies.push(sourceBuffer.subarray(bodyStartByte, bodyEndByte));
|
|
72344
|
+
if (bodyEndByte === sourceBuffer.length) break;
|
|
72345
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, bodyEndByte + SCRIPT_CLOSE.length);
|
|
72346
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
72347
|
+
}
|
|
72348
|
+
return {
|
|
72349
|
+
executableScriptBodies,
|
|
72350
|
+
lintBuffer: maskedBuffer ?? sourceBuffer
|
|
72351
|
+
};
|
|
72352
|
+
};
|
|
72353
|
+
const prepareHtmlLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
|
|
72354
|
+
const lintFiles = [];
|
|
72355
|
+
const sourcePathByLintPath = /* @__PURE__ */ new Map();
|
|
72356
|
+
const sizeByLintPath = /* @__PURE__ */ new Map();
|
|
72357
|
+
const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
|
|
72358
|
+
let htmlFileIndex = 0;
|
|
72359
|
+
let hasThreeModuleImport = false;
|
|
72360
|
+
for (const candidateFile of candidateFiles) {
|
|
72361
|
+
if (!HTML_FILE_PATTERN.test(candidateFile)) {
|
|
72362
|
+
lintFiles.push(candidateFile);
|
|
72363
|
+
continue;
|
|
72364
|
+
}
|
|
72365
|
+
const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
|
|
72366
|
+
const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
|
|
72367
|
+
const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
|
|
72368
|
+
if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
|
|
72369
|
+
const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
|
|
72370
|
+
NFS.writeFileSync(lintPath, lintBuffer);
|
|
72371
|
+
lintFiles.push(lintPath);
|
|
72372
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
72373
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
72374
|
+
hasThreeModuleImport ||= executableScriptBodies.some((scriptBody) => containsThreeModuleImport(scriptBody.toString("utf8")));
|
|
72375
|
+
htmlFileIndex++;
|
|
72376
|
+
}
|
|
72377
|
+
return {
|
|
72378
|
+
lintFiles,
|
|
72379
|
+
sourcePathByLintPath,
|
|
72380
|
+
sizeByLintPath,
|
|
72381
|
+
hasThreeModuleImport
|
|
72382
|
+
};
|
|
72383
|
+
};
|
|
71491
72384
|
/**
|
|
71492
72385
|
* Atomically (re)writes the generated oxlintrc.json. Used twice in
|
|
71493
72386
|
* the runner: once for the primary scan, once for the
|
|
@@ -71648,6 +72541,8 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
71648
72541
|
const runOxlint = async (options) => {
|
|
71649
72542
|
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;
|
|
71650
72543
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
72544
|
+
const runtimeGlobals = Array.isArray(userConfig?.runtimeGlobals) ? userConfig.runtimeGlobals.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
72545
|
+
let unpluginAutoImportGlobalScopes = [];
|
|
71651
72546
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
71652
72547
|
validateRuleRegistration();
|
|
71653
72548
|
resetManifestCaches();
|
|
@@ -71661,21 +72556,6 @@ const runOxlint = async (options) => {
|
|
|
71661
72556
|
const pluginPath = resolvePluginPath();
|
|
71662
72557
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
71663
72558
|
const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
71664
|
-
const buildConfig = (overrides) => createOxlintConfig({
|
|
71665
|
-
pluginPath,
|
|
71666
|
-
project,
|
|
71667
|
-
customRulesOnly,
|
|
71668
|
-
extendsPaths: overrides.extendsPaths,
|
|
71669
|
-
ignoredTags,
|
|
71670
|
-
includedTags,
|
|
71671
|
-
includeTagDefaults,
|
|
71672
|
-
serverAuthFunctionNames,
|
|
71673
|
-
severityControls,
|
|
71674
|
-
userPlugins,
|
|
71675
|
-
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
71676
|
-
ruleSelection: overrides.ruleSelection,
|
|
71677
|
-
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
71678
|
-
});
|
|
71679
72559
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
71680
72560
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
71681
72561
|
const configPath = Path.join(configDirectory, "oxlintrc.json");
|
|
@@ -71711,7 +72591,36 @@ const runOxlint = async (options) => {
|
|
|
71711
72591
|
await yieldToEventLoop();
|
|
71712
72592
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
71713
72593
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
72594
|
+
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
72595
|
+
rootDirectory,
|
|
72596
|
+
candidateFiles
|
|
72597
|
+
});
|
|
72598
|
+
const preparedHtmlSources = prepareHtmlLintSources(rootDirectory, configDirectory, candidateFiles);
|
|
72599
|
+
const lintFiles = preparedHtmlSources.lintFiles;
|
|
72600
|
+
const hasHtmlFiles = preparedHtmlSources.sourcePathByLintPath.size > 0;
|
|
72601
|
+
const lintProject = !project.hasThree && preparedHtmlSources.hasThreeModuleImport ? {
|
|
72602
|
+
...project,
|
|
72603
|
+
hasThree: true
|
|
72604
|
+
} : project;
|
|
72605
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
72606
|
+
pluginPath,
|
|
72607
|
+
project: lintProject,
|
|
72608
|
+
customRulesOnly,
|
|
72609
|
+
extendsPaths: overrides.extendsPaths,
|
|
72610
|
+
ignoredTags,
|
|
72611
|
+
includedTags,
|
|
72612
|
+
includeTagDefaults,
|
|
72613
|
+
runtimeGlobals,
|
|
72614
|
+
unpluginAutoImportGlobalScopes,
|
|
72615
|
+
serverAuthFunctionNames,
|
|
72616
|
+
severityControls,
|
|
72617
|
+
userPlugins,
|
|
72618
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
72619
|
+
ruleSelection: overrides.ruleSelection,
|
|
72620
|
+
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
72621
|
+
});
|
|
71714
72622
|
const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
|
|
72623
|
+
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedHtmlSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
|
|
71715
72624
|
const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
|
|
71716
72625
|
baseArgs: passBaseArgs,
|
|
71717
72626
|
files: passFiles,
|
|
@@ -71740,7 +72649,8 @@ const runOxlint = async (options) => {
|
|
|
71740
72649
|
fileBatches: passFileBatches,
|
|
71741
72650
|
rootDirectory,
|
|
71742
72651
|
nodeBinaryPath,
|
|
71743
|
-
project,
|
|
72652
|
+
project: lintProject,
|
|
72653
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
71744
72654
|
onPartialFailure: reportPartialFailure,
|
|
71745
72655
|
onAnalyzedFiles: (filePaths) => {
|
|
71746
72656
|
analyzedFiles = filePaths;
|
|
@@ -71775,7 +72685,7 @@ const runOxlint = async (options) => {
|
|
|
71775
72685
|
};
|
|
71776
72686
|
}
|
|
71777
72687
|
};
|
|
71778
|
-
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0) {
|
|
72688
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasHtmlFiles) {
|
|
71779
72689
|
const rulesetHash = computeRulesetHash({
|
|
71780
72690
|
config: buildConfig({
|
|
71781
72691
|
extendsPaths: [],
|
|
@@ -71933,14 +72843,15 @@ const runOxlint = async (options) => {
|
|
|
71933
72843
|
]);
|
|
71934
72844
|
}
|
|
71935
72845
|
const baseArgs = makeBaseArgs(configPath);
|
|
71936
|
-
const fileBatches = buildFileBatches(baseArgs,
|
|
72846
|
+
const fileBatches = buildFileBatches(baseArgs, lintFiles);
|
|
71937
72847
|
let analyzedFiles = [];
|
|
71938
72848
|
const runBatches = () => spawnLintBatches({
|
|
71939
72849
|
baseArgs,
|
|
71940
72850
|
fileBatches,
|
|
71941
72851
|
rootDirectory,
|
|
71942
72852
|
nodeBinaryPath,
|
|
71943
|
-
project,
|
|
72853
|
+
project: lintProject,
|
|
72854
|
+
sourcePathByLintPath: preparedHtmlSources.sourcePathByLintPath,
|
|
71944
72855
|
onPartialFailure,
|
|
71945
72856
|
onAnalyzedFiles: (filePaths) => {
|
|
71946
72857
|
analyzedFiles = filePaths;
|
|
@@ -73474,7 +74385,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
73474
74385
|
/** Display name used in client-facing messages and progress titles. */
|
|
73475
74386
|
const SERVER_DISPLAY_NAME = "React Doctor";
|
|
73476
74387
|
/** Server version reported in `serverInfo`; injected at build, `dev` from source. */
|
|
73477
|
-
const SERVER_VERSION = "0.9.
|
|
74388
|
+
const SERVER_VERSION = "0.9.1";
|
|
73478
74389
|
/** `Diagnostic.source` shown next to every published diagnostic. */
|
|
73479
74390
|
const DIAGNOSTIC_SOURCE = "react-doctor";
|
|
73480
74391
|
/**
|
|
@@ -73516,7 +74427,8 @@ const SCANNABLE_EXTENSIONS = [
|
|
|
73516
74427
|
".js",
|
|
73517
74428
|
".jsx",
|
|
73518
74429
|
".mts",
|
|
73519
|
-
".mjs"
|
|
74430
|
+
".mjs",
|
|
74431
|
+
".html"
|
|
73520
74432
|
];
|
|
73521
74433
|
const SILENT_LOGGER = {
|
|
73522
74434
|
info: () => {},
|
|
@@ -75504,5 +76416,5 @@ const startLanguageServer = () => {
|
|
|
75504
76416
|
};
|
|
75505
76417
|
//#endregion
|
|
75506
76418
|
export { startLanguageServer };
|
|
75507
|
-
!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]="
|
|
75508
|
-
//# debugId=
|
|
76419
|
+
!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]="6a2a246a-da30-59c5-aa97-af8188206b96")}catch(e){}}();
|
|
76420
|
+
//# debugId=6a2a246a-da30-59c5-aa97-af8188206b96
|