react-doctor 0.9.3-dev.3a93a34 → 0.9.3-dev.45afa01
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 +794 -223
- package/dist/index.d.ts +9 -2
- package/dist/index.js +478 -137
- package/dist/lsp.js +487 -142
- package/dist/{run-scan-app-DtYeufgr.js → run-scan-app-QbtG43NL.js} +243 -112
- package/package.json +4 -4
package/dist/lsp.js
CHANGED
|
@@ -9,7 +9,7 @@ import { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FIL
|
|
|
9
9
|
import * as Crypto from "node:crypto";
|
|
10
10
|
import crypto, { createHash } from "node:crypto";
|
|
11
11
|
import * as NodeChildProcess from "node:child_process";
|
|
12
|
-
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
12
|
+
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
13
13
|
import { ResolverFactory } from "oxc-resolver";
|
|
14
14
|
import ts from "typescript";
|
|
15
15
|
import * as NodeUrl from "node:url";
|
|
@@ -3647,7 +3647,7 @@ const flatMap$5 = /* @__PURE__ */ dual(2, (self, f) => isNone(self) ? none() : f
|
|
|
3647
3647
|
* @category filtering
|
|
3648
3648
|
* @since 2.0.0
|
|
3649
3649
|
*/
|
|
3650
|
-
const filter = /* @__PURE__ */ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some(self.value) : none());
|
|
3650
|
+
const filter$1 = /* @__PURE__ */ dual(2, (self, predicate) => isNone(self) ? none() : predicate(self.value) ? some(self.value) : none());
|
|
3651
3651
|
//#endregion
|
|
3652
3652
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Result.js
|
|
3653
3653
|
/**
|
|
@@ -15586,7 +15586,7 @@ function transformOptional(f) {
|
|
|
15586
15586
|
*/
|
|
15587
15587
|
function withDefault$1(defaultValue) {
|
|
15588
15588
|
return new Getter((o) => {
|
|
15589
|
-
const filtered = filter(o, isNotUndefined);
|
|
15589
|
+
const filtered = filter$1(o, isNotUndefined);
|
|
15590
15590
|
return isSome(filtered) ? succeed$2(filtered) : mapEager(defaultValue, some);
|
|
15591
15591
|
});
|
|
15592
15592
|
}
|
|
@@ -19434,6 +19434,10 @@ var JsonReportProjectEntryV3 = class extends Class("JsonReportProjectEntryV3")({
|
|
|
19434
19434
|
scannedFileCount: optional(Number$1),
|
|
19435
19435
|
elapsedMilliseconds: Number$1
|
|
19436
19436
|
}) {};
|
|
19437
|
+
var JsonReportSkippedProject = class extends Class("JsonReportSkippedProject")({
|
|
19438
|
+
directory: String$1,
|
|
19439
|
+
reason: Literal("max-duration")
|
|
19440
|
+
}) {};
|
|
19437
19441
|
/** Original full, diff, and staged report contract. */
|
|
19438
19442
|
var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
19439
19443
|
schemaVersion: Literal(1),
|
|
@@ -19462,6 +19466,7 @@ var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
|
19462
19466
|
reactDetected: optional(Boolean$1),
|
|
19463
19467
|
diff: NullOr(JsonReportDiffInfo),
|
|
19464
19468
|
projects: ArraySchema(JsonReportProjectEntry),
|
|
19469
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19465
19470
|
diagnostics: ArraySchema(Diagnostic),
|
|
19466
19471
|
summary: JsonReportSummary,
|
|
19467
19472
|
elapsedMilliseconds: Number$1,
|
|
@@ -19490,6 +19495,7 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
|
|
|
19490
19495
|
diff: NullOr(JsonReportDiffInfo),
|
|
19491
19496
|
baseline: JsonReportBaseline,
|
|
19492
19497
|
projects: ArraySchema(JsonReportProjectEntry),
|
|
19498
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19493
19499
|
diagnostics: ArraySchema(Diagnostic),
|
|
19494
19500
|
summary: JsonReportSummary,
|
|
19495
19501
|
elapsedMilliseconds: Number$1,
|
|
@@ -19506,6 +19512,7 @@ var JsonReportV3 = class extends Class("JsonReportV3")({
|
|
|
19506
19512
|
diff: NullOr(JsonReportDiffInfo),
|
|
19507
19513
|
baseline: optional(JsonReportBaseline),
|
|
19508
19514
|
projects: ArraySchema(JsonReportProjectEntryV3),
|
|
19515
|
+
skippedProjects: optional(ArraySchema(JsonReportSkippedProject)),
|
|
19509
19516
|
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19510
19517
|
summary: JsonReportSummary,
|
|
19511
19518
|
elapsedMilliseconds: Number$1,
|
|
@@ -53488,6 +53495,47 @@ const flattenArray = (self) => transformPull$1(self, (pull) => {
|
|
|
53488
53495
|
}));
|
|
53489
53496
|
});
|
|
53490
53497
|
/**
|
|
53498
|
+
* Filters arrays of elements emitted by a channel, applying the filter
|
|
53499
|
+
* to each element within the arrays and only emitting non-empty filtered arrays.
|
|
53500
|
+
*
|
|
53501
|
+
* **Example** (Filtering array output)
|
|
53502
|
+
*
|
|
53503
|
+
* ```ts
|
|
53504
|
+
* import { Array, Channel } from "effect"
|
|
53505
|
+
*
|
|
53506
|
+
* const nonEmptyArrayPredicate = Array.isReadonlyArrayNonEmpty
|
|
53507
|
+
*
|
|
53508
|
+
* // Create a channel that outputs arrays of mixed data
|
|
53509
|
+
* const arrayChannel = Channel.fromIterable([
|
|
53510
|
+
* Array.make(1, 2, 3, 4, 5),
|
|
53511
|
+
* Array.make(6, 7, 8, 9, 10),
|
|
53512
|
+
* Array.make(11, 12, 13, 14, 15)
|
|
53513
|
+
* ]).pipe(Channel.filter(nonEmptyArrayPredicate))
|
|
53514
|
+
*
|
|
53515
|
+
* // Filter arrays to keep only even numbers
|
|
53516
|
+
* const evenArraysChannel = Channel.filterArray(arrayChannel, (n) => n % 2 === 0)
|
|
53517
|
+
* // Outputs: [2, 4], [6, 8, 10], [12, 14]
|
|
53518
|
+
* // Note: Only non-empty filtered arrays are emitted
|
|
53519
|
+
*
|
|
53520
|
+
* // Arrays that would become empty after filtering are discarded entirely
|
|
53521
|
+
* const oddChannel = Channel.fromIterable([
|
|
53522
|
+
* Array.make(1, 3, 5),
|
|
53523
|
+
* Array.make(2, 4),
|
|
53524
|
+
* Array.make(7, 9)
|
|
53525
|
+
* ]).pipe(Channel.filter(nonEmptyArrayPredicate))
|
|
53526
|
+
* const filteredOddChannel = Channel.filterArray(oddChannel, (n) => n % 2 === 0)
|
|
53527
|
+
* // Outputs: [2, 4] (the arrays [1,3,5] and [7,9] are discarded)
|
|
53528
|
+
* ```
|
|
53529
|
+
*
|
|
53530
|
+
* @category filtering
|
|
53531
|
+
* @since 4.0.0
|
|
53532
|
+
*/
|
|
53533
|
+
const filterArray = /* @__PURE__ */ dual(2, (self, predicate) => transformPull$1(self, (pull) => succeed$2(flatMap$2(pull, function loop(arr) {
|
|
53534
|
+
const passes = [];
|
|
53535
|
+
for (let i = 0; i < arr.length; i++) if (predicate(arr[i])) passes.push(arr[i]);
|
|
53536
|
+
return isReadonlyArrayNonEmpty(passes) ? succeed$2(passes) : flatMap$2(pull, loop);
|
|
53537
|
+
}))));
|
|
53538
|
+
/**
|
|
53491
53539
|
* Filters and maps each element inside emitted non-empty arrays using a
|
|
53492
53540
|
* `Filter`.
|
|
53493
53541
|
*
|
|
@@ -55125,6 +55173,30 @@ const concat = /* @__PURE__ */ dual(2, (self, that) => flatten(fromArray([self,
|
|
|
55125
55173
|
*/
|
|
55126
55174
|
const merge$1 = /* @__PURE__ */ dual((args) => isStream(args[0]) && isStream(args[1]), (self, that, options) => fromChannel(merge$2(toChannel(self), toChannel(that), options)));
|
|
55127
55175
|
/**
|
|
55176
|
+
* Filters a stream to the elements that satisfy a predicate.
|
|
55177
|
+
*
|
|
55178
|
+
* **Example** (Filtering stream values)
|
|
55179
|
+
*
|
|
55180
|
+
* ```ts
|
|
55181
|
+
* import { Console, Effect, Stream } from "effect"
|
|
55182
|
+
*
|
|
55183
|
+
* const program = Effect.gen(function*() {
|
|
55184
|
+
* const stream = Stream.make(1, 2, 3, 4).pipe(
|
|
55185
|
+
* Stream.filter((n) => n % 2 === 0)
|
|
55186
|
+
* )
|
|
55187
|
+
* const values = yield* Stream.runCollect(stream)
|
|
55188
|
+
* yield* Console.log(values)
|
|
55189
|
+
* })
|
|
55190
|
+
*
|
|
55191
|
+
* Effect.runPromise(program)
|
|
55192
|
+
* // Output: [ 2, 4 ]
|
|
55193
|
+
* ```
|
|
55194
|
+
*
|
|
55195
|
+
* @category filtering
|
|
55196
|
+
* @since 2.0.0
|
|
55197
|
+
*/
|
|
55198
|
+
const filter = /* @__PURE__ */ dual(2, (self, predicate) => fromChannel(filterArray(toChannel(self), predicate)));
|
|
55199
|
+
/**
|
|
55128
55200
|
* Filters and maps stream elements in one pass using a `Filter`.
|
|
55129
55201
|
*
|
|
55130
55202
|
* @category filtering
|
|
@@ -61908,6 +61980,7 @@ const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
|
61908
61980
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
61909
61981
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
61910
61982
|
const GIT_LS_FILES_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
61983
|
+
const GIT_CHECK_ATTR_MAX_BUFFER_BYTES = GIT_LS_FILES_MAX_BUFFER_BYTES;
|
|
61911
61984
|
const SCANNED_DOT_DIRECTORIES = new Set([".dumi", ".storybook"]);
|
|
61912
61985
|
const IGNORED_DIRECTORIES = new Set([
|
|
61913
61986
|
".angular",
|
|
@@ -62216,13 +62289,9 @@ const DEAD_CODE_WORKER_TIMEOUT_MS = 12e4;
|
|
|
62216
62289
|
const OXLINT_SPLIT_TOTAL_BUDGET_MS = 18e4;
|
|
62217
62290
|
const ABORT_EXIT_CODES = new Set([134, 3221226505]);
|
|
62218
62291
|
const OXLINT_OOM_RESCUE_BUDGET_MS = 6e4;
|
|
62219
|
-
const DEAD_CODE_PHASE_TIMEOUT_MS = 15e4;
|
|
62220
|
-
const LINT_PHASE_TIMEOUT_MS = 3e5;
|
|
62221
|
-
const SCAN_TOTAL_DEADLINE_MS = 9e5;
|
|
62222
62292
|
const DEAD_CODE_WORKER_MAX_OLD_SPACE_MB = 8192;
|
|
62223
62293
|
const DEAD_CODE_WORKER_MEM_BUDGET_BYTES = 2 * 1024 * 1024 * 1024;
|
|
62224
62294
|
const DEAD_CODE_TIMEOUT_CEILING_MS = 6e5;
|
|
62225
|
-
const DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS = 3e4;
|
|
62226
62295
|
const DEAD_CODE_OVERLAP_PARSE_SHARE = .4;
|
|
62227
62296
|
const RECOMMENDED_PNPM_MINIMUM_RELEASE_AGE_MINUTES = 10080;
|
|
62228
62297
|
const REACT_SERVER_DOM_PACKAGES = [
|
|
@@ -62317,6 +62386,66 @@ const isPlainObject = (value) => {
|
|
|
62317
62386
|
const prototype = Object.getPrototypeOf(value);
|
|
62318
62387
|
return prototype === null || prototype === Object.prototype;
|
|
62319
62388
|
};
|
|
62389
|
+
const LINGUIST_ATTRIBUTES = ["linguist-generated", "linguist-vendored"];
|
|
62390
|
+
const DISABLED_ATTRIBUTE_VALUES = new Set([
|
|
62391
|
+
"unspecified",
|
|
62392
|
+
"unset",
|
|
62393
|
+
"false",
|
|
62394
|
+
"0",
|
|
62395
|
+
"off",
|
|
62396
|
+
"no"
|
|
62397
|
+
]);
|
|
62398
|
+
const buildInput = (relativePaths) => `${relativePaths.join("\0")}\0`;
|
|
62399
|
+
const parseIgnoredPaths = (output) => {
|
|
62400
|
+
const ignoredPaths = /* @__PURE__ */ new Set();
|
|
62401
|
+
const fields = output.split("\0");
|
|
62402
|
+
for (let fieldIndex = 0; fieldIndex + 2 < fields.length; fieldIndex += 3) {
|
|
62403
|
+
const filePath = fields[fieldIndex];
|
|
62404
|
+
const value = fields[fieldIndex + 2]?.toLowerCase();
|
|
62405
|
+
if (filePath && value && !DISABLED_ATTRIBUTE_VALUES.has(value)) ignoredPaths.add(filePath);
|
|
62406
|
+
}
|
|
62407
|
+
return ignoredPaths;
|
|
62408
|
+
};
|
|
62409
|
+
const collectGitLinguistIgnoredPaths = (rootDirectory, relativePaths) => {
|
|
62410
|
+
if (relativePaths.length === 0) return /* @__PURE__ */ new Set();
|
|
62411
|
+
const result = spawnSync("git", [
|
|
62412
|
+
"check-attr",
|
|
62413
|
+
"-z",
|
|
62414
|
+
"--stdin",
|
|
62415
|
+
...LINGUIST_ATTRIBUTES
|
|
62416
|
+
], {
|
|
62417
|
+
cwd: rootDirectory,
|
|
62418
|
+
encoding: "utf-8",
|
|
62419
|
+
input: buildInput(relativePaths),
|
|
62420
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES
|
|
62421
|
+
});
|
|
62422
|
+
if (result.error || result.status !== 0) return /* @__PURE__ */ new Set();
|
|
62423
|
+
return parseIgnoredPaths(result.stdout);
|
|
62424
|
+
};
|
|
62425
|
+
const collectGitLinguistIgnoredPathsCooperative = (rootDirectory, relativePaths, signal) => {
|
|
62426
|
+
if (relativePaths.length === 0) return Promise.resolve(/* @__PURE__ */ new Set());
|
|
62427
|
+
return new Promise((resolve, reject) => {
|
|
62428
|
+
signal?.throwIfAborted();
|
|
62429
|
+
execFile("git", [
|
|
62430
|
+
"check-attr",
|
|
62431
|
+
"-z",
|
|
62432
|
+
"--stdin",
|
|
62433
|
+
...LINGUIST_ATTRIBUTES
|
|
62434
|
+
], {
|
|
62435
|
+
cwd: rootDirectory,
|
|
62436
|
+
encoding: "utf-8",
|
|
62437
|
+
killSignal: "SIGKILL",
|
|
62438
|
+
maxBuffer: GIT_CHECK_ATTR_MAX_BUFFER_BYTES,
|
|
62439
|
+
signal
|
|
62440
|
+
}, (error, stdout) => {
|
|
62441
|
+
if (signal?.aborted) {
|
|
62442
|
+
reject(signal.reason);
|
|
62443
|
+
return;
|
|
62444
|
+
}
|
|
62445
|
+
resolve(error ? /* @__PURE__ */ new Set() : parseIgnoredPaths(stdout));
|
|
62446
|
+
}).stdin?.end(buildInput(relativePaths));
|
|
62447
|
+
});
|
|
62448
|
+
};
|
|
62320
62449
|
const lastSourceMappingUrl = (fileContent) => {
|
|
62321
62450
|
const lastReference = [...fileContent.matchAll(/\/\/# sourceMappingURL=(\S+)/g)].at(-1);
|
|
62322
62451
|
return lastReference ? lastReference[1] : null;
|
|
@@ -62421,6 +62550,9 @@ function* walkSourceTreeFiles(rootDirectory) {
|
|
|
62421
62550
|
}
|
|
62422
62551
|
}
|
|
62423
62552
|
}
|
|
62553
|
+
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
62554
|
+
setImmediate(resolve);
|
|
62555
|
+
});
|
|
62424
62556
|
const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
62425
62557
|
const entries = [];
|
|
62426
62558
|
for (const relativePath of relativePaths) {
|
|
@@ -62434,23 +62566,55 @@ const collectSizedSourceFiles = (rootDirectory, relativePaths) => {
|
|
|
62434
62566
|
}
|
|
62435
62567
|
return entries;
|
|
62436
62568
|
};
|
|
62437
|
-
const
|
|
62569
|
+
const collectSizedSourceFilesCooperative = async (rootDirectory, relativePaths, signal) => {
|
|
62570
|
+
const entries = [];
|
|
62571
|
+
let sliceStartedAt = performance.now();
|
|
62572
|
+
for (const relativePath of relativePaths) {
|
|
62573
|
+
signal?.throwIfAborted();
|
|
62574
|
+
const absolutePath = Path.resolve(rootDirectory, relativePath);
|
|
62575
|
+
const sizeBytes = statSourceFileSize(absolutePath);
|
|
62576
|
+
if (!isLargeMinifiedFile(absolutePath, sizeBytes)) entries.push({
|
|
62577
|
+
path: relativePath,
|
|
62578
|
+
sizeBytes: sizeBytes ?? 0
|
|
62579
|
+
});
|
|
62580
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62581
|
+
await yieldToEventLoop();
|
|
62582
|
+
sliceStartedAt = performance.now();
|
|
62583
|
+
}
|
|
62584
|
+
}
|
|
62585
|
+
return entries;
|
|
62586
|
+
};
|
|
62587
|
+
const parseGitSourceFilePaths = (output) => {
|
|
62588
|
+
const trackedPaths = /* @__PURE__ */ new Set();
|
|
62589
|
+
const untrackedPaths = [];
|
|
62590
|
+
for (const entry of output.split("\0")) {
|
|
62591
|
+
if (entry.length === 0) continue;
|
|
62592
|
+
const trackedPath = /^[0-7]{6} [0-9a-f]+ [0-3]\t([\s\S]+)$/.exec(entry)?.[1];
|
|
62593
|
+
if (trackedPath === void 0) untrackedPaths.push(entry);
|
|
62594
|
+
else trackedPaths.add(trackedPath);
|
|
62595
|
+
}
|
|
62596
|
+
return {
|
|
62597
|
+
trackedPaths: [...trackedPaths],
|
|
62598
|
+
untrackedPaths
|
|
62599
|
+
};
|
|
62600
|
+
};
|
|
62601
|
+
const listGitSourceFilePaths = (rootDirectory) => {
|
|
62438
62602
|
const result = spawnSync("git", [
|
|
62439
62603
|
"ls-files",
|
|
62440
62604
|
"-z",
|
|
62441
|
-
|
|
62605
|
+
"--stage",
|
|
62606
|
+
"--others",
|
|
62607
|
+
"--exclude-standard"
|
|
62442
62608
|
], {
|
|
62443
62609
|
cwd: rootDirectory,
|
|
62444
62610
|
encoding: "utf-8",
|
|
62445
62611
|
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
62446
62612
|
});
|
|
62447
62613
|
if (result.error || result.status !== 0) return null;
|
|
62448
|
-
return result.stdout
|
|
62614
|
+
return parseGitSourceFilePaths(result.stdout);
|
|
62449
62615
|
};
|
|
62450
|
-
const
|
|
62451
|
-
const trackedPaths =
|
|
62452
|
-
const untrackedPaths = gitLsFiles(rootDirectory, ["--others", "--exclude-standard"]);
|
|
62453
|
-
if (trackedPaths === null || untrackedPaths === null) return null;
|
|
62616
|
+
const collectGitCandidateSourceFilePaths = (rootDirectory, paths) => {
|
|
62617
|
+
const { trackedPaths, untrackedPaths } = paths;
|
|
62454
62618
|
const emitDuplicateJsPaths = collectTypeScriptEmitDuplicateJsPaths({
|
|
62455
62619
|
trackedPaths: new Set(trackedPaths),
|
|
62456
62620
|
untrackedPaths,
|
|
@@ -62458,12 +62622,65 @@ const listSourceFilesViaGit = (rootDirectory) => {
|
|
|
62458
62622
|
});
|
|
62459
62623
|
return [...trackedPaths, ...untrackedPaths].filter((filePath) => isLintableSourceFile(filePath) && !hasIgnoredPathSegment(filePath) && !emitDuplicateJsPaths.has(filePath));
|
|
62460
62624
|
};
|
|
62625
|
+
const filterGitSourceFilePaths = (rootDirectory, paths) => {
|
|
62626
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62627
|
+
const linguistIgnoredPaths = collectGitLinguistIgnoredPaths(rootDirectory, candidatePaths);
|
|
62628
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62629
|
+
};
|
|
62630
|
+
const listSourceFilesViaGit = (rootDirectory) => {
|
|
62631
|
+
const paths = listGitSourceFilePaths(rootDirectory);
|
|
62632
|
+
return paths === null ? null : filterGitSourceFilePaths(rootDirectory, paths);
|
|
62633
|
+
};
|
|
62634
|
+
const listSourceFilesViaGitCooperative = async (rootDirectory, signal) => {
|
|
62635
|
+
const paths = await new Promise((resolve, reject) => {
|
|
62636
|
+
signal?.throwIfAborted();
|
|
62637
|
+
execFile("git", [
|
|
62638
|
+
"ls-files",
|
|
62639
|
+
"-z",
|
|
62640
|
+
"--stage",
|
|
62641
|
+
"--others",
|
|
62642
|
+
"--exclude-standard"
|
|
62643
|
+
], {
|
|
62644
|
+
cwd: rootDirectory,
|
|
62645
|
+
encoding: "utf-8",
|
|
62646
|
+
killSignal: "SIGKILL",
|
|
62647
|
+
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES,
|
|
62648
|
+
signal
|
|
62649
|
+
}, (error, stdout) => {
|
|
62650
|
+
if (signal?.aborted) {
|
|
62651
|
+
reject(signal.reason);
|
|
62652
|
+
return;
|
|
62653
|
+
}
|
|
62654
|
+
resolve(error ? null : parseGitSourceFilePaths(stdout));
|
|
62655
|
+
});
|
|
62656
|
+
});
|
|
62657
|
+
if (paths === null) return null;
|
|
62658
|
+
const candidatePaths = collectGitCandidateSourceFilePaths(rootDirectory, paths);
|
|
62659
|
+
const linguistIgnoredPaths = await collectGitLinguistIgnoredPathsCooperative(rootDirectory, candidatePaths, signal);
|
|
62660
|
+
return candidatePaths.filter((filePath) => !linguistIgnoredPaths.has(filePath));
|
|
62661
|
+
};
|
|
62461
62662
|
const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
62462
62663
|
const filePaths = [];
|
|
62463
62664
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62464
62665
|
return filePaths;
|
|
62465
62666
|
};
|
|
62466
|
-
const
|
|
62667
|
+
const listSourceFilesViaFilesystemCooperative = async (rootDirectory, signal) => {
|
|
62668
|
+
const filePaths = [];
|
|
62669
|
+
let sliceStartedAt = performance.now();
|
|
62670
|
+
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
62671
|
+
signal?.throwIfAborted();
|
|
62672
|
+
if (isLintableSourceFile(name)) filePaths.push(Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/"));
|
|
62673
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
62674
|
+
await yieldToEventLoop();
|
|
62675
|
+
sliceStartedAt = performance.now();
|
|
62676
|
+
}
|
|
62677
|
+
}
|
|
62678
|
+
return filePaths;
|
|
62679
|
+
};
|
|
62680
|
+
const listSourceFilePaths = (rootDirectory) => (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort();
|
|
62681
|
+
const listSourceFilePathsCooperative = async (rootDirectory, signal) => (await listSourceFilesViaGitCooperative(rootDirectory, signal) ?? await listSourceFilesViaFilesystemCooperative(rootDirectory, signal)).sort();
|
|
62682
|
+
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, listSourceFilePaths(rootDirectory));
|
|
62683
|
+
const listSourceFilesCooperative = async (rootDirectory, signal) => (await collectSizedSourceFilesCooperative(rootDirectory, await listSourceFilePathsCooperative(rootDirectory, signal), signal)).map((entry) => entry.path);
|
|
62467
62684
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
62468
62685
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
62469
62686
|
const UTF8_BOM_CHARACTER = "";
|
|
@@ -64792,7 +65009,16 @@ const getBrowserslistProtectionRequirement = (directory) => {
|
|
|
64792
65009
|
if (!queries) return void 0;
|
|
64793
65010
|
let requirement;
|
|
64794
65011
|
let hasUnsupportedTarget = false;
|
|
64795
|
-
|
|
65012
|
+
const previousIgnoreOldData = process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
65013
|
+
let browserTargets = [];
|
|
65014
|
+
try {
|
|
65015
|
+
process.env.BROWSERSLIST_IGNORE_OLD_DATA = "true";
|
|
65016
|
+
browserTargets = (0, import_browserslist.default)(queries);
|
|
65017
|
+
} finally {
|
|
65018
|
+
if (previousIgnoreOldData === void 0) delete process.env.BROWSERSLIST_IGNORE_OLD_DATA;
|
|
65019
|
+
else process.env.BROWSERSLIST_IGNORE_OLD_DATA = previousIgnoreOldData;
|
|
65020
|
+
}
|
|
65021
|
+
for (const browserTarget of browserTargets) {
|
|
64796
65022
|
const browserRequirement = getBrowserProtectionRequirement(browserTarget);
|
|
64797
65023
|
if (browserRequirement === "unsupported") hasUnsupportedTarget = true;
|
|
64798
65024
|
if (browserRequirement === "noreferrer") requirement = "noreferrer";
|
|
@@ -64902,8 +65128,8 @@ const clearProjectCache = () => {
|
|
|
64902
65128
|
* framework-agnostic rules. Throws only when the directory has nothing
|
|
64903
65129
|
* to scan (no enclosing project and no source files of its own).
|
|
64904
65130
|
*/
|
|
64905
|
-
const discoverProjectWithoutPackageJson = (directory) => {
|
|
64906
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
65131
|
+
const discoverProjectWithoutPackageJson = (directory, options) => {
|
|
65132
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
64907
65133
|
const hasOwnTsConfig = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
64908
65134
|
const enclosingProjectRoot = findNearestAncestorPackageJson(directory);
|
|
64909
65135
|
const enclosingProject = enclosingProjectRoot !== null ? discoverProject(enclosingProjectRoot) : null;
|
|
@@ -64970,12 +65196,15 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
64970
65196
|
sourceFileCount
|
|
64971
65197
|
};
|
|
64972
65198
|
};
|
|
64973
|
-
const discoverProject = (directory) => {
|
|
65199
|
+
const discoverProject = (directory, options = {}) => {
|
|
64974
65200
|
const cached = cachedProjectInfos.get(directory);
|
|
64975
|
-
if (cached !== void 0) return cached
|
|
65201
|
+
if (cached !== void 0) return options.sourceFileCount === void 0 ? cached : {
|
|
65202
|
+
...cached,
|
|
65203
|
+
sourceFileCount: options.sourceFileCount
|
|
65204
|
+
};
|
|
64976
65205
|
const packageJsonPath = Path.join(directory, "package.json");
|
|
64977
65206
|
if (!isFile(packageJsonPath)) {
|
|
64978
|
-
const synthesized = discoverProjectWithoutPackageJson(directory);
|
|
65207
|
+
const synthesized = discoverProjectWithoutPackageJson(directory, options);
|
|
64979
65208
|
cachedProjectInfos.set(directory, synthesized);
|
|
64980
65209
|
return synthesized;
|
|
64981
65210
|
}
|
|
@@ -65038,7 +65267,7 @@ const discoverProject = (directory) => {
|
|
|
65038
65267
|
const zodVersion = zod.version;
|
|
65039
65268
|
const projectName = packageJson.name ?? Path.basename(directory);
|
|
65040
65269
|
const hasTypeScript = NFS.existsSync(Path.join(directory, "tsconfig.json"));
|
|
65041
|
-
const sourceFileCount = countSourceFiles(directory);
|
|
65270
|
+
const sourceFileCount = options.sourceFileCount ?? countSourceFiles(directory);
|
|
65042
65271
|
const hasReactNativeWorkspace = framework === "expo" || framework === "react-native" || workspaceFacts.hasReactNativeAwarePackage;
|
|
65043
65272
|
const expoVersion = hasReactNativeWorkspace ? resolveCatalogBackedDependencyVersion({
|
|
65044
65273
|
rootDirectory: directory,
|
|
@@ -65845,6 +66074,10 @@ const classifyByDirectoryCohort = (packageDirectory) => {
|
|
|
65845
66074
|
current = parent;
|
|
65846
66075
|
}
|
|
65847
66076
|
};
|
|
66077
|
+
const clearPackageRoleCache = () => {
|
|
66078
|
+
cachedRoleByPackageDirectory.clear();
|
|
66079
|
+
cachedPackageDirectoryByFilename.clear();
|
|
66080
|
+
};
|
|
65848
66081
|
const classifyPackageRole = (filename) => {
|
|
65849
66082
|
if (!filename) return "unknown";
|
|
65850
66083
|
const packageDirectory = findNearestPackageDirectory(filename);
|
|
@@ -66394,7 +66627,8 @@ const readSystemFacts$1 = () => ({
|
|
|
66394
66627
|
/**
|
|
66395
66628
|
* Auto lint-worker count: the smaller of the (cgroup-CPU-aware) core count and
|
|
66396
66629
|
* the number of `PER_WORKER_MEM_BUDGET_BYTES` workers that fit in available
|
|
66397
|
-
* memory,
|
|
66630
|
+
* memory, and the measured automatic parallel-efficiency ceiling, then clamped
|
|
66631
|
+
* to `[MIN, HARD_MAX]` by `resolveScanConcurrency`.
|
|
66398
66632
|
*
|
|
66399
66633
|
* `os.availableParallelism()` already respects cgroup CPU quotas, so the core
|
|
66400
66634
|
* term needs no help. Available memory is `os.totalmem()` floored by the cgroup
|
|
@@ -66410,7 +66644,7 @@ const readSystemFacts$1 = () => ({
|
|
|
66410
66644
|
const resolveAutoScanConcurrency = (facts = readSystemFacts$1()) => {
|
|
66411
66645
|
const availableMemoryBytes = Math.min(facts.totalMemoryBytes, facts.cgroupMemoryLimitBytes ?? Number.POSITIVE_INFINITY);
|
|
66412
66646
|
const memoryBoundedWorkers = Math.floor(availableMemoryBytes / PER_WORKER_MEM_BUDGET_BYTES);
|
|
66413
|
-
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers));
|
|
66647
|
+
return resolveScanConcurrency(Math.min(facts.availableCores, memoryBoundedWorkers, 10));
|
|
66414
66648
|
};
|
|
66415
66649
|
const resolveLintBatchOrdering = () => {
|
|
66416
66650
|
return process.env["REACT_DOCTOR_LINT_BATCH_ORDERING"]?.trim().toLowerCase() === "arrival" ? "arrival" : "cost";
|
|
@@ -66423,24 +66657,22 @@ const resolveLintBatchOrdering = () => {
|
|
|
66423
66657
|
*/
|
|
66424
66658
|
var OxlintSpawnTimeoutMs = class extends Reference("react-doctor/OxlintSpawnTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS", OXLINT_SPAWN_TIMEOUT_MS) }) {};
|
|
66425
66659
|
/**
|
|
66426
|
-
* Effect-side cap on the lint phase.
|
|
66427
|
-
*
|
|
66660
|
+
* Optional Effect-side cap on the lint phase. Unbounded unless explicitly
|
|
66661
|
+
* configured through the env var or a test layer.
|
|
66428
66662
|
* Tests override via `Layer.succeed(LintPhaseTimeoutMs, ...)`.
|
|
66429
66663
|
*/
|
|
66430
|
-
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS",
|
|
66664
|
+
var LintPhaseTimeoutMs = class extends Reference("react-doctor/LintPhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_LINT_PHASE_TIMEOUT_MS", null) }) {};
|
|
66431
66665
|
/**
|
|
66432
|
-
* Effect-side cap on the dead-code phase
|
|
66433
|
-
*
|
|
66434
|
-
* type-heavy projects; tests override via
|
|
66666
|
+
* Optional Effect-side cap on the dead-code phase. Unbounded unless explicitly
|
|
66667
|
+
* configured through the env var or a test layer. Tests override via
|
|
66435
66668
|
* `Layer.succeed(DeadCodePhaseTimeoutMs, ...)`.
|
|
66436
66669
|
*/
|
|
66437
|
-
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS",
|
|
66670
|
+
var DeadCodePhaseTimeoutMs = class extends Reference("react-doctor/DeadCodePhaseTimeoutMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_DEAD_CODE_PHASE_TIMEOUT_MS", null) }) {};
|
|
66438
66671
|
/**
|
|
66439
|
-
*
|
|
66440
|
-
*
|
|
66441
|
-
* large repos; tests override via `Layer.succeed(ScanDeadlineMs, ...)`.
|
|
66672
|
+
* Optional overall scan deadline. Unbounded unless explicitly configured
|
|
66673
|
+
* through the env var or a test layer.
|
|
66442
66674
|
*/
|
|
66443
|
-
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS",
|
|
66675
|
+
var ScanDeadlineMs = class extends Reference("react-doctor/ScanDeadlineMs", { defaultValue: () => readPositiveEnvMs("REACT_DOCTOR_SCAN_DEADLINE_MS", null) }) {};
|
|
66444
66676
|
/**
|
|
66445
66677
|
* Wall-clock budget for the supply-chain check when it runs on a background
|
|
66446
66678
|
* fiber overlapping the lint pass. Reads from the env var on startup so the
|
|
@@ -66513,14 +66745,14 @@ var DeadCodeOverlap = class extends Reference("react-doctor/DeadCodeOverlap", {
|
|
|
66513
66745
|
/**
|
|
66514
66746
|
* How the full-scan lint pass plans its file batches. `"cost"` (the default)
|
|
66515
66747
|
* builds size-balanced LPT batches (`planLintBatches`): the same mandatory
|
|
66516
|
-
* batch count as greedy chunking
|
|
66517
|
-
*
|
|
66748
|
+
* batch count as greedy chunking, but every batch gets an even share of files
|
|
66749
|
+
* AND bytes, so no full chunk is a straggler while
|
|
66518
66750
|
* the remainder-batch worker idles — and the heavy files are SPREAD across
|
|
66519
66751
|
* batches, the precondition the old sort-desc-then-chunk-100 `cost` mode
|
|
66520
66752
|
* lacked (it packed the heaviest files into one wave-1 straggler batch,
|
|
66521
66753
|
* measurably regressing size-skewed repos, which is why it never earned the
|
|
66522
66754
|
* default). `"arrival"` (`REACT_DOCTOR_LINT_BATCH_ORDERING=arrival`) is the
|
|
66523
|
-
* rollback hatch to plain greedy
|
|
66755
|
+
* rollback hatch to plain greedy fixed-size chunking in discovery order. Tests
|
|
66524
66756
|
* override via `Layer.succeed(LintBatchOrdering, ...)`. Diff / staged scans
|
|
66525
66757
|
* never reach this — they pass user-scoped `includePaths` that skip discovery
|
|
66526
66758
|
* and stay in arrival order; only the full-scan branch reads it.
|
|
@@ -67010,6 +67242,10 @@ const dedupeRelatedDiagnostics = (diagnostics) => {
|
|
|
67010
67242
|
}
|
|
67011
67243
|
return uniqueDiagnostics;
|
|
67012
67244
|
};
|
|
67245
|
+
const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
67246
|
+
const relativePath = Path.relative(parentAbsolutePath, childAbsolutePath);
|
|
67247
|
+
return Boolean(relativePath) && !relativePath.startsWith("..") && !Path.isAbsolute(relativePath);
|
|
67248
|
+
};
|
|
67013
67249
|
const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
67014
67250
|
const sortDiagnosticsStable = (diagnostics) => [...diagnostics].sort((left, right) => compareStrings(left.filePath, right.filePath) || left.line - right.line || left.column - right.column || compareStrings(left.plugin, right.plugin) || compareStrings(left.rule, right.rule) || compareStrings(left.severity, right.severity) || compareStrings(left.message, right.message));
|
|
67015
67251
|
const getDirectDependencyNames = (packageJson) => new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {})]);
|
|
@@ -68586,7 +68822,7 @@ const readScannedFile = (candidate) => {
|
|
|
68586
68822
|
return null;
|
|
68587
68823
|
}
|
|
68588
68824
|
};
|
|
68589
|
-
function* collectSecurityScanFiles(rootDirectory) {
|
|
68825
|
+
function* collectSecurityScanFiles(rootDirectory, excludedDirectories = /* @__PURE__ */ new Set()) {
|
|
68590
68826
|
const priorityCandidates = [];
|
|
68591
68827
|
const artifactCandidates = [];
|
|
68592
68828
|
const otherCandidates = [];
|
|
@@ -68601,7 +68837,7 @@ function* collectSecurityScanFiles(rootDirectory) {
|
|
|
68601
68837
|
for (const entry of readDirectoryEntries(current.absolutePath)) {
|
|
68602
68838
|
const absolutePath = Path.join(current.absolutePath, entry.name);
|
|
68603
68839
|
if (entry.isDirectory()) {
|
|
68604
|
-
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name)) stack.push({
|
|
68840
|
+
if (!SKIPPED_DIRECTORY_NAMES.has(entry.name) && !excludedDirectories.has(Path.resolve(absolutePath))) stack.push({
|
|
68605
68841
|
absolutePath,
|
|
68606
68842
|
depth: current.depth + 1
|
|
68607
68843
|
});
|
|
@@ -68782,10 +69018,8 @@ const shouldEnableRule = (requires, tags, capabilities, ignoredTags, disabledWhe
|
|
|
68782
69018
|
}
|
|
68783
69019
|
return true;
|
|
68784
69020
|
};
|
|
69021
|
+
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
68785
69022
|
const shouldEnableRuleByDefaultStatus = (options) => options.defaultEnabled !== false || options.hasExplicitOverride === true || options.includeTagDefaults && options.hasIncludedTags;
|
|
68786
|
-
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
68787
|
-
setImmediate(resolve);
|
|
68788
|
-
});
|
|
68789
69023
|
const createSecurityScanSession = (rootDirectory, options) => {
|
|
68790
69024
|
const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
|
|
68791
69025
|
const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
|
|
@@ -68838,19 +69072,35 @@ const createSecurityScanSession = (rootDirectory, options) => {
|
|
|
68838
69072
|
};
|
|
68839
69073
|
};
|
|
68840
69074
|
const checkSecurityScanCooperative = async (rootDirectory, options = {}) => {
|
|
69075
|
+
const throwIfScanAborted = () => {
|
|
69076
|
+
options.signal?.throwIfAborted();
|
|
69077
|
+
};
|
|
69078
|
+
const didReachDeadline = () => {
|
|
69079
|
+
const hasDeadlineElapsed = options.deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(options.deadlineEpochMs) === 0;
|
|
69080
|
+
if (hasDeadlineElapsed) options.onDeadlineExceeded?.();
|
|
69081
|
+
return hasDeadlineElapsed;
|
|
69082
|
+
};
|
|
69083
|
+
throwIfScanAborted();
|
|
68841
69084
|
const session = createSecurityScanSession(rootDirectory, options);
|
|
68842
69085
|
if (session === null) return [];
|
|
69086
|
+
if (didReachDeadline()) return [];
|
|
68843
69087
|
let sliceStartedAt = performance.now();
|
|
68844
|
-
for (const file of collectSecurityScanFiles(rootDirectory)) {
|
|
69088
|
+
for (const file of collectSecurityScanFiles(rootDirectory, options.excludedDirectories)) {
|
|
69089
|
+
throwIfScanAborted();
|
|
69090
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68845
69091
|
if (file === null) {
|
|
68846
69092
|
if (performance.now() - sliceStartedAt >= 12) {
|
|
68847
69093
|
await yieldToEventLoop();
|
|
69094
|
+
throwIfScanAborted();
|
|
69095
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68848
69096
|
sliceStartedAt = performance.now();
|
|
68849
69097
|
}
|
|
68850
69098
|
continue;
|
|
68851
69099
|
}
|
|
68852
69100
|
for (const _ruleStep of session.scanFileByRule(file)) if (performance.now() - sliceStartedAt >= 12) {
|
|
68853
69101
|
await yieldToEventLoop();
|
|
69102
|
+
throwIfScanAborted();
|
|
69103
|
+
if (didReachDeadline()) return session.diagnostics;
|
|
68854
69104
|
sliceStartedAt = performance.now();
|
|
68855
69105
|
}
|
|
68856
69106
|
}
|
|
@@ -69764,7 +70014,6 @@ const isDiagnosticOnSurface = (diagnostic, surface, config) => {
|
|
|
69764
70014
|
return true;
|
|
69765
70015
|
};
|
|
69766
70016
|
const filterDiagnosticsForSurface = (diagnostics, surface, config) => diagnostics.filter((diagnostic) => isDiagnosticOnSurface(diagnostic, surface, config));
|
|
69767
|
-
const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs - Date.now(), 0);
|
|
69768
70017
|
/**
|
|
69769
70018
|
* Budget for the dead-code phase, scaled to the work. deslop's graph build is
|
|
69770
70019
|
* CPU-bound and roughly linear in file count, so a fixed 120s cap is too tight
|
|
@@ -69772,25 +70021,28 @@ const remainingDeadlineBudgetMs = (deadlineEpochMs) => Math.max(deadlineEpochMs
|
|
|
69772
70021
|
* tipped over by any concurrent load — silently dropping every dead-code
|
|
69773
70022
|
* finding. Scaling the budget with file count (and inversely with the core
|
|
69774
70023
|
* share when overlapped) lets the pass complete, while the ceiling still
|
|
69775
|
-
* reclaims a genuinely wedged worker.
|
|
69776
|
-
* and the Effect-side phase backstop that sits a margin above it.
|
|
70024
|
+
* reclaims a genuinely wedged worker.
|
|
69777
70025
|
*/
|
|
69778
70026
|
const resolveDeadCodeTimeout = (input) => {
|
|
69779
70027
|
const coreShareFactor = Math.max(1, input.fullConcurrency / Math.max(1, input.deadCodeConcurrency));
|
|
69780
|
-
|
|
69781
|
-
return {
|
|
69782
|
-
workerTimeoutMs,
|
|
69783
|
-
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
69784
|
-
};
|
|
70028
|
+
return { workerTimeoutMs: Math.min(DEAD_CODE_TIMEOUT_CEILING_MS, Math.max(DEAD_CODE_WORKER_TIMEOUT_MS, Math.ceil(input.sourceFileCount * 30 * coreShareFactor))) };
|
|
69785
70029
|
};
|
|
69786
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
70030
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig, sourceFiles) => {
|
|
69787
70031
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
69788
70032
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
69789
|
-
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
70033
|
+
return (sourceFiles ?? listSourceFiles(rootDirectory)).filter((filePath) => {
|
|
69790
70034
|
if (!isLintableSourceFile(filePath)) return false;
|
|
69791
70035
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
69792
70036
|
});
|
|
69793
70037
|
};
|
|
70038
|
+
const filterPathsOutsideDirectories = (input) => {
|
|
70039
|
+
const excludedPrefixes = input.excludedDirectories.map((excludedDirectory) => Path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, input.rootDirectory)).map((excludedDirectory) => Path.relative(input.rootDirectory, excludedDirectory).replaceAll("\\", "/")).sort((left, right) => left.length - right.length).filter((candidatePrefix, index, prefixes) => !prefixes.slice(0, index).some((prefix) => candidatePrefix.startsWith(`${prefix}/`)));
|
|
70040
|
+
if (excludedPrefixes.length === 0) return [...input.relativePaths];
|
|
70041
|
+
return input.relativePaths.filter((relativePath) => {
|
|
70042
|
+
const normalizedRelativePath = relativePath.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
70043
|
+
return !excludedPrefixes.some((excludedPrefix) => normalizedRelativePath === excludedPrefix || normalizedRelativePath.startsWith(`${excludedPrefix}/`));
|
|
70044
|
+
});
|
|
70045
|
+
};
|
|
69794
70046
|
var Config = class Config extends Service()("react-doctor/Config") {
|
|
69795
70047
|
static layerNode = effect(Config, gen(function* () {
|
|
69796
70048
|
const cache = yield* make$3({
|
|
@@ -69852,6 +70104,7 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69852
70104
|
static layerNode = succeed$3(Files, Files.of({
|
|
69853
70105
|
readLines: (input) => sync(() => createNodeReadFileLinesSync(input.rootDirectory)(input.filePath)),
|
|
69854
70106
|
listSourceFiles: (rootDirectory) => sync(() => listSourceFiles(rootDirectory)),
|
|
70107
|
+
listSourceFilesCooperative: (input) => promise(() => listSourceFilesCooperative(input.rootDirectory, input.signal)),
|
|
69855
70108
|
isFile: (filePath) => sync(() => isFile(filePath)),
|
|
69856
70109
|
isDirectory: (filePath) => sync(() => isDirectory(filePath))
|
|
69857
70110
|
}));
|
|
@@ -69878,6 +70131,16 @@ var Files = class Files extends Service()("react-doctor/Files") {
|
|
|
69878
70131
|
}
|
|
69879
70132
|
return files;
|
|
69880
70133
|
}),
|
|
70134
|
+
listSourceFilesCooperative: (input) => sync(() => {
|
|
70135
|
+
const rootDirectory = input.rootDirectory;
|
|
70136
|
+
const prefix = rootDirectory.endsWith("/") ? rootDirectory : `${rootDirectory}/`;
|
|
70137
|
+
const files = [];
|
|
70138
|
+
for (const absolute of tree.keys()) {
|
|
70139
|
+
if (!absolute.startsWith(prefix)) continue;
|
|
70140
|
+
files.push(absolute.slice(prefix.length));
|
|
70141
|
+
}
|
|
70142
|
+
return files;
|
|
70143
|
+
}),
|
|
69881
70144
|
isFile: (filePath) => sync(() => tree.has(filePath)),
|
|
69882
70145
|
isDirectory: (filePath) => sync(() => {
|
|
69883
70146
|
const prefix = filePath.endsWith("/") ? filePath : `${filePath}/`;
|
|
@@ -70453,7 +70716,7 @@ const batchIncludePaths = (baseArgs, includePaths) => {
|
|
|
70453
70716
|
for (const filePath of includePaths) {
|
|
70454
70717
|
const entryLength = filePath.length + 1;
|
|
70455
70718
|
const exceedsArgLength = currentBatch.length > 0 && currentBatchLength + entryLength > 24e3;
|
|
70456
|
-
const exceedsFileCount = currentBatch.length >=
|
|
70719
|
+
const exceedsFileCount = currentBatch.length >= 200;
|
|
70457
70720
|
if (exceedsArgLength || exceedsFileCount) {
|
|
70458
70721
|
batches.push(currentBatch);
|
|
70459
70722
|
currentBatch = [];
|
|
@@ -70800,7 +71063,7 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
70800
71063
|
}
|
|
70801
71064
|
return enabled;
|
|
70802
71065
|
};
|
|
70803
|
-
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 }) => {
|
|
71066
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, runtimeGlobals, unpluginAutoImportGlobalScopes, serverAuthFunctionNames, projectIndexModuleSources, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
70804
71067
|
const hasIncludedTags = includedTags.size > 0;
|
|
70805
71068
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
70806
71069
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
@@ -70864,7 +71127,8 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
70864
71127
|
}))
|
|
70865
71128
|
} : {},
|
|
70866
71129
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
70867
|
-
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
71130
|
+
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {},
|
|
71131
|
+
...projectIndexModuleSources !== void 0 ? { projectIndexModuleSources: [...projectIndexModuleSources] } : {}
|
|
70868
71132
|
} },
|
|
70869
71133
|
rules: {
|
|
70870
71134
|
...reactCompilerRules,
|
|
@@ -72349,6 +72613,12 @@ const buildProfiledNodeArguments = (input) => [
|
|
|
72349
72613
|
...input.heapProfileDirectory ? ["--heap-prof", `--heap-prof-dir=${input.heapProfileDirectory}`] : [],
|
|
72350
72614
|
...input.argumentsList
|
|
72351
72615
|
];
|
|
72616
|
+
const lowerChildProcessPriority = (processId) => {
|
|
72617
|
+
if (processId === void 0) return;
|
|
72618
|
+
try {
|
|
72619
|
+
OS.setPriority(processId, OS.constants.priority.PRIORITY_BELOW_NORMAL);
|
|
72620
|
+
} catch {}
|
|
72621
|
+
};
|
|
72352
72622
|
const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
72353
72623
|
/**
|
|
72354
72624
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
@@ -72387,6 +72657,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
|
|
|
72387
72657
|
"pipe"
|
|
72388
72658
|
]
|
|
72389
72659
|
});
|
|
72660
|
+
lowerChildProcessPriority(child.pid);
|
|
72390
72661
|
const onAbort = () => {
|
|
72391
72662
|
child.kill("SIGKILL");
|
|
72392
72663
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
@@ -72509,7 +72780,7 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
72509
72780
|
* loop with a slimmer config in that case.
|
|
72510
72781
|
*/
|
|
72511
72782
|
const spawnLintBatches = async (input) => {
|
|
72512
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth =
|
|
72783
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 9, signal, deadlineEpochMs } = input;
|
|
72513
72784
|
const resolveSourcePath = (filePath) => {
|
|
72514
72785
|
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
72515
72786
|
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
@@ -72517,6 +72788,12 @@ const spawnLintBatches = async (input) => {
|
|
|
72517
72788
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
72518
72789
|
let rescueDeadlineEpochMs;
|
|
72519
72790
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
72791
|
+
const resolveSpawnTimeoutMs = () => {
|
|
72792
|
+
const deadlineBudgets = [deadlineEpochMs, rescueDeadlineEpochMs].filter((deadline) => deadline !== void 0).map(remainingDeadlineBudgetMs);
|
|
72793
|
+
if (deadlineBudgets.length === 0) return spawnTimeoutMs;
|
|
72794
|
+
const remainingDeadlineMs = Math.min(...deadlineBudgets);
|
|
72795
|
+
return spawnTimeoutMs === void 0 ? remainingDeadlineMs : Math.min(spawnTimeoutMs, remainingDeadlineMs);
|
|
72796
|
+
};
|
|
72520
72797
|
const runBatchPass = async (concurrency, passBatches, passOnFileProgress) => {
|
|
72521
72798
|
const totalFileCount = passBatches.reduce((sum, batch) => sum + batch.length, 0);
|
|
72522
72799
|
const allDiagnostics = [];
|
|
@@ -72534,12 +72811,13 @@ const spawnLintBatches = async (input) => {
|
|
|
72534
72811
|
const batchArgs = [...baseArgs, ...batch];
|
|
72535
72812
|
try {
|
|
72536
72813
|
const spawnBatch = () => {
|
|
72537
|
-
|
|
72814
|
+
const effectiveSpawnTimeoutMs = resolveSpawnTimeoutMs();
|
|
72815
|
+
if (effectiveSpawnTimeoutMs === 0) {
|
|
72538
72816
|
deadlineSkippedFiles.push(...batch);
|
|
72539
72817
|
batchState.deadlineSkippedFileCount += batch.length;
|
|
72540
72818
|
return Promise.resolve(null);
|
|
72541
72819
|
}
|
|
72542
|
-
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath,
|
|
72820
|
+
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, effectiveSpawnTimeoutMs, outputMaxBytes, signal, () => {
|
|
72543
72821
|
if (batchState.didStart) return;
|
|
72544
72822
|
batchState.didStart = true;
|
|
72545
72823
|
startedFileCount += batchState.initialFileCount;
|
|
@@ -72694,11 +72972,36 @@ const validateRuleRegistration = () => {
|
|
|
72694
72972
|
].filter((entry) => entry !== null).join("; ");
|
|
72695
72973
|
console.warn(`[react-doctor] rule-registration drift: ${detail}`);
|
|
72696
72974
|
};
|
|
72975
|
+
const PROJECT_INDEX_MODULE_SOURCES = [
|
|
72976
|
+
"next/og",
|
|
72977
|
+
"@vercel/og",
|
|
72978
|
+
"satori",
|
|
72979
|
+
"remotion"
|
|
72980
|
+
];
|
|
72981
|
+
const collectProjectIndexModuleSources = async (rootDirectory, candidateFiles) => {
|
|
72982
|
+
const foundModuleSources = /* @__PURE__ */ new Set();
|
|
72983
|
+
let sliceStartedAt = performance.now();
|
|
72984
|
+
for (const candidateFile of candidateFiles) {
|
|
72985
|
+
let sourceBuffer;
|
|
72986
|
+
try {
|
|
72987
|
+
sourceBuffer = NFS.readFileSync(Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile));
|
|
72988
|
+
} catch {
|
|
72989
|
+
continue;
|
|
72990
|
+
}
|
|
72991
|
+
for (const moduleSource of PROJECT_INDEX_MODULE_SOURCES) if (sourceBuffer.includes(`"${moduleSource}"`) || sourceBuffer.includes(`'${moduleSource}'`)) foundModuleSources.add(moduleSource);
|
|
72992
|
+
if (foundModuleSources.size === PROJECT_INDEX_MODULE_SOURCES.length) break;
|
|
72993
|
+
if (performance.now() - sliceStartedAt >= 12) {
|
|
72994
|
+
await yieldToEventLoop();
|
|
72995
|
+
sliceStartedAt = performance.now();
|
|
72996
|
+
}
|
|
72997
|
+
}
|
|
72998
|
+
return [...foundModuleSources].sort();
|
|
72999
|
+
};
|
|
72697
73000
|
/**
|
|
72698
73001
|
* Balanced LPT (longest-processing-time-first) lint batch planner. Where
|
|
72699
|
-
* `batchIncludePaths` greedily fills
|
|
72700
|
-
* remainder batch
|
|
72701
|
-
*
|
|
73002
|
+
* `batchIncludePaths` greedily fills fixed-size batches and leaves a small
|
|
73003
|
+
* remainder batch, so the parallel pool's wall clock is set by whichever
|
|
73004
|
+
* full chunk happened to collect the most work while
|
|
72702
73005
|
* the remainder's worker idles), this planner keeps the SAME mandatory batch
|
|
72703
73006
|
* count — `ceil(files / OXLINT_MAX_FILES_PER_BATCH)`, the JS-plugin
|
|
72704
73007
|
* perf-cliff / native-binding SIGABRT guard — and assigns files largest-first,
|
|
@@ -72727,7 +73030,7 @@ const validateRuleRegistration = () => {
|
|
|
72727
73030
|
*/
|
|
72728
73031
|
const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
72729
73032
|
if (files.length === 0) return [];
|
|
72730
|
-
const batchCount = Math.ceil(files.length /
|
|
73033
|
+
const batchCount = Math.ceil(files.length / 200);
|
|
72731
73034
|
const maxFilesPerBatch = Math.ceil(files.length / batchCount);
|
|
72732
73035
|
const baseArgsLengthChars = estimateArgsLength(baseArgs);
|
|
72733
73036
|
const descendingSizeIndexes = [...files.keys()].sort((leftIndex, rightIndex) => (sizeByFile.get(files[rightIndex]) ?? 0) - (sizeByFile.get(files[leftIndex]) ?? 0));
|
|
@@ -73256,6 +73559,7 @@ const runOxlint = async (options) => {
|
|
|
73256
73559
|
await yieldToEventLoop();
|
|
73257
73560
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
73258
73561
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
73562
|
+
const projectIndexModuleSources = includePaths === void 0 && options.deadlineEpochMs === void 0 ? await collectProjectIndexModuleSources(rootDirectory, candidateFiles) : void 0;
|
|
73259
73563
|
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
73260
73564
|
rootDirectory,
|
|
73261
73565
|
candidateFiles
|
|
@@ -73278,6 +73582,7 @@ const runOxlint = async (options) => {
|
|
|
73278
73582
|
runtimeGlobals,
|
|
73279
73583
|
unpluginAutoImportGlobalScopes,
|
|
73280
73584
|
serverAuthFunctionNames,
|
|
73585
|
+
projectIndexModuleSources,
|
|
73281
73586
|
severityControls,
|
|
73282
73587
|
userPlugins,
|
|
73283
73588
|
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
@@ -73745,10 +74050,10 @@ const translateProjectInfoError = (cause, directory) => {
|
|
|
73745
74050
|
}) });
|
|
73746
74051
|
};
|
|
73747
74052
|
var Project = class Project extends Service()("react-doctor/Project") {
|
|
73748
|
-
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (
|
|
74053
|
+
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (input) {
|
|
73749
74054
|
return yield* try_({
|
|
73750
|
-
try: () => discoverProject(directory),
|
|
73751
|
-
catch: (cause) => translateProjectInfoError(cause, directory)
|
|
74055
|
+
try: () => discoverProject(input.directory, { sourceFileCount: input.sourceFileCount }),
|
|
74056
|
+
catch: (cause) => translateProjectInfoError(cause, input.directory)
|
|
73752
74057
|
});
|
|
73753
74058
|
}) }));
|
|
73754
74059
|
static layerOf = (projectInfo) => succeed$3(Project, Project.of({ discover: () => succeed$2(projectInfo) }));
|
|
@@ -74333,9 +74638,10 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
74333
74638
|
* outage.
|
|
74334
74639
|
*/
|
|
74335
74640
|
var SupplyChain = class SupplyChain extends Service()("react-doctor/SupplyChain") {
|
|
74336
|
-
static layerNode = succeed$3(SupplyChain, SupplyChain.of({ run: (input) => unwrap(flatMap$2(SupplyChainOverlapTimeoutMs, (
|
|
74337
|
-
|
|
74338
|
-
|
|
74641
|
+
static layerNode = succeed$3(SupplyChain, SupplyChain.of({ run: (input) => unwrap(flatMap$2(SupplyChainOverlapTimeoutMs, (configuredTimeoutMs) => checkSupplyChain({
|
|
74642
|
+
rootDirectory: input.rootDirectory,
|
|
74643
|
+
userConfig: input.userConfig,
|
|
74644
|
+
totalTimeoutMs: input.timeoutMs ?? configuredTimeoutMs
|
|
74339
74645
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), withSpan("SupplyChain.run"))) }));
|
|
74340
74646
|
static layerOf = (diagnostics) => succeed$3(SupplyChain, SupplyChain.of({ run: () => fromIterable$1(diagnostics) }));
|
|
74341
74647
|
};
|
|
@@ -74370,10 +74676,6 @@ const NO_HOOKS = {
|
|
|
74370
74676
|
beforeLint: () => void_,
|
|
74371
74677
|
afterLint: () => void_
|
|
74372
74678
|
};
|
|
74373
|
-
const filterMapNullable = (transform) => fromPredicateOption((value) => {
|
|
74374
|
-
const result = transform(value);
|
|
74375
|
-
return result === null ? none() : some(result);
|
|
74376
|
-
});
|
|
74377
74679
|
const fileReader = (filesService, rootDirectory) => (filePath) => {
|
|
74378
74680
|
const lines = runSync(filesService.readLines({
|
|
74379
74681
|
filePath,
|
|
@@ -74397,7 +74699,7 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74397
74699
|
* The GitHub viewer-permission lookup is forked onto a background
|
|
74398
74700
|
* fiber here and joined late (it feeds score metadata, not
|
|
74399
74701
|
* diagnostics).
|
|
74400
|
-
* 2. beforeLint hook (e.g. CLI
|
|
74702
|
+
* 2. beforeLint hook (e.g. CLI records project telemetry)
|
|
74401
74703
|
* 3. environment checks (reduced-motion + pnpm hardening +
|
|
74402
74704
|
* expo/react-native), collected synchronously. The heavier
|
|
74403
74705
|
* content-regex security scan is forked instead (like supply-chain
|
|
@@ -74410,13 +74712,11 @@ const formatLintFailText = (reasonTag, nodeVersion) => {
|
|
|
74410
74712
|
* `SupplyChainOverlapTimeoutMs` (measured from fork) so a hung
|
|
74411
74713
|
* socket can't drag out its join; on timeout it fails open to no
|
|
74412
74714
|
* diagnostics — the same outcome class as a Socket outage.
|
|
74413
|
-
* 5. Linter.run runs; DeadCode.run
|
|
74414
|
-
*
|
|
74415
|
-
*
|
|
74416
|
-
*
|
|
74417
|
-
*
|
|
74418
|
-
* fiber is joined (or interrupted, SIGKILLing its worker, on lint
|
|
74419
|
-
* failure) before diagnostics are concatenated. The afterLint hook
|
|
74715
|
+
* 5. Linter.run runs; DeadCode.run forks only when
|
|
74716
|
+
* REACT_DOCTOR_DEAD_CODE_OVERLAP=on. The default "auto" and explicit
|
|
74717
|
+
* "off" paths stay sequential. The fiber is joined (or interrupted,
|
|
74718
|
+
* SIGKILLing its worker, on lint failure) before diagnostics are
|
|
74719
|
+
* concatenated. The afterLint hook
|
|
74420
74720
|
* fires between lint and dead-code. Progress spinner labels AND the
|
|
74421
74721
|
* final diagnostic / score order stay independent of execution
|
|
74422
74722
|
* order, so terminal output is identical either way; supply-chain
|
|
@@ -74451,8 +74751,28 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74451
74751
|
const partialFailuresRef = yield* LintPartialFailures;
|
|
74452
74752
|
const resolvedConfig = yield* configService.resolve(input.directory);
|
|
74453
74753
|
const scanDirectory = resolvedConfig.resolvedDirectory;
|
|
74454
|
-
const
|
|
74754
|
+
const excludedProjectDirectories = (input.excludedProjectDirectories ?? []).map((excludedDirectory) => Path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, scanDirectory));
|
|
74755
|
+
const excludedProjectRelativePaths = excludedProjectDirectories.map((excludedDirectory) => Path.relative(scanDirectory, excludedDirectory).replaceAll("\\", "/"));
|
|
74756
|
+
const isExcludedProjectDiagnostic = (diagnostic) => {
|
|
74757
|
+
const relativeFilePath = toNormalizedRelativePath(diagnostic.filePath, scanDirectory);
|
|
74758
|
+
return excludedProjectRelativePaths.some((excludedRelativePath) => relativeFilePath === excludedRelativePath || relativeFilePath.startsWith(`${excludedRelativePath}/`));
|
|
74759
|
+
};
|
|
74760
|
+
const precomputedSourceFiles = input.suppressScanSummary === true || excludedProjectDirectories.length > 0 ? yield* filesService.listSourceFilesCooperative({
|
|
74761
|
+
rootDirectory: scanDirectory,
|
|
74762
|
+
signal: input.signal
|
|
74763
|
+
}) : null;
|
|
74764
|
+
const includedPrecomputedSourceFiles = precomputedSourceFiles !== null && excludedProjectDirectories.length > 0 ? filterPathsOutsideDirectories({
|
|
74765
|
+
rootDirectory: scanDirectory,
|
|
74766
|
+
relativePaths: precomputedSourceFiles,
|
|
74767
|
+
excludedDirectories: excludedProjectDirectories
|
|
74768
|
+
}) : precomputedSourceFiles;
|
|
74769
|
+
const sourceFileCount = excludedProjectDirectories.length > 0 ? includedPrecomputedSourceFiles?.length : input.precomputedSourceFileCount ?? includedPrecomputedSourceFiles?.length;
|
|
74770
|
+
const project = yield* projectService.discover({
|
|
74771
|
+
directory: scanDirectory,
|
|
74772
|
+
sourceFileCount
|
|
74773
|
+
});
|
|
74455
74774
|
if (!isAnalyzableProject(project)) return yield* new ReactDoctorError({ reason: new NoReactDependency({ directory: scanDirectory }) });
|
|
74775
|
+
const deadCodeSourceFileCount = input.retainExcludedProjectDeadCodeDiagnostics === true && precomputedSourceFiles !== null ? precomputedSourceFiles.length : project.sourceFileCount;
|
|
74456
74776
|
const [repo, sha, defaultBranch] = yield* all([
|
|
74457
74777
|
gitService.githubRepo(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
74458
74778
|
gitService.headSha(scanDirectory).pipe(orElseSucceed(() => null)),
|
|
@@ -74463,11 +74783,16 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74463
74783
|
directory: scanDirectory,
|
|
74464
74784
|
repo
|
|
74465
74785
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
74466
|
-
|
|
74467
|
-
|
|
74786
|
+
let lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, includedPrecomputedSourceFiles ?? void 0);
|
|
74787
|
+
if (excludedProjectDirectories.length > 0) lintIncludePaths = filterPathsOutsideDirectories({
|
|
74788
|
+
rootDirectory: scanDirectory,
|
|
74789
|
+
relativePaths: lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory)),
|
|
74790
|
+
excludedDirectories: excludedProjectDirectories
|
|
74791
|
+
});
|
|
74792
|
+
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? includedPrecomputedSourceFiles ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
74468
74793
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
74469
74794
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
74470
|
-
yield* beforeLint(project
|
|
74795
|
+
yield* beforeLint(project);
|
|
74471
74796
|
const isDiffMode = input.includePaths.length > 0;
|
|
74472
74797
|
const showWarnings = input.warnings ?? resolvedConfig.config?.warnings ?? true;
|
|
74473
74798
|
const transform = buildDiagnosticPipeline({
|
|
@@ -74477,7 +74802,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74477
74802
|
respectInlineDisables: input.respectInlineDisables,
|
|
74478
74803
|
showWarnings
|
|
74479
74804
|
});
|
|
74480
|
-
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(
|
|
74805
|
+
const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(fromPredicateOption((diagnostic) => {
|
|
74806
|
+
const filteredDiagnostic = transform.apply(diagnostic);
|
|
74807
|
+
return filteredDiagnostic === null ? none() : some(filteredDiagnostic);
|
|
74808
|
+
})));
|
|
74481
74809
|
const applyPerElementPipeline = (rawStream) => filterPerElementPipeline(rawStream).pipe(tap((diagnostic) => reporterService.emit(diagnostic)));
|
|
74482
74810
|
const envCollected = yield* runCollect(applyPerElementPipeline(fromIterable$1(isDiffMode ? [] : [
|
|
74483
74811
|
...checkReducedMotion(scanDirectory),
|
|
@@ -74487,17 +74815,31 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74487
74815
|
...checkReactNativeProject(scanDirectory, project)
|
|
74488
74816
|
])));
|
|
74489
74817
|
const securityScanFailedRef = yield* make$13(false);
|
|
74490
|
-
|
|
74818
|
+
let didSecurityScanReachDeadline = false;
|
|
74819
|
+
const securityScanFiber = yield* forkChild(runCollect(applyPerElementPipeline(isDiffMode ? empty$4 : unwrap(tryPromise((signal) => checkSecurityScanCooperative(scanDirectory, {
|
|
74491
74820
|
project,
|
|
74492
74821
|
ignoredTags: input.ignoredTags,
|
|
74493
74822
|
includedTags: input.includedTags,
|
|
74494
|
-
includeTagDefaults: input.includeTagDefaults
|
|
74823
|
+
includeTagDefaults: input.includeTagDefaults,
|
|
74824
|
+
excludedDirectories: new Set(excludedProjectDirectories),
|
|
74825
|
+
deadlineEpochMs: input.deadlineEpochMs,
|
|
74826
|
+
signal,
|
|
74827
|
+
onDeadlineExceeded: () => {
|
|
74828
|
+
didSecurityScanReachDeadline = true;
|
|
74829
|
+
}
|
|
74495
74830
|
})).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)), catch_$1(() => set(securityScanFailedRef, true).pipe(as(empty$4))))))).pipe(withSpan("SecurityScan.run")));
|
|
74831
|
+
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74832
|
+
const capOptionalToDeadline = (phaseTimeoutMs) => {
|
|
74833
|
+
if (input.deadlineEpochMs === void 0) return phaseTimeoutMs;
|
|
74834
|
+
const remainingBudgetMs = remainingDeadlineBudgetMs(input.deadlineEpochMs);
|
|
74835
|
+
return phaseTimeoutMs === null ? remainingBudgetMs : Math.min(phaseTimeoutMs, remainingBudgetMs);
|
|
74836
|
+
};
|
|
74496
74837
|
const shouldRunSupplyChain = !isDiffMode || (input.supplyChainManifestChanged ?? false);
|
|
74497
|
-
const supplyChainOverlapTimeout = yield* SupplyChainOverlapTimeoutMs;
|
|
74838
|
+
const supplyChainOverlapTimeout = capToDeadline(yield* SupplyChainOverlapTimeoutMs);
|
|
74498
74839
|
const supplyChainFiber = yield* forkChild(shouldRunSupplyChain ? runCollect(applyPerElementPipeline(supplyChainService.run({
|
|
74499
74840
|
rootDirectory: scanDirectory,
|
|
74500
|
-
userConfig: resolvedConfig.config
|
|
74841
|
+
userConfig: resolvedConfig.config,
|
|
74842
|
+
timeoutMs: supplyChainOverlapTimeout
|
|
74501
74843
|
}))).pipe(map$3((diagnostics) => ({
|
|
74502
74844
|
diagnostics,
|
|
74503
74845
|
timedOut: false
|
|
@@ -74521,46 +74863,49 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74521
74863
|
const scanConcurrency = resolveScanConcurrency(yield* OxlintConcurrency);
|
|
74522
74864
|
const lintPhaseTimeoutMs = yield* LintPhaseTimeoutMs;
|
|
74523
74865
|
const deadCodePhaseTimeoutMs = yield* DeadCodePhaseTimeoutMs;
|
|
74524
|
-
const resolveDeadCodePhaseTimeoutMs = (scaledPhaseTimeoutMs) => deadCodePhaseTimeoutMs === 15e4 ? scaledPhaseTimeoutMs : deadCodePhaseTimeoutMs;
|
|
74525
74866
|
const workerCountSuffix = scanConcurrency > 1 ? ` ${highlighter.dim(`[~${scanConcurrency} workers]`)}` : "";
|
|
74526
|
-
const capToDeadline = (phaseTimeoutMs) => input.deadlineEpochMs === void 0 ? phaseTimeoutMs : Math.min(phaseTimeoutMs, remainingDeadlineBudgetMs(input.deadlineEpochMs));
|
|
74527
74867
|
const shouldRunDeadCode = input.runDeadCode && !isDiffMode && (showWarnings || deadCodeMaySurfaceWhenWarningsHidden(resolvedConfig.config));
|
|
74528
74868
|
const deadCodeOverlapMode = yield* DeadCodeOverlap;
|
|
74529
74869
|
const shouldOverlapDeadCode = shouldRunDeadCode && deadCodeOverlapMode === "on";
|
|
74530
74870
|
const deadCodeParseConcurrency = shouldOverlapDeadCode ? Math.max(1, Math.floor(scanConcurrency * DEAD_CODE_OVERLAP_PARSE_SHARE)) : void 0;
|
|
74531
74871
|
const lintConcurrency = deadCodeParseConcurrency === void 0 ? scanConcurrency : Math.max(1, scanConcurrency - deadCodeParseConcurrency);
|
|
74532
|
-
const buildCollectDeadCode = (deadCodeTimeout) =>
|
|
74533
|
-
|
|
74534
|
-
|
|
74535
|
-
|
|
74536
|
-
|
|
74537
|
-
|
|
74538
|
-
|
|
74539
|
-
|
|
74540
|
-
|
|
74541
|
-
|
|
74542
|
-
|
|
74543
|
-
|
|
74544
|
-
|
|
74545
|
-
|
|
74546
|
-
|
|
74547
|
-
|
|
74548
|
-
|
|
74549
|
-
|
|
74550
|
-
|
|
74551
|
-
|
|
74552
|
-
|
|
74553
|
-
|
|
74554
|
-
|
|
74555
|
-
|
|
74872
|
+
const buildCollectDeadCode = (deadCodeTimeout) => {
|
|
74873
|
+
const collectDeadCode = runCollect(applyPerElementPipeline(deadCodeService.run({
|
|
74874
|
+
rootDirectory: scanDirectory,
|
|
74875
|
+
parseConcurrency: deadCodeParseConcurrency,
|
|
74876
|
+
workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
|
|
74877
|
+
onCacheOutcome: (didHitCache) => {
|
|
74878
|
+
deadCodeCacheHit = didHitCache;
|
|
74879
|
+
},
|
|
74880
|
+
onSummaryCacheStats: (stats) => {
|
|
74881
|
+
deadCodeSummaryCacheHits = stats.hits;
|
|
74882
|
+
deadCodeSummaryCacheMisses = stats.misses;
|
|
74883
|
+
}
|
|
74884
|
+
}).pipe(filter((diagnostic) => input.retainExcludedProjectDeadCodeDiagnostics === true || !isExcludedProjectDiagnostic(diagnostic)), catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
|
|
74885
|
+
yield* set(deadCodeFailure, {
|
|
74886
|
+
didFail: true,
|
|
74887
|
+
reason: error.message
|
|
74888
|
+
});
|
|
74889
|
+
return empty$4;
|
|
74890
|
+
}))))));
|
|
74891
|
+
const phaseTimeoutMs = deadCodeTimeout.phaseTimeoutMs;
|
|
74892
|
+
if (phaseTimeoutMs === null) return collectDeadCode;
|
|
74893
|
+
return collectDeadCode.pipe(timeoutOption(phaseTimeoutMs), flatMap$2(match$3({
|
|
74894
|
+
onNone: () => set(deadCodeFailure, {
|
|
74895
|
+
didFail: true,
|
|
74896
|
+
reason: `Dead-code analysis exceeded ${Math.round(phaseTimeoutMs / MILLISECONDS_PER_SECOND)}s and was skipped.`
|
|
74897
|
+
}).pipe(as([])),
|
|
74898
|
+
onSome: succeed$2
|
|
74899
|
+
})));
|
|
74900
|
+
};
|
|
74556
74901
|
const overlapDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74557
|
-
sourceFileCount:
|
|
74902
|
+
sourceFileCount: deadCodeSourceFileCount,
|
|
74558
74903
|
deadCodeConcurrency: deadCodeParseConcurrency ?? scanConcurrency,
|
|
74559
74904
|
fullConcurrency: scanConcurrency
|
|
74560
74905
|
});
|
|
74561
74906
|
const deadCodeFiber = shouldOverlapDeadCode ? yield* forkChild(buildCollectDeadCode({
|
|
74562
74907
|
workerTimeoutMs: overlapDeadCodeTimeout.workerTimeoutMs,
|
|
74563
|
-
phaseTimeoutMs:
|
|
74908
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74564
74909
|
})) : null;
|
|
74565
74910
|
const scanProgress = yield* progressService.start("Scanning...");
|
|
74566
74911
|
const scanStartTime = Date.now();
|
|
@@ -74611,7 +74956,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74611
74956
|
});
|
|
74612
74957
|
return empty$4;
|
|
74613
74958
|
}))));
|
|
74614
|
-
const
|
|
74959
|
+
const collectLintDiagnostics = runCollect(filterPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream));
|
|
74960
|
+
const lintCollected = dedupeRelatedDiagnostics(yield* lintPhaseTimeoutMs === null ? collectLintDiagnostics : collectLintDiagnostics.pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
|
|
74615
74961
|
onNone: () => set(lintFailure, {
|
|
74616
74962
|
didFail: true,
|
|
74617
74963
|
reason: `Lint analysis exceeded ${lintPhaseTimeoutMs / MILLISECONDS_PER_SECOND}s and was skipped.`,
|
|
@@ -74641,13 +74987,13 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74641
74987
|
} else {
|
|
74642
74988
|
yield* scanProgress.update(`Scanned ${scannedFilesLabel}, analyzing dead code...`);
|
|
74643
74989
|
const sequentialDeadCodeTimeout = resolveDeadCodeTimeout({
|
|
74644
|
-
sourceFileCount: totalFileCount,
|
|
74990
|
+
sourceFileCount: input.retainExcludedProjectDeadCodeDiagnostics === true ? deadCodeSourceFileCount : totalFileCount,
|
|
74645
74991
|
deadCodeConcurrency: scanConcurrency,
|
|
74646
74992
|
fullConcurrency: scanConcurrency
|
|
74647
74993
|
});
|
|
74648
74994
|
deadCodeCollected = deadCodeFiber !== null ? yield* join(deadCodeFiber) : yield* buildCollectDeadCode({
|
|
74649
74995
|
workerTimeoutMs: sequentialDeadCodeTimeout.workerTimeoutMs,
|
|
74650
|
-
phaseTimeoutMs:
|
|
74996
|
+
phaseTimeoutMs: capOptionalToDeadline(deadCodePhaseTimeoutMs)
|
|
74651
74997
|
});
|
|
74652
74998
|
}
|
|
74653
74999
|
const deadCodeFailureState = lintFailureState.didFail ? {
|
|
@@ -74691,7 +75037,11 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74691
75037
|
metadata: scoreMetadata
|
|
74692
75038
|
});
|
|
74693
75039
|
const lintPartialFailures = yield* get$2(partialFailuresRef);
|
|
74694
|
-
const
|
|
75040
|
+
const didSecurityScanFail = yield* get$2(securityScanFailedRef);
|
|
75041
|
+
const securityScanFailed = didSecurityScanFail || didSecurityScanReachDeadline;
|
|
75042
|
+
let securityScanFailureReason = null;
|
|
75043
|
+
if (didSecurityScanReachDeadline) securityScanFailureReason = "Security scan reached the max scan duration; findings collected before the deadline were preserved.";
|
|
75044
|
+
else if (didSecurityScanFail) securityScanFailureReason = "Security scan failed and was skipped.";
|
|
74695
75045
|
return {
|
|
74696
75046
|
project,
|
|
74697
75047
|
userConfig: resolvedConfig.config,
|
|
@@ -74714,6 +75064,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74714
75064
|
scanConcurrency,
|
|
74715
75065
|
supplyChainOverlapTimedOut: supplyChainResult.timedOut,
|
|
74716
75066
|
securityScanFailed,
|
|
75067
|
+
securityScanFailureReason,
|
|
74717
75068
|
lintCacheHitFileCount,
|
|
74718
75069
|
lintCacheTotalFileCount,
|
|
74719
75070
|
lintSidecarReplayedFileCount,
|
|
@@ -74729,7 +75080,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
74729
75080
|
"inspect.runDeadCode": input.runDeadCode,
|
|
74730
75081
|
"inspect.isCi": input.isCi,
|
|
74731
75082
|
"inspect.scoreSurface": input.scoreSurface ?? "score"
|
|
74732
|
-
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) =>
|
|
75083
|
+
} }), (scanProgram) => flatMap$2(ScanDeadlineMs, (scanDeadlineMs) => {
|
|
75084
|
+
if (scanDeadlineMs === null) return scanProgram;
|
|
75085
|
+
return scanProgram.pipe(timeout(scanDeadlineMs), catchTag$1("TimeoutError", () => new ReactDoctorError({ reason: new ScanDeadlineExceeded({ detail: `${scanDeadlineMs / MILLISECONDS_PER_SECOND}s elapsed` }) })));
|
|
75086
|
+
}));
|
|
74733
75087
|
const parseNodeVersion = (versionString) => {
|
|
74734
75088
|
const [major = 0, minor = 0, patch = 0] = versionString.replace(/^v/, "").trim().split(".").map(Number);
|
|
74735
75089
|
return {
|
|
@@ -74830,16 +75184,6 @@ const resolveNodeForOxlint = () => {
|
|
|
74830
75184
|
});
|
|
74831
75185
|
});
|
|
74832
75186
|
/**
|
|
74833
|
-
* Zip-Slip defense: relative paths come from git (`diff --name-only`), which
|
|
74834
|
-
* normalizes during ordinary adds, but a crafted index/pack/symlinked tree can
|
|
74835
|
-
* smuggle `..` segments that escape the temp root. Resolve against the temp dir
|
|
74836
|
-
* and reject anything that lands outside before writing.
|
|
74837
|
-
*/
|
|
74838
|
-
const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
74839
|
-
const relative = path.relative(parentAbsolutePath, childAbsolutePath);
|
|
74840
|
-
return Boolean(relative) && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
74841
|
-
};
|
|
74842
|
-
/**
|
|
74843
75187
|
* Writes a set of source files (supplied by `readContent` — e.g.
|
|
74844
75188
|
* `git show <ref>:<path>` for a baseline tree, or `git show :<path>` for the
|
|
74845
75189
|
* index) into a temp tree that mirrors the project layout, copying the
|
|
@@ -75691,10 +76035,7 @@ const createProjectGraph = (options) => {
|
|
|
75691
76035
|
for (const root of roots) try {
|
|
75692
76036
|
for (const workspacePackage of discoverReactSubprojects(root)) {
|
|
75693
76037
|
const directory = normalizeDirectory(workspacePackage.directory);
|
|
75694
|
-
if (!seen.has(directory)) seen.set(directory, {
|
|
75695
|
-
directory,
|
|
75696
|
-
name: workspacePackage.name
|
|
75697
|
-
});
|
|
76038
|
+
if (!seen.has(directory)) seen.set(directory, { directory });
|
|
75698
76039
|
}
|
|
75699
76040
|
} catch (error) {
|
|
75700
76041
|
logger.warn(`Project discovery failed for ${root}: ${messageFromUnknown(error)}`);
|
|
@@ -75719,6 +76060,7 @@ const createProjectGraph = (options) => {
|
|
|
75719
76060
|
clearProjectCache();
|
|
75720
76061
|
clearConfigCache();
|
|
75721
76062
|
clearPackageJsonCache();
|
|
76063
|
+
clearPackageRoleCache();
|
|
75722
76064
|
clearIgnorePatternsCache();
|
|
75723
76065
|
clearAutoSuppressionCaches();
|
|
75724
76066
|
clearMinifiedFileCache();
|
|
@@ -76116,11 +76458,9 @@ const createScheduler = (options) => {
|
|
|
76116
76458
|
timers.clear();
|
|
76117
76459
|
queue.length = 0;
|
|
76118
76460
|
};
|
|
76119
|
-
const pendingCount = () => queue.length + running + timers.size;
|
|
76120
76461
|
return {
|
|
76121
76462
|
enqueue,
|
|
76122
76463
|
cancelProject,
|
|
76123
|
-
pendingCount,
|
|
76124
76464
|
dispose
|
|
76125
76465
|
};
|
|
76126
76466
|
};
|
|
@@ -76767,8 +77107,11 @@ const METRIC = {
|
|
|
76767
77107
|
scanPhaseDuration: "scan.phase_duration",
|
|
76768
77108
|
scanFiles: "scan.files",
|
|
76769
77109
|
scanScore: "scan.score",
|
|
77110
|
+
scanScoreRetry: "scan.score_retry",
|
|
76770
77111
|
scanClean: "scan.clean",
|
|
76771
77112
|
scanCheckSkipped: "scan.check_skipped",
|
|
77113
|
+
scanProjectSkipped: "scan.project_skipped",
|
|
77114
|
+
scanWorkspaceDeadCodeShared: "scan.workspace_deadcode_shared",
|
|
76772
77115
|
scanNoReactDetected: "scan.no_react_detected",
|
|
76773
77116
|
baselineDegraded: "baseline.degraded",
|
|
76774
77117
|
ruleFired: "rule.fired",
|
|
@@ -76799,8 +77142,10 @@ const METRIC = {
|
|
|
76799
77142
|
tuiFindingNavigated: "tui.finding_navigated",
|
|
76800
77143
|
tuiIssueStreamShown: "tui.issue_stream_shown",
|
|
76801
77144
|
tuiProjectPathContextShown: "tui.project_path_context_shown",
|
|
77145
|
+
tuiProjectSelectInlineShown: "tui.project_select_inline_shown",
|
|
76802
77146
|
tuiReportActionSelected: "tui.report_action_selected",
|
|
76803
77147
|
tuiCancelled: "tui.cancelled",
|
|
77148
|
+
tuiScanInlineShown: "tui.scan_inline_shown",
|
|
76804
77149
|
tuiStackedReportCapped: "tui.stacked_report_capped",
|
|
76805
77150
|
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
76806
77151
|
jsonOutUsed: "json.out_used"
|
|
@@ -77103,5 +77448,5 @@ const startLanguageServer = () => {
|
|
|
77103
77448
|
};
|
|
77104
77449
|
//#endregion
|
|
77105
77450
|
export { startLanguageServer };
|
|
77106
|
-
!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]="
|
|
77107
|
-
//# debugId=
|
|
77451
|
+
!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]="9c497322-df37-5162-a092-8ebb7ef33f3a")}catch(e){}}();
|
|
77452
|
+
//# debugId=9c497322-df37-5162-a092-8ebb7ef33f3a
|