react-doctor 0.7.1-dev.5809083 → 0.7.1-dev.7cf4d0b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +505 -49
- package/dist/index.d.ts +7 -0
- package/dist/index.js +498 -44
- package/dist/lsp.js +498 -44
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7b7c23b7-250e-5339-af06-e3e3b5eb5f98")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -9,7 +9,7 @@ import * as NFS from "node:fs";
|
|
|
9
9
|
import fs, { mkdtempSync, rmSync } from "node:fs";
|
|
10
10
|
import process$1 from "node:process";
|
|
11
11
|
import * as ts from "typescript";
|
|
12
|
-
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
12
|
+
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
13
13
|
import * as OS from "node:os";
|
|
14
14
|
import os, { tmpdir } from "node:os";
|
|
15
15
|
import { parseJSON5 } from "confbox";
|
|
@@ -35968,8 +35968,10 @@ const isFile = (filePath) => {
|
|
|
35968
35968
|
};
|
|
35969
35969
|
const SOURCE_FILE_PATTERN = /\.(tsx?|jsx?|mts|mjs)$/;
|
|
35970
35970
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
35971
|
+
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
35971
35972
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
35972
35973
|
const GIT_LS_FILES_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
35974
|
+
const SCANNED_DOT_DIRECTORIES = new Set([".dumi", ".storybook"]);
|
|
35973
35975
|
const IGNORED_DIRECTORIES = new Set([
|
|
35974
35976
|
".angular",
|
|
35975
35977
|
".astro",
|
|
@@ -36154,8 +36156,9 @@ const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
|
36154
36156
|
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
36155
36157
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
36156
36158
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
36157
|
-
const
|
|
36158
|
-
const
|
|
36159
|
+
const isIgnoredDirectoryName = (directoryName) => IGNORED_DIRECTORIES.has(directoryName) || directoryName.startsWith(".") && !SCANNED_DOT_DIRECTORIES.has(directoryName);
|
|
36160
|
+
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => isIgnoredDirectoryName(segment));
|
|
36161
|
+
const isLintableSourceFile = (filePath) => SOURCE_FILE_PATTERN.test(filePath) && !GENERATED_BUNDLE_FILE_PATTERN.test(filePath) && !GENERATED_SOURCE_DIRECTORY_PATTERN.test(filePath);
|
|
36159
36162
|
const isMinifiedSource = (absolutePath) => {
|
|
36160
36163
|
let fileDescriptor;
|
|
36161
36164
|
try {
|
|
@@ -36216,7 +36219,7 @@ function* walkSourceTreeFiles(rootDirectory) {
|
|
|
36216
36219
|
for (const entry of readDirectoryEntries(currentDirectory)) {
|
|
36217
36220
|
const absolutePath = Path.join(currentDirectory, entry.name);
|
|
36218
36221
|
if (entry.isDirectory()) {
|
|
36219
|
-
if (!
|
|
36222
|
+
if (!isIgnoredDirectoryName(entry.name)) stack.push(absolutePath);
|
|
36220
36223
|
continue;
|
|
36221
36224
|
}
|
|
36222
36225
|
if (entry.isFile()) yield {
|
|
@@ -36262,6 +36265,23 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
36262
36265
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
36263
36266
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
36264
36267
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
36268
|
+
/**
|
|
36269
|
+
* The chain of ancestor directories of `startDirectory`, nearest first, up to
|
|
36270
|
+
* and including the filesystem root. With `includeStart`, the chain begins at
|
|
36271
|
+
* `startDirectory` itself; otherwise at its parent. The one place the "walk up
|
|
36272
|
+
* the tree" traversal is expressed, so each caller adds only its own match /
|
|
36273
|
+
* stop policy instead of re-deriving the `path.dirname` loop.
|
|
36274
|
+
*/
|
|
36275
|
+
const ancestorDirectories = (startDirectory, { includeStart }) => {
|
|
36276
|
+
const directories = [];
|
|
36277
|
+
let currentDirectory = includeStart ? startDirectory : Path.dirname(startDirectory);
|
|
36278
|
+
while (true) {
|
|
36279
|
+
directories.push(currentDirectory);
|
|
36280
|
+
const parentDirectory = Path.dirname(currentDirectory);
|
|
36281
|
+
if (parentDirectory === currentDirectory) return directories;
|
|
36282
|
+
currentDirectory = parentDirectory;
|
|
36283
|
+
}
|
|
36284
|
+
};
|
|
36265
36285
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
36266
36286
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
36267
36287
|
try {
|
|
@@ -36292,11 +36312,7 @@ const isMonorepoRoot = (directory) => {
|
|
|
36292
36312
|
return Array.isArray(packageJson.workspaces) || Boolean(packageJson.workspaces?.packages);
|
|
36293
36313
|
};
|
|
36294
36314
|
const findMonorepoRoot = (startDirectory) => {
|
|
36295
|
-
|
|
36296
|
-
while (currentDirectory !== Path.dirname(currentDirectory)) {
|
|
36297
|
-
if (isMonorepoRoot(currentDirectory)) return currentDirectory;
|
|
36298
|
-
currentDirectory = Path.dirname(currentDirectory);
|
|
36299
|
-
}
|
|
36315
|
+
for (const directory of ancestorDirectories(startDirectory, { includeStart: false })) if (isMonorepoRoot(directory)) return directory;
|
|
36300
36316
|
return null;
|
|
36301
36317
|
};
|
|
36302
36318
|
/**
|
|
@@ -36942,6 +36958,74 @@ const findDependencyInfoFromMonorepoRoot = (directory) => {
|
|
|
36942
36958
|
framework: rootInfo.framework !== "unknown" ? rootInfo.framework : workspaceInfo.framework
|
|
36943
36959
|
};
|
|
36944
36960
|
};
|
|
36961
|
+
/**
|
|
36962
|
+
* Walk up from `startDirectory` to the nearest ancestor that owns a
|
|
36963
|
+
* `package.json`, stopping at (and including) the enclosing project boundary
|
|
36964
|
+
* — the working tree's git root or a monorepo root. Lets a scan of a package
|
|
36965
|
+
* subfolder that has no `package.json` of its own adopt the nearest enclosing
|
|
36966
|
+
* package as its project root, so it inherits that package's dependency +
|
|
36967
|
+
* framework detection instead of synthesizing an empty (React-blind) project.
|
|
36968
|
+
*
|
|
36969
|
+
* Generalizes the older monorepo-root-only lookup: the nearest ancestor is the
|
|
36970
|
+
* most specific owning package (a leaf workspace, not just the repo root), so
|
|
36971
|
+
* a subfolder of one workspace no longer borrows a sibling's capabilities.
|
|
36972
|
+
*
|
|
36973
|
+
* Returns `null` when no ancestor `package.json` exists inside the project
|
|
36974
|
+
* boundary (a loose tree of files, or a subfolder of a package-less repo).
|
|
36975
|
+
*/
|
|
36976
|
+
const findNearestAncestorPackageJson = (startDirectory) => {
|
|
36977
|
+
if (isProjectBoundary(startDirectory)) return null;
|
|
36978
|
+
for (const directory of ancestorDirectories(startDirectory, { includeStart: false })) {
|
|
36979
|
+
if (isFile(Path.join(directory, "package.json"))) return directory;
|
|
36980
|
+
if (isProjectBoundary(directory)) return null;
|
|
36981
|
+
}
|
|
36982
|
+
return null;
|
|
36983
|
+
};
|
|
36984
|
+
/**
|
|
36985
|
+
* Last-resort React detection: locate React the way Node's `node_modules`
|
|
36986
|
+
* resolution would from `directory` — check each `node_modules/react` up the
|
|
36987
|
+
* tree — but bounded to the enclosing repo so a globally installed React can't
|
|
36988
|
+
* masquerade as the project's version. Stops at (and including) the nearest
|
|
36989
|
+
* project boundary — the git root or a monorepo root — and returns the first
|
|
36990
|
+
* installed `version`.
|
|
36991
|
+
*
|
|
36992
|
+
* Makes "React is installed and importable" ⇒ "React is detected" an invariant
|
|
36993
|
+
* for packages whose only React declaration is a version-less spec
|
|
36994
|
+
* (`workspace:*`, `*`, a dist-tag) or where React lives solely in a hoisted
|
|
36995
|
+
* `node_modules` the declaration walks never reach — the profile of a component
|
|
36996
|
+
* package inside a monorepo. Matching the `node_modules/react` entry rather than
|
|
36997
|
+
* its realpath means a project whose `node_modules` is symlinked elsewhere (a
|
|
36998
|
+
* Docker volume, a shared store) still counts, while a global install outside
|
|
36999
|
+
* the repo does not.
|
|
37000
|
+
*
|
|
37001
|
+
* Returns `null` when React isn't installed within the repo or its package.json
|
|
37002
|
+
* carries no version string. A tree with no boundary marker at all bounds the
|
|
37003
|
+
* search to `directory`, so a dependency hoisted above the scanned package there
|
|
37004
|
+
* is conservatively not adopted.
|
|
37005
|
+
*/
|
|
37006
|
+
/**
|
|
37007
|
+
* The nearest enclosing project boundary (git root or monorepo root), or
|
|
37008
|
+
* `directory` itself when the scan target sits outside any repo. Bounds the
|
|
37009
|
+
* node_modules walk so a React hoisted anywhere inside the repo counts, but a
|
|
37010
|
+
* React in an ancestor above the repo — a home-directory or global
|
|
37011
|
+
* `node_modules` — can't leak in.
|
|
37012
|
+
*/
|
|
37013
|
+
const findContainmentRoot = (directory) => {
|
|
37014
|
+
for (const ancestorDirectory of ancestorDirectories(directory, { includeStart: true })) if (isProjectBoundary(ancestorDirectory)) return ancestorDirectory;
|
|
37015
|
+
return directory;
|
|
37016
|
+
};
|
|
37017
|
+
const resolveInstalledReactVersion = (directory) => {
|
|
37018
|
+
const containmentRoot = findContainmentRoot(directory);
|
|
37019
|
+
for (const ancestorDirectory of ancestorDirectories(directory, { includeStart: true })) {
|
|
37020
|
+
const reactPackageJsonPath = Path.join(ancestorDirectory, "node_modules", "react", "package.json");
|
|
37021
|
+
if (isFile(reactPackageJsonPath)) {
|
|
37022
|
+
const installedVersion = readPackageJson$1(reactPackageJsonPath).version;
|
|
37023
|
+
return typeof installedVersion === "string" ? installedVersion : null;
|
|
37024
|
+
}
|
|
37025
|
+
if (ancestorDirectory === containmentRoot) return null;
|
|
37026
|
+
}
|
|
37027
|
+
return null;
|
|
37028
|
+
};
|
|
36945
37029
|
const findInWorkspacePackageJsons = (rootDirectory, rootPackageJson, select) => {
|
|
36946
37030
|
const rootValue = select(rootPackageJson);
|
|
36947
37031
|
if (rootValue !== null) return rootValue;
|
|
@@ -37098,6 +37182,10 @@ const normalizeCompilerOptions = (compilerOptions) => {
|
|
|
37098
37182
|
hasExplicitLib
|
|
37099
37183
|
};
|
|
37100
37184
|
};
|
|
37185
|
+
const normalizeReferencePaths = (references) => {
|
|
37186
|
+
if (!Array.isArray(references)) return [];
|
|
37187
|
+
return references.map((reference) => isPlainObject(reference) && typeof reference.path === "string" ? reference.path : null).filter((referencePath) => referencePath !== null);
|
|
37188
|
+
};
|
|
37101
37189
|
const readTsConfig = (filePath) => {
|
|
37102
37190
|
let content;
|
|
37103
37191
|
try {
|
|
@@ -37109,6 +37197,7 @@ const readTsConfig = (filePath) => {
|
|
|
37109
37197
|
if (!isPlainObject(parsed.config)) return null;
|
|
37110
37198
|
return {
|
|
37111
37199
|
extends: typeof parsed.config.extends === "string" ? parsed.config.extends : void 0,
|
|
37200
|
+
referencePaths: normalizeReferencePaths(parsed.config.references),
|
|
37112
37201
|
compilerOptions: normalizeCompilerOptions(parsed.config.compilerOptions)
|
|
37113
37202
|
};
|
|
37114
37203
|
};
|
|
@@ -37149,20 +37238,37 @@ const libEntryIncludesES2023Array = (entry) => {
|
|
|
37149
37238
|
};
|
|
37150
37239
|
const libIncludesES2023 = (lib) => lib.some(libEntryIncludesES2023Array);
|
|
37151
37240
|
const compilerOptionsArePreES2023 = (compilerOptions) => {
|
|
37241
|
+
if (compilerOptions.target && targetYearIsPreES2023(compilerOptions.target)) return true;
|
|
37152
37242
|
if (compilerOptions.hasExplicitLib) return !libIncludesES2023(compilerOptions.lib ?? []);
|
|
37153
|
-
if (compilerOptions.target) return targetYearIsPreES2023(compilerOptions.target);
|
|
37154
37243
|
return false;
|
|
37155
37244
|
};
|
|
37156
37245
|
const compilerOptionsDeclareTargetOrLib = (compilerOptions) => compilerOptions.hasExplicitLib || compilerOptions.target !== void 0;
|
|
37157
|
-
const detectPreES2023FromConfig = (tsConfigPath) => {
|
|
37246
|
+
const detectPreES2023FromConfig = (tsConfigPath, visitedConfigPaths = /* @__PURE__ */ new Set()) => {
|
|
37247
|
+
if (visitedConfigPaths.has(tsConfigPath)) return false;
|
|
37158
37248
|
const compilerOptions = readResolvedCompilerOptions(tsConfigPath, 0, /* @__PURE__ */ new Set());
|
|
37159
37249
|
if (!compilerOptions) return false;
|
|
37160
|
-
if (!compilerOptionsDeclareTargetOrLib(compilerOptions))
|
|
37250
|
+
if (!compilerOptionsDeclareTargetOrLib(compilerOptions)) {
|
|
37251
|
+
const tsConfig = readTsConfig(tsConfigPath);
|
|
37252
|
+
if (!tsConfig) return false;
|
|
37253
|
+
const nextVisitedConfigPaths = new Set(visitedConfigPaths);
|
|
37254
|
+
nextVisitedConfigPaths.add(tsConfigPath);
|
|
37255
|
+
const configDirectory = Path.dirname(tsConfigPath);
|
|
37256
|
+
return tsConfig.referencePaths.some((referencePath) => {
|
|
37257
|
+
const resolvedReferencePath = Path.resolve(configDirectory, referencePath);
|
|
37258
|
+
const referencedConfigPath = isFile(resolvedReferencePath) ? resolvedReferencePath : Path.join(resolvedReferencePath, TSCONFIG_FILENAME);
|
|
37259
|
+
return isFile(referencedConfigPath) && detectPreES2023FromConfig(referencedConfigPath, nextVisitedConfigPaths);
|
|
37260
|
+
});
|
|
37261
|
+
}
|
|
37161
37262
|
return compilerOptionsArePreES2023(compilerOptions);
|
|
37162
37263
|
};
|
|
37264
|
+
const FALLBACK_TSCONFIG_FILENAMES = ["tsconfig.app.json", "tsconfig.build.json"];
|
|
37163
37265
|
const detectPreES2023Target = (directory) => {
|
|
37164
37266
|
const tsConfigPath = Path.join(directory, TSCONFIG_FILENAME);
|
|
37165
37267
|
if (isFile(tsConfigPath)) return detectPreES2023FromConfig(tsConfigPath);
|
|
37268
|
+
for (const fallbackFilename of FALLBACK_TSCONFIG_FILENAMES) {
|
|
37269
|
+
const fallbackPath = Path.join(directory, fallbackFilename);
|
|
37270
|
+
if (isFile(fallbackPath)) return detectPreES2023FromConfig(fallbackPath);
|
|
37271
|
+
}
|
|
37166
37272
|
return false;
|
|
37167
37273
|
};
|
|
37168
37274
|
const REACT_DEPENDENCY_NAMES = new Set([
|
|
@@ -37278,19 +37384,20 @@ const discoverReactSubprojects = (rootDirectory) => {
|
|
|
37278
37384
|
const cachedProjectInfos = /* @__PURE__ */ new Map();
|
|
37279
37385
|
/**
|
|
37280
37386
|
* Build a `ProjectInfo` for a directory that has no `package.json` of
|
|
37281
|
-
* its own — a
|
|
37282
|
-
* of TypeScript/JavaScript files. Dependency + framework
|
|
37283
|
-
* inherited from the enclosing
|
|
37284
|
-
*
|
|
37285
|
-
*
|
|
37286
|
-
*
|
|
37287
|
-
*
|
|
37387
|
+
* its own — a package subfolder like `repo/packages` or `app/src/features`,
|
|
37388
|
+
* or any loose tree of TypeScript/JavaScript files. Dependency + framework
|
|
37389
|
+
* detection is inherited from the nearest enclosing package (a leaf
|
|
37390
|
+
* workspace, a plain app root, or a monorepo root — whichever is closest,
|
|
37391
|
+
* bounded by the git root), so scanning a subdirectory of a React project
|
|
37392
|
+
* still gets the React capabilities; a standalone non-React directory simply
|
|
37393
|
+
* scans with the framework-agnostic rules. Throws only when the directory has
|
|
37394
|
+
* nothing to scan (no enclosing project and no source files of its own).
|
|
37288
37395
|
*/
|
|
37289
37396
|
const discoverProjectWithoutPackageJson = (directory) => {
|
|
37290
37397
|
const sourceFileCount = countSourceFiles(directory);
|
|
37291
37398
|
const hasOwnTsConfig = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
37292
|
-
const
|
|
37293
|
-
const enclosingProject =
|
|
37399
|
+
const enclosingProjectRoot = findNearestAncestorPackageJson(directory);
|
|
37400
|
+
const enclosingProject = enclosingProjectRoot !== null ? discoverProject(enclosingProjectRoot) : null;
|
|
37294
37401
|
if (enclosingProject !== null) return {
|
|
37295
37402
|
...enclosingProject,
|
|
37296
37403
|
rootDirectory: directory,
|
|
@@ -37320,6 +37427,7 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
37320
37427
|
shopifyFlashListVersion: null,
|
|
37321
37428
|
shopifyFlashListMajorVersion: null,
|
|
37322
37429
|
hasReanimated: false,
|
|
37430
|
+
reanimatedVersion: null,
|
|
37323
37431
|
isPreES2023Target: hasOwnTsConfig && detectPreES2023Target(directory),
|
|
37324
37432
|
sourceFileCount
|
|
37325
37433
|
};
|
|
@@ -37394,6 +37502,7 @@ const discoverProject = (directory) => {
|
|
|
37394
37502
|
if (!reactVersion && reactDeclaration.version && !isCatalogReference(reactDeclaration.version)) reactVersion = reactDeclaration.version;
|
|
37395
37503
|
if (!tailwindVersion && tailwindDeclaration.version && !isCatalogReference(tailwindDeclaration.version)) tailwindVersion = tailwindDeclaration.version;
|
|
37396
37504
|
if (!zodVersion && zodDeclaration.version && !isCatalogReference(zodDeclaration.version)) zodVersion = zodDeclaration.version;
|
|
37505
|
+
if (!reactVersion || parseReactMajor(reactVersion) === null) reactVersion = resolveInstalledReactVersion(directory) ?? reactVersion;
|
|
37397
37506
|
const projectName = packageJson.name ?? Path.basename(directory);
|
|
37398
37507
|
const hasTypeScript = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
37399
37508
|
const sourceFileCount = countSourceFiles(directory);
|
|
@@ -37411,6 +37520,7 @@ const discoverProject = (directory) => {
|
|
|
37411
37520
|
version: findShopifyFlashListVersion(directory, packageJson)
|
|
37412
37521
|
}) : null;
|
|
37413
37522
|
const hasReanimated = hasReactNativeWorkspace && someWorkspacePackageJson(directory, packageJson, isPackageJsonReanimatedAware);
|
|
37523
|
+
const reanimatedVersion = hasReanimated ? findInWorkspacePackageJsons(directory, packageJson, (workspacePackageJson) => getDependencySpec(workspacePackageJson, REANIMATED_DEPENDENCY_NAME)) : null;
|
|
37414
37524
|
const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
|
|
37415
37525
|
rootDirectory: directory,
|
|
37416
37526
|
rootPackageJson: packageJson,
|
|
@@ -37440,6 +37550,7 @@ const discoverProject = (directory) => {
|
|
|
37440
37550
|
shopifyFlashListVersion,
|
|
37441
37551
|
shopifyFlashListMajorVersion: shopifyFlashListVersion === null ? null : getLowestDependencyMajor(shopifyFlashListVersion),
|
|
37442
37552
|
hasReanimated,
|
|
37553
|
+
reanimatedVersion,
|
|
37443
37554
|
isPreES2023Target,
|
|
37444
37555
|
sourceFileCount
|
|
37445
37556
|
};
|
|
@@ -37632,6 +37743,9 @@ const buildRuleSeverityControls = (config) => {
|
|
|
37632
37743
|
...config.buckets !== void 0 ? { buckets: config.buckets } : {}
|
|
37633
37744
|
};
|
|
37634
37745
|
};
|
|
37746
|
+
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
37747
|
+
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
37748
|
+
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
37635
37749
|
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
37636
37750
|
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
37637
37751
|
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
@@ -37709,6 +37823,7 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
|
37709
37823
|
"react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
37710
37824
|
"react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
37711
37825
|
"react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
|
|
37826
|
+
"react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
|
|
37712
37827
|
"react/jsx-no-undef": "react-doctor/jsx-no-undef",
|
|
37713
37828
|
"react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
|
|
37714
37829
|
"react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
|
|
@@ -37793,9 +37908,6 @@ const tokenizeRuleList = (ruleList) => {
|
|
|
37793
37908
|
if (!ruleSection) return [];
|
|
37794
37909
|
return ruleSection.split(/[,\s]+/).map((token) => token.trim()).filter(Boolean);
|
|
37795
37910
|
};
|
|
37796
|
-
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
37797
|
-
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
37798
|
-
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
37799
37911
|
const buildHint = (tool, token, ruleId) => `oxlint matches plugin rules only by their full name, so \`${token}\` in your ${tool}-disable comment does not silence \`${ruleId}\` — add \`${ruleId}\` to the comment (e.g. \`${token}, ${ruleId}\`).`;
|
|
37800
37912
|
const tokenMisnamesRule = (token, ruleId) => token !== ruleId && isSameRuleKey(token, ruleId);
|
|
37801
37913
|
const detectInlineNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
@@ -37849,6 +37961,53 @@ const detectForeignDisableNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
37849
37961
|
if (!ruleId.startsWith("react-doctor/")) return null;
|
|
37850
37962
|
return detectInlineNearMiss(lines, diagnosticLineIndex, ruleId) ?? detectBlockNearMiss(lines, diagnosticLineIndex, ruleId);
|
|
37851
37963
|
};
|
|
37964
|
+
const ESLINT_REACT_HOOKS_PLUGIN_PREFIX = "react-hooks/";
|
|
37965
|
+
const buildAcceptedTokens = (ruleId) => {
|
|
37966
|
+
const shortRuleId = ruleId.slice(15);
|
|
37967
|
+
return new Set([ruleId, `${ESLINT_REACT_HOOKS_PLUGIN_PREFIX}${shortRuleId}`]);
|
|
37968
|
+
};
|
|
37969
|
+
const listNamesRule = (ruleList, acceptedTokens) => tokenizeRuleList(ruleList).some((token) => acceptedTokens.has(token));
|
|
37970
|
+
const isInlineDisabled = (lines, diagnosticLineIndex, acceptedTokens) => {
|
|
37971
|
+
const candidates = [{
|
|
37972
|
+
line: lines[diagnosticLineIndex],
|
|
37973
|
+
requiredScope: "line"
|
|
37974
|
+
}, {
|
|
37975
|
+
line: lines[diagnosticLineIndex - 1],
|
|
37976
|
+
requiredScope: "next-line"
|
|
37977
|
+
}];
|
|
37978
|
+
for (const { line, requiredScope } of candidates) {
|
|
37979
|
+
const match = line?.match(FOREIGN_INLINE_DISABLE_PATTERN);
|
|
37980
|
+
if (!match) continue;
|
|
37981
|
+
const [, , scope, ruleList] = match;
|
|
37982
|
+
if (scope !== requiredScope) continue;
|
|
37983
|
+
if (listNamesRule(ruleList, acceptedTokens)) return true;
|
|
37984
|
+
}
|
|
37985
|
+
return false;
|
|
37986
|
+
};
|
|
37987
|
+
const isBlockDisabled = (lines, diagnosticLineIndex, acceptedTokens) => {
|
|
37988
|
+
let isRangeOpen = false;
|
|
37989
|
+
const lastLineIndex = Math.min(diagnosticLineIndex, lines.length - 1);
|
|
37990
|
+
for (let lineIndex = 0; lineIndex <= lastLineIndex; lineIndex++) {
|
|
37991
|
+
const line = lines[lineIndex];
|
|
37992
|
+
if (line === void 0 || !line.includes("-disable") && !line.includes("-enable")) continue;
|
|
37993
|
+
const disableMatch = line.match(FOREIGN_BLOCK_DISABLE_PATTERN);
|
|
37994
|
+
if (disableMatch && listNamesRule(disableMatch[2], acceptedTokens)) {
|
|
37995
|
+
isRangeOpen = true;
|
|
37996
|
+
continue;
|
|
37997
|
+
}
|
|
37998
|
+
const enableMatch = line.match(FOREIGN_BLOCK_ENABLE_PATTERN);
|
|
37999
|
+
if (enableMatch) {
|
|
38000
|
+
const enabledRules = tokenizeRuleList(enableMatch[1]);
|
|
38001
|
+
if (enabledRules.length === 0 || enabledRules.some((rule) => acceptedTokens.has(rule))) isRangeOpen = false;
|
|
38002
|
+
}
|
|
38003
|
+
}
|
|
38004
|
+
return isRangeOpen;
|
|
38005
|
+
};
|
|
38006
|
+
const isCompilerRuleForeignDisabled = (lines, diagnosticLineIndex, ruleId) => {
|
|
38007
|
+
if (!ruleId.startsWith("react-hooks-js/")) return false;
|
|
38008
|
+
const acceptedTokens = buildAcceptedTokens(ruleId);
|
|
38009
|
+
return isInlineDisabled(lines, diagnosticLineIndex, acceptedTokens) || isBlockDisabled(lines, diagnosticLineIndex, acceptedTokens);
|
|
38010
|
+
};
|
|
37852
38011
|
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
37853
38012
|
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
37854
38013
|
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
@@ -37992,6 +38151,11 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
37992
38151
|
isSuppressed: true,
|
|
37993
38152
|
nearMissHint: null
|
|
37994
38153
|
};
|
|
38154
|
+
if (isCompilerRuleForeignDisabled(lines, diagnosticLineIndex, ruleId)) return {
|
|
38155
|
+
isSuppressed: true,
|
|
38156
|
+
nearMissHint: null,
|
|
38157
|
+
isForeignDirective: true
|
|
38158
|
+
};
|
|
37995
38159
|
const directComments = findStackedDisableCommentsAbove(lines, diagnosticLineIndex);
|
|
37996
38160
|
if (hasChainSuppressor(directComments, ruleId)) return {
|
|
37997
38161
|
isSuppressed: true,
|
|
@@ -38273,12 +38437,18 @@ const collectStringSet = (values) => {
|
|
|
38273
38437
|
return new Set(values.filter((value) => typeof value === "string"));
|
|
38274
38438
|
};
|
|
38275
38439
|
const JSX_NO_UNDEF_IDENTIFIER_PATTERN = /^`([^`]+)`/;
|
|
38440
|
+
const NODE_CLI_PATH_SEGMENTS = new Set([
|
|
38441
|
+
"scripts",
|
|
38442
|
+
"bin",
|
|
38443
|
+
"tools"
|
|
38444
|
+
]);
|
|
38445
|
+
const hasNodeCliPathSegment = (filePath) => filePath.split(/[\\/]/).slice(0, -1).some((segment) => NODE_CLI_PATH_SEGMENTS.has(segment));
|
|
38276
38446
|
/**
|
|
38277
38447
|
* Pre-compiles every stateful filter and returns a single
|
|
38278
38448
|
* `apply(diagnostic)` closure that runs (in order):
|
|
38279
38449
|
*
|
|
38280
38450
|
* 1. auto-suppress (test-noise rules in test files; `migration-hint`
|
|
38281
|
-
* wins over `test-noise`)
|
|
38451
|
+
* wins over `test-noise`; `no-console` on Node CLI scripts)
|
|
38282
38452
|
* 2. severity overrides (top-level `rules` / `categories`, with
|
|
38283
38453
|
* `"off"` dropping)
|
|
38284
38454
|
* 3. warning suppression (only when `showWarnings` is false: drops every
|
|
@@ -38376,6 +38546,12 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
38376
38546
|
if (hasRawTextWrappers && isInsideStringOnlyWrapper(lines, diagnostic.line, diagnostic.column, rawTextWrapperComponentNames)) return true;
|
|
38377
38547
|
return false;
|
|
38378
38548
|
};
|
|
38549
|
+
const isNoConsoleOnNodeCliScript = (diagnostic) => {
|
|
38550
|
+
if (diagnostic.rule !== "no-console") return false;
|
|
38551
|
+
if (hasNodeCliPathSegment(diagnostic.filePath)) return true;
|
|
38552
|
+
const lines = getFileLines(diagnostic.filePath);
|
|
38553
|
+
return lines !== null && Boolean(lines[0]?.startsWith("#!"));
|
|
38554
|
+
};
|
|
38379
38555
|
const isJsxNoUndefSuppressedByConfig = (diagnostic) => {
|
|
38380
38556
|
if (!hasRuntimeGlobals) return false;
|
|
38381
38557
|
if (diagnostic.rule !== "jsx-no-undef") return false;
|
|
@@ -38385,6 +38561,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
38385
38561
|
return {
|
|
38386
38562
|
apply: (diagnostic) => {
|
|
38387
38563
|
if (shouldAutoSuppress(diagnostic)) return null;
|
|
38564
|
+
if (isNoConsoleOnNodeCliScript(diagnostic)) return null;
|
|
38388
38565
|
let current = diagnostic;
|
|
38389
38566
|
let explicitSeverityOverride;
|
|
38390
38567
|
let explicitRuleOverride;
|
|
@@ -38414,7 +38591,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
38414
38591
|
if (lines) {
|
|
38415
38592
|
const ruleIdentifier = `${current.plugin}/${current.rule}`;
|
|
38416
38593
|
const evaluation = evaluateSuppression(lines, current.line - 1, ruleIdentifier);
|
|
38417
|
-
if (evaluation.isSuppressed) return suppress(current, "inline");
|
|
38594
|
+
if (evaluation.isSuppressed) return suppress(current, evaluation.isForeignDirective ? "foreign-inline" : "inline");
|
|
38418
38595
|
if (evaluation.nearMissHint) current = {
|
|
38419
38596
|
...current,
|
|
38420
38597
|
suppressionHint: evaluation.nearMissHint
|
|
@@ -42590,9 +42767,17 @@ const buildNoSecretsRecommendation = (project, fallbackRecommendation) => {
|
|
|
42590
42767
|
return `Move secrets to server-only code. In ${formatFrameworkName(project.framework)}, only \`${publicEnvPrefix}\` env vars are exposed to the browser, and they must not contain secrets`;
|
|
42591
42768
|
};
|
|
42592
42769
|
const REANIMATED_SHARED_VALUE_HINT = "If this is a Reanimated shared value, prefer its React Compiler-compatible `.get()` / `.set()` accessors over `.value` — https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support";
|
|
42770
|
+
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
42771
|
+
const supportsAccessors = (reanimatedVersion) => {
|
|
42772
|
+
if (reanimatedVersion === null) return true;
|
|
42773
|
+
const lowerBound = import_semver.validRange(reanimatedVersion) !== null ? import_semver.minVersion(reanimatedVersion) : import_semver.coerce(reanimatedVersion);
|
|
42774
|
+
if (lowerBound === null) return true;
|
|
42775
|
+
return import_semver.gte(lowerBound, ACCESSORS_MIN_VERSION);
|
|
42776
|
+
};
|
|
42593
42777
|
const appendReanimatedSharedValueHint = (help, rule, project) => {
|
|
42594
42778
|
if (rule !== "immutability") return help;
|
|
42595
42779
|
if (!project.hasReanimated) return help;
|
|
42780
|
+
if (!supportsAccessors(project.reanimatedVersion)) return help;
|
|
42596
42781
|
if (!help) return REANIMATED_SHARED_VALUE_HINT;
|
|
42597
42782
|
return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
|
|
42598
42783
|
};
|
|
@@ -42754,13 +42939,13 @@ const REACT_USE_BINDING_RESOLUTION = {
|
|
|
42754
42939
|
isReactUseBinding: true,
|
|
42755
42940
|
isReactNamespaceBinding: false
|
|
42756
42941
|
};
|
|
42757
|
-
const getScriptKind = (filename) => {
|
|
42942
|
+
const getScriptKind$2 = (filename) => {
|
|
42758
42943
|
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
42759
42944
|
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
42760
42945
|
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
42761
42946
|
return ts.ScriptKind.JS;
|
|
42762
42947
|
};
|
|
42763
|
-
const getUtf16Offset = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
42948
|
+
const getUtf16Offset$1 = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
42764
42949
|
const unwrapExpression = (expression) => {
|
|
42765
42950
|
let currentExpression = expression;
|
|
42766
42951
|
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
@@ -43009,8 +43194,8 @@ const findUseCallIdentifier = (sourceFile, useOffset) => {
|
|
|
43009
43194
|
return matchedIdentifier;
|
|
43010
43195
|
};
|
|
43011
43196
|
const resolveUseCallBinding = (sourceText, filename, utf8Offset) => {
|
|
43012
|
-
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(filename));
|
|
43013
|
-
const useIdentifier = findUseCallIdentifier(sourceFile, getUtf16Offset(sourceText, utf8Offset));
|
|
43197
|
+
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true, getScriptKind$2(filename));
|
|
43198
|
+
const useIdentifier = findUseCallIdentifier(sourceFile, getUtf16Offset$1(sourceText, utf8Offset));
|
|
43014
43199
|
if (!useIdentifier) return null;
|
|
43015
43200
|
return resolveIdentifierBinding(useIdentifier, collectReactImportBindings(sourceFile), sourceFile);
|
|
43016
43201
|
};
|
|
@@ -43031,6 +43216,201 @@ const shouldSuppressLocalUseHookDiagnostic = (diagnostic, rootDirectory) => {
|
|
|
43031
43216
|
const bindingResolution = resolveUseCallBinding(sourceText, absolutePath, primaryLabel.span.offset);
|
|
43032
43217
|
return bindingResolution !== null && !bindingResolution.isReactUseBinding;
|
|
43033
43218
|
};
|
|
43219
|
+
const SUPPRESSED_COMPILER_CODES = new Set(["react-hooks-js(immutability)", "react-hooks-js(refs)"]);
|
|
43220
|
+
const WORKLET_DIRECTIVE = "worklet";
|
|
43221
|
+
const WORKLET_ACCEPTING_CALLEES = new Set([
|
|
43222
|
+
"useAnimatedStyle",
|
|
43223
|
+
"useAnimatedProps",
|
|
43224
|
+
"useDerivedValue",
|
|
43225
|
+
"useAnimatedReaction",
|
|
43226
|
+
"useAnimatedScrollHandler",
|
|
43227
|
+
"useAnimatedGestureHandler",
|
|
43228
|
+
"useFrameCallback",
|
|
43229
|
+
"runOnUI",
|
|
43230
|
+
"executeOnUIRuntimeSync"
|
|
43231
|
+
]);
|
|
43232
|
+
const GESTURE_ROOT_IDENTIFIER = "Gesture";
|
|
43233
|
+
const getScriptKind$1 = (filename) => {
|
|
43234
|
+
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
43235
|
+
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
43236
|
+
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
43237
|
+
return ts.ScriptKind.JS;
|
|
43238
|
+
};
|
|
43239
|
+
const getUtf16Offset = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
43240
|
+
const hasWorkletDirective = (node) => {
|
|
43241
|
+
if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) return false;
|
|
43242
|
+
const body = node.body;
|
|
43243
|
+
if (!body || !ts.isBlock(body)) return false;
|
|
43244
|
+
for (const statement of body.statements) {
|
|
43245
|
+
if (!ts.isExpressionStatement(statement)) return false;
|
|
43246
|
+
if (!ts.isStringLiteral(statement.expression)) return false;
|
|
43247
|
+
if (statement.expression.text === WORKLET_DIRECTIVE) return true;
|
|
43248
|
+
}
|
|
43249
|
+
return false;
|
|
43250
|
+
};
|
|
43251
|
+
const rootIdentifierOfCallChain = (expression) => {
|
|
43252
|
+
let currentExpression = expression;
|
|
43253
|
+
while (true) {
|
|
43254
|
+
if (ts.isIdentifier(currentExpression)) return currentExpression.text;
|
|
43255
|
+
if (ts.isPropertyAccessExpression(currentExpression)) {
|
|
43256
|
+
currentExpression = currentExpression.expression;
|
|
43257
|
+
continue;
|
|
43258
|
+
}
|
|
43259
|
+
if (ts.isCallExpression(currentExpression)) {
|
|
43260
|
+
currentExpression = currentExpression.expression;
|
|
43261
|
+
continue;
|
|
43262
|
+
}
|
|
43263
|
+
return null;
|
|
43264
|
+
}
|
|
43265
|
+
};
|
|
43266
|
+
const isWorkletAcceptingCall = (callExpression) => {
|
|
43267
|
+
const callee = callExpression.expression;
|
|
43268
|
+
if (ts.isIdentifier(callee)) return WORKLET_ACCEPTING_CALLEES.has(callee.text);
|
|
43269
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
43270
|
+
if (WORKLET_ACCEPTING_CALLEES.has(callee.name.text)) return true;
|
|
43271
|
+
return rootIdentifierOfCallChain(callee) === GESTURE_ROOT_IDENTIFIER;
|
|
43272
|
+
}
|
|
43273
|
+
return false;
|
|
43274
|
+
};
|
|
43275
|
+
const isFunctionWorklet = (functionNode) => {
|
|
43276
|
+
if (hasWorkletDirective(functionNode)) return true;
|
|
43277
|
+
const parent = functionNode.parent;
|
|
43278
|
+
return ts.isCallExpression(parent) && parent.arguments.some((argument) => argument === functionNode) && isWorkletAcceptingCall(parent);
|
|
43279
|
+
};
|
|
43280
|
+
const findNodeAtOffset = (sourceFile, targetOffset) => {
|
|
43281
|
+
let matchedNode = null;
|
|
43282
|
+
const visit = (node) => {
|
|
43283
|
+
if (node.getStart(sourceFile) > targetOffset || node.getEnd() <= targetOffset) return;
|
|
43284
|
+
matchedNode = node;
|
|
43285
|
+
ts.forEachChild(node, visit);
|
|
43286
|
+
};
|
|
43287
|
+
visit(sourceFile);
|
|
43288
|
+
return matchedNode;
|
|
43289
|
+
};
|
|
43290
|
+
const isOffsetInsideWorklet = (sourceFile, targetOffset) => {
|
|
43291
|
+
let currentNode = findNodeAtOffset(sourceFile, targetOffset);
|
|
43292
|
+
while (currentNode) {
|
|
43293
|
+
if (ts.isFunctionLike(currentNode) && isFunctionWorklet(currentNode)) return true;
|
|
43294
|
+
currentNode = currentNode.parent;
|
|
43295
|
+
}
|
|
43296
|
+
return false;
|
|
43297
|
+
};
|
|
43298
|
+
const shouldSuppressCompilerFindingInWorklet = (diagnostic, project, rootDirectory) => {
|
|
43299
|
+
if (!SUPPRESSED_COMPILER_CODES.has(diagnostic.code)) return false;
|
|
43300
|
+
if (!project.hasReanimated) return false;
|
|
43301
|
+
const primaryLabel = diagnostic.labels[0];
|
|
43302
|
+
if (!primaryLabel) return false;
|
|
43303
|
+
const absolutePath = Path.isAbsolute(diagnostic.filename) ? diagnostic.filename : Path.join(rootDirectory, diagnostic.filename);
|
|
43304
|
+
let sourceText;
|
|
43305
|
+
try {
|
|
43306
|
+
sourceText = NFS.readFileSync(absolutePath, "utf-8");
|
|
43307
|
+
} catch {
|
|
43308
|
+
return false;
|
|
43309
|
+
}
|
|
43310
|
+
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind$1(absolutePath)), getUtf16Offset(sourceText, primaryLabel.span.offset));
|
|
43311
|
+
};
|
|
43312
|
+
const MANUAL_MEMOIZATION_PLUGIN = "react-doctor";
|
|
43313
|
+
const MANUAL_MEMOIZATION_RULE = "react-compiler-no-manual-memoization";
|
|
43314
|
+
const REACT_COMPILER_PLUGIN = "react-hooks-js";
|
|
43315
|
+
const getScriptKind = (filename) => {
|
|
43316
|
+
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
43317
|
+
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
43318
|
+
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
43319
|
+
return ts.ScriptKind.JS;
|
|
43320
|
+
};
|
|
43321
|
+
const isManualMemoizationDiagnostic = (diagnostic) => diagnostic.plugin === MANUAL_MEMOIZATION_PLUGIN && diagnostic.rule === MANUAL_MEMOIZATION_RULE;
|
|
43322
|
+
const nodeLineRange = (sourceFile, node) => ({
|
|
43323
|
+
startLine: sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1,
|
|
43324
|
+
endLine: sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line + 1
|
|
43325
|
+
});
|
|
43326
|
+
const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
43327
|
+
let foundRange = null;
|
|
43328
|
+
const visit = (node) => {
|
|
43329
|
+
if (foundRange) return;
|
|
43330
|
+
if (ts.isFunctionLike(node)) {
|
|
43331
|
+
const range = nodeLineRange(sourceFile, node);
|
|
43332
|
+
if (range.startLine <= targetLine && targetLine <= range.endLine) foundRange = range;
|
|
43333
|
+
return;
|
|
43334
|
+
}
|
|
43335
|
+
ts.forEachChild(node, visit);
|
|
43336
|
+
};
|
|
43337
|
+
visit(sourceFile);
|
|
43338
|
+
return foundRange;
|
|
43339
|
+
};
|
|
43340
|
+
const NEWLINE_BYTE = 10;
|
|
43341
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
43342
|
+
let lineNumber = 1;
|
|
43343
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
43344
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
43345
|
+
return lineNumber;
|
|
43346
|
+
};
|
|
43347
|
+
/**
|
|
43348
|
+
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
43349
|
+
* whose enclosing function also carries a `react-hooks-js` (React
|
|
43350
|
+
* Compiler) diagnostic. Every react-hooks-js finding marks a function the
|
|
43351
|
+
* compiler could NOT compile (a bail-out / skip / preserve-manual-
|
|
43352
|
+
* memoization failure), so "React Compiler already caches every value
|
|
43353
|
+
* here" is false for that function and the manual memoization is
|
|
43354
|
+
* load-bearing, not dead weight.
|
|
43355
|
+
*
|
|
43356
|
+
* Matching is per enclosing function, not per file: a bailed-out
|
|
43357
|
+
* component must not silence redundant-memo findings in a sibling
|
|
43358
|
+
* component the compiler did optimize.
|
|
43359
|
+
*
|
|
43360
|
+
* Module-scope `memo(() => …)` wrappers have no enclosing function; for
|
|
43361
|
+
* those the memo call's own span is the containment range, so a bail-out
|
|
43362
|
+
* inside the inline-wrapped component still suppresses. Every failure
|
|
43363
|
+
* path (unreadable file, missing span) fails open and keeps the
|
|
43364
|
+
* diagnostic.
|
|
43365
|
+
*/
|
|
43366
|
+
const suppressMemoizationInBailedOutFunctions = (diagnostics, rootDirectory) => {
|
|
43367
|
+
const compilerDiagnosticLinesByFile = /* @__PURE__ */ new Map();
|
|
43368
|
+
let hasManualMemoizationDiagnostic = false;
|
|
43369
|
+
for (const diagnostic of diagnostics) {
|
|
43370
|
+
if (isManualMemoizationDiagnostic(diagnostic)) {
|
|
43371
|
+
hasManualMemoizationDiagnostic = true;
|
|
43372
|
+
continue;
|
|
43373
|
+
}
|
|
43374
|
+
if (diagnostic.plugin !== REACT_COMPILER_PLUGIN || diagnostic.line <= 0) continue;
|
|
43375
|
+
const lines = compilerDiagnosticLinesByFile.get(diagnostic.filePath);
|
|
43376
|
+
if (lines) lines.push(diagnostic.line);
|
|
43377
|
+
else compilerDiagnosticLinesByFile.set(diagnostic.filePath, [diagnostic.line]);
|
|
43378
|
+
}
|
|
43379
|
+
if (!hasManualMemoizationDiagnostic || compilerDiagnosticLinesByFile.size === 0) return diagnostics;
|
|
43380
|
+
const parsedFileCache = /* @__PURE__ */ new Map();
|
|
43381
|
+
const readAndParse = (filePath) => {
|
|
43382
|
+
const cached = parsedFileCache.get(filePath);
|
|
43383
|
+
if (cached !== void 0) return cached;
|
|
43384
|
+
const absolutePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory || ".", filePath);
|
|
43385
|
+
let parsed;
|
|
43386
|
+
try {
|
|
43387
|
+
const buffer = NFS.readFileSync(absolutePath);
|
|
43388
|
+
parsed = {
|
|
43389
|
+
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true, getScriptKind(absolutePath)),
|
|
43390
|
+
buffer
|
|
43391
|
+
};
|
|
43392
|
+
} catch {
|
|
43393
|
+
parsed = null;
|
|
43394
|
+
}
|
|
43395
|
+
parsedFileCache.set(filePath, parsed);
|
|
43396
|
+
return parsed;
|
|
43397
|
+
};
|
|
43398
|
+
const isInsideBailedOutFunction = (diagnostic) => {
|
|
43399
|
+
const compilerLines = compilerDiagnosticLinesByFile.get(diagnostic.filePath);
|
|
43400
|
+
if (!compilerLines || diagnostic.line <= 0) return false;
|
|
43401
|
+
const parsed = readAndParse(diagnostic.filePath);
|
|
43402
|
+
if (!parsed) return false;
|
|
43403
|
+
let containmentRange = findOutermostEnclosingFunctionRange(parsed.sourceFile, diagnostic.line);
|
|
43404
|
+
if (!containmentRange && diagnostic.offset !== void 0 && diagnostic.length !== void 0) containmentRange = {
|
|
43405
|
+
startLine: diagnostic.line,
|
|
43406
|
+
endLine: lineOfUtf8Offset(parsed.buffer, diagnostic.offset + diagnostic.length)
|
|
43407
|
+
};
|
|
43408
|
+
if (!containmentRange) return false;
|
|
43409
|
+
const { startLine, endLine } = containmentRange;
|
|
43410
|
+
return compilerLines.some((compilerLine) => startLine <= compilerLine && compilerLine <= endLine);
|
|
43411
|
+
};
|
|
43412
|
+
return diagnostics.filter((diagnostic) => !isManualMemoizationDiagnostic(diagnostic) || !isInsideBailedOutFunction(diagnostic));
|
|
43413
|
+
};
|
|
43034
43414
|
const FILEPATH_WITH_LOCATION_PATTERN = /\S+\.\w+:\d+:\d+[\s\S]*$/;
|
|
43035
43415
|
const LEADING_SEVERITY_LABEL_PATTERN = /^(?:Error|Warning):\s*/;
|
|
43036
43416
|
const TRAILING_PERIOD_PATTERN = /\.$/;
|
|
@@ -43170,7 +43550,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43170
43550
|
minifiedFileCache.set(absolutePath, minified);
|
|
43171
43551
|
return minified;
|
|
43172
43552
|
};
|
|
43173
|
-
return parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory)).map((diagnostic) => {
|
|
43553
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
43174
43554
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
43175
43555
|
const primaryLabel = diagnostic.labels[0];
|
|
43176
43556
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
@@ -43197,7 +43577,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43197
43577
|
...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
|
|
43198
43578
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
43199
43579
|
};
|
|
43200
|
-
});
|
|
43580
|
+
}), rootDirectory);
|
|
43201
43581
|
};
|
|
43202
43582
|
const buildOxlintChildEnv = (sourceEnv) => {
|
|
43203
43583
|
const childEnv = {};
|
|
@@ -43708,6 +44088,7 @@ const runOxlint = async (options) => {
|
|
|
43708
44088
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
43709
44089
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
43710
44090
|
validateRuleRegistration();
|
|
44091
|
+
resetManifestCaches();
|
|
43711
44092
|
if (includePaths !== void 0 && includePaths.length === 0) return [];
|
|
43712
44093
|
const pluginPath = resolvePluginPath();
|
|
43713
44094
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
@@ -44370,9 +44751,10 @@ const CONTEXT_AXES = [
|
|
|
44370
44751
|
}
|
|
44371
44752
|
];
|
|
44372
44753
|
const SCORE_AXES = [...GATED_AXES, ...CONTEXT_AXES];
|
|
44373
|
-
const
|
|
44374
|
-
|
|
44375
|
-
|
|
44754
|
+
const gatedAxesForSection = (section) => section === "devDependencies" ? GATED_AXES.filter((axis) => axis.key !== "vulnerability") : GATED_AXES;
|
|
44755
|
+
const worstGatedAxis = (score, gatedAxes) => {
|
|
44756
|
+
let worst = gatedAxes[0];
|
|
44757
|
+
for (const axis of gatedAxes) if (score[axis.key] < score[worst.key]) worst = axis;
|
|
44376
44758
|
return worst;
|
|
44377
44759
|
};
|
|
44378
44760
|
const clampScore = (value) => {
|
|
@@ -44396,6 +44778,69 @@ const resolveConcreteVersion = (spec) => {
|
|
|
44396
44778
|
if (range === null || range === "*") return null;
|
|
44397
44779
|
return import_semver.minVersion(trimmed)?.version ?? null;
|
|
44398
44780
|
};
|
|
44781
|
+
const readTextFileOrNull = (filePath) => {
|
|
44782
|
+
try {
|
|
44783
|
+
return NFS.readFileSync(filePath, "utf-8");
|
|
44784
|
+
} catch {
|
|
44785
|
+
return null;
|
|
44786
|
+
}
|
|
44787
|
+
};
|
|
44788
|
+
const buildNpmLockLookup = (lockText) => {
|
|
44789
|
+
let parsed;
|
|
44790
|
+
try {
|
|
44791
|
+
parsed = JSON.parse(lockText);
|
|
44792
|
+
} catch {
|
|
44793
|
+
return null;
|
|
44794
|
+
}
|
|
44795
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
44796
|
+
const lock = parsed;
|
|
44797
|
+
return (name) => {
|
|
44798
|
+
const entry = lock.packages?.[`node_modules/${name}`] ?? lock.dependencies?.[name];
|
|
44799
|
+
return typeof entry?.version === "string" ? entry.version : null;
|
|
44800
|
+
};
|
|
44801
|
+
};
|
|
44802
|
+
const buildYarnLockLookup = (lockText) => {
|
|
44803
|
+
const lines = lockText.split(/\r?\n/);
|
|
44804
|
+
return (name, spec) => {
|
|
44805
|
+
const descriptor = `${name}@${spec}`;
|
|
44806
|
+
const berryDescriptor = `${name}@npm:${spec}`;
|
|
44807
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
44808
|
+
const line = lines[lineIndex];
|
|
44809
|
+
if (line.startsWith(" ") || line.startsWith("#") || !line.includes(":")) continue;
|
|
44810
|
+
const descriptors = line.replace(/:\s*$/, "").split(",").map((part) => part.trim().replace(/^"|"$/g, ""));
|
|
44811
|
+
if (!descriptors.includes(descriptor) && !descriptors.includes(berryDescriptor)) continue;
|
|
44812
|
+
for (let bodyIndex = lineIndex + 1; bodyIndex < lines.length && (lines[bodyIndex].startsWith(" ") || lines[bodyIndex] === ""); bodyIndex += 1) {
|
|
44813
|
+
const versionMatch = /^\s+version:?\s+"?([^"\s]+)"?/.exec(lines[bodyIndex]);
|
|
44814
|
+
if (versionMatch) return versionMatch[1];
|
|
44815
|
+
}
|
|
44816
|
+
return null;
|
|
44817
|
+
}
|
|
44818
|
+
return null;
|
|
44819
|
+
};
|
|
44820
|
+
};
|
|
44821
|
+
const buildPnpmLockLookup = (lockText) => {
|
|
44822
|
+
return (name) => {
|
|
44823
|
+
const entryPattern = new RegExp(`^ {4,8}['"]?${name.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&")}['"]?:\\s*$`);
|
|
44824
|
+
const lines = lockText.split(/\r?\n/);
|
|
44825
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
44826
|
+
if (!entryPattern.test(lines[lineIndex])) continue;
|
|
44827
|
+
for (let bodyIndex = lineIndex + 1; bodyIndex < lines.length && /^ {5,}\S/.test(lines[bodyIndex]); bodyIndex += 1) {
|
|
44828
|
+
const versionMatch = /^\s+version:\s+['"]?([^'"\s(]+)/.exec(lines[bodyIndex]);
|
|
44829
|
+
if (versionMatch) return versionMatch[1];
|
|
44830
|
+
}
|
|
44831
|
+
}
|
|
44832
|
+
return null;
|
|
44833
|
+
};
|
|
44834
|
+
};
|
|
44835
|
+
const buildLockedVersionLookup = (rootDirectory) => {
|
|
44836
|
+
const npmLockText = readTextFileOrNull(Path.join(rootDirectory, "package-lock.json"));
|
|
44837
|
+
if (npmLockText !== null) return buildNpmLockLookup(npmLockText);
|
|
44838
|
+
const yarnLockText = readTextFileOrNull(Path.join(rootDirectory, "yarn.lock"));
|
|
44839
|
+
if (yarnLockText !== null) return buildYarnLockLookup(yarnLockText);
|
|
44840
|
+
const pnpmLockText = readTextFileOrNull(Path.join(rootDirectory, "pnpm-lock.yaml"));
|
|
44841
|
+
if (pnpmLockText !== null) return buildPnpmLockLookup(pnpmLockText);
|
|
44842
|
+
return null;
|
|
44843
|
+
};
|
|
44399
44844
|
const locateDependencyKey = (packageJsonText, section, name) => {
|
|
44400
44845
|
const needle = `"${name}"`;
|
|
44401
44846
|
const sectionHeader = new RegExp(`"${section}"\\s*:\\s*\\{`);
|
|
@@ -44422,7 +44867,7 @@ const locateDependencyKey = (packageJsonText, section, name) => {
|
|
|
44422
44867
|
}
|
|
44423
44868
|
return null;
|
|
44424
44869
|
};
|
|
44425
|
-
const collectDependenciesToScore = (packageJson, packageJsonText, includeDevDependencies) => {
|
|
44870
|
+
const collectDependenciesToScore = (packageJson, packageJsonText, includeDevDependencies, lockedVersionLookup) => {
|
|
44426
44871
|
const sectionByName = /* @__PURE__ */ new Map();
|
|
44427
44872
|
for (const name of Object.keys(packageJson.dependencies ?? {})) sectionByName.set(name, "dependencies");
|
|
44428
44873
|
if (includeDevDependencies) {
|
|
@@ -44432,13 +44877,18 @@ const collectDependenciesToScore = (packageJson, packageJsonText, includeDevDepe
|
|
|
44432
44877
|
for (const [name, section] of sectionByName) {
|
|
44433
44878
|
if (SUPPLY_CHAIN_IGNORED_PACKAGES.has(name)) continue;
|
|
44434
44879
|
const spec = (packageJson[section] ?? {})[name] ?? "";
|
|
44435
|
-
const
|
|
44436
|
-
if (
|
|
44880
|
+
const floorVersion = resolveConcreteVersion(spec);
|
|
44881
|
+
if (floorVersion === null) continue;
|
|
44882
|
+
const lockedVersion = lockedVersionLookup?.(name, spec) ?? null;
|
|
44883
|
+
const lockSatisfiesSpec = lockedVersion !== null && import_semver.valid(lockedVersion) !== null && import_semver.satisfies(lockedVersion, spec);
|
|
44884
|
+
const isExactPin = import_semver.valid(spec.trim()) !== null;
|
|
44437
44885
|
const location = locateDependencyKey(packageJsonText, section, name);
|
|
44438
44886
|
dependencies.push({
|
|
44439
44887
|
name,
|
|
44440
|
-
version,
|
|
44888
|
+
version: lockSatisfiesSpec ? lockedVersion : floorVersion,
|
|
44441
44889
|
spec,
|
|
44890
|
+
section,
|
|
44891
|
+
resolution: isExactPin ? "pin" : lockSatisfiesSpec ? "locked" : "floor",
|
|
44442
44892
|
line: location?.line ?? 0,
|
|
44443
44893
|
column: location?.column ?? 0
|
|
44444
44894
|
});
|
|
@@ -44589,7 +45039,11 @@ const formatAlertReason = (topAlerts, totalCount) => {
|
|
|
44589
45039
|
}
|
|
44590
45040
|
return `Socket flagged ${totalCount} alerts (${topAlerts.map((alert) => friendlyAlertType(alert.type)).join(", ")}${totalCount > topAlerts.length ? ` (+${totalCount - topAlerts.length} more)` : ""}); most severe: ${displaySeverity(topAlerts[0].severity)}.`;
|
|
44591
45041
|
};
|
|
44592
|
-
const formatDependencyIdentity = (dependency) =>
|
|
45042
|
+
const formatDependencyIdentity = (dependency) => {
|
|
45043
|
+
if (dependency.resolution === "pin") return `${dependency.name}@${dependency.version}`;
|
|
45044
|
+
if (dependency.resolution === "locked") return `${dependency.name}@${dependency.version} (lockfile resolution of "${dependency.spec}")`;
|
|
45045
|
+
return `${dependency.name}@${dependency.version} (lowest version "${dependency.spec}" allows)`;
|
|
45046
|
+
};
|
|
44593
45047
|
const buildSupplyChainHelp = (dependency, failingAxis, topAlerts, packagePageUrl, options) => {
|
|
44594
45048
|
const hasCriticalAlert = topAlerts.some((alert) => alert.severity.toLowerCase() === "critical");
|
|
44595
45049
|
const entry = `\`"${dependency.name}": "${dependency.spec}"\``;
|
|
@@ -44632,7 +45086,7 @@ const buildLowScoreDiagnostic = (dependency, artifact, failingAxis, options) =>
|
|
|
44632
45086
|
const checkSupplyChain = (input) => gen(function* () {
|
|
44633
45087
|
const options = resolveOptions(input.userConfig);
|
|
44634
45088
|
const packageJsonPath = Path.join(input.rootDirectory, "package.json");
|
|
44635
|
-
const dependencies = collectDependenciesToScore(readPackageJson$1(packageJsonPath), readPackageJsonText(packageJsonPath), options.includeDevDependencies);
|
|
45089
|
+
const dependencies = collectDependenciesToScore(readPackageJson$1(packageJsonPath), readPackageJsonText(packageJsonPath), options.includeDevDependencies, buildLockedVersionLookup(input.rootDirectory));
|
|
44636
45090
|
if (dependencies.length === 0) return [];
|
|
44637
45091
|
const cacheDirectory = isSupplyChainCacheDisabled() ? null : resolveReactDoctorCacheDir(input.rootDirectory);
|
|
44638
45092
|
if (cacheDirectory !== null) pruneExpiredSocketCache(cacheDirectory);
|
|
@@ -44641,7 +45095,7 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
44641
45095
|
for (let index = 0; index < dependencies.length; index += 1) {
|
|
44642
45096
|
const artifact = artifacts[index];
|
|
44643
45097
|
if (!artifact) continue;
|
|
44644
|
-
const worstAxis = worstGatedAxis(artifact.score);
|
|
45098
|
+
const worstAxis = worstGatedAxis(artifact.score, gatedAxesForSection(dependencies[index].section));
|
|
44645
45099
|
if (toHundred(artifact.score[worstAxis.key]) >= options.minScore) continue;
|
|
44646
45100
|
diagnostics.push(buildLowScoreDiagnostic(dependencies[index], artifact, worstAxis, options));
|
|
44647
45101
|
}
|
|
@@ -45924,7 +46378,7 @@ const makeNoopConsole = () => ({
|
|
|
45924
46378
|
});
|
|
45925
46379
|
//#endregion
|
|
45926
46380
|
//#region src/cli/utils/version.ts
|
|
45927
|
-
const VERSION = "0.7.1-dev.
|
|
46381
|
+
const VERSION = "0.7.1-dev.7cf4d0b";
|
|
45928
46382
|
//#endregion
|
|
45929
46383
|
//#region src/cli/utils/json-mode.ts
|
|
45930
46384
|
let context = null;
|
|
@@ -46293,13 +46747,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
46293
46747
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
46294
46748
|
* standard `SENTRY_RELEASE` override.
|
|
46295
46749
|
*/
|
|
46296
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.1-dev.
|
|
46750
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.1-dev.7cf4d0b`;
|
|
46297
46751
|
/**
|
|
46298
46752
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
46299
46753
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
46300
46754
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
46301
46755
|
*/
|
|
46302
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.1-dev.
|
|
46756
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.1-dev.7cf4d0b") ? "development" : "production");
|
|
46303
46757
|
/**
|
|
46304
46758
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
46305
46759
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -58816,13 +59270,15 @@ const buildOutcomeAttributes = (input) => {
|
|
|
58816
59270
|
const countBySource = {
|
|
58817
59271
|
config: 0,
|
|
58818
59272
|
override: 0,
|
|
58819
|
-
inline: 0
|
|
59273
|
+
inline: 0,
|
|
59274
|
+
"foreign-inline": 0
|
|
58820
59275
|
};
|
|
58821
59276
|
for (const suppression of input.suppressedRuleCounts) countBySource[suppression.source] += suppression.count;
|
|
58822
|
-
suppressionRollup.suppressed = countBySource.config + countBySource.override + countBySource.inline;
|
|
59277
|
+
suppressionRollup.suppressed = countBySource.config + countBySource.override + countBySource.inline + countBySource["foreign-inline"];
|
|
58823
59278
|
suppressionRollup.suppressedConfig = countBySource.config;
|
|
58824
59279
|
suppressionRollup.suppressedOverride = countBySource.override;
|
|
58825
59280
|
suppressionRollup.suppressedInline = countBySource.inline;
|
|
59281
|
+
suppressionRollup.suppressedForeignInline = countBySource["foreign-inline"];
|
|
58826
59282
|
}
|
|
58827
59283
|
const attributes = {
|
|
58828
59284
|
...withNamespace("outcome", {
|
|
@@ -64472,4 +64928,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
64472
64928
|
export {};
|
|
64473
64929
|
|
|
64474
64930
|
//# sourceMappingURL=cli.js.map
|
|
64475
|
-
//# debugId=
|
|
64931
|
+
//# debugId=7b7c23b7-250e-5339-af06-e3e3b5eb5f98
|