react-doctor 0.9.1 → 0.9.2-dev.075865f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cli.js +2170 -344
- package/dist/index.d.ts +11 -5
- package/dist/index.js +1844 -241
- package/dist/lsp.js +1833 -238
- package/dist/{run-scan-app-DZ5jGWFf.js → run-scan-app-DHRvqfkX.js} +288 -216
- package/package.json +9 -7
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]="3bff4f9b-31f8-5abe-b7a2-a0ab9f6a85b4")}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";
|
|
@@ -8,17 +8,19 @@ import path from "node:path";
|
|
|
8
8
|
import * as NFS from "node:fs";
|
|
9
9
|
import fs, { mkdtempSync, rmSync } from "node:fs";
|
|
10
10
|
import process$1 from "node:process";
|
|
11
|
-
import
|
|
11
|
+
import { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, REACT_DOCTOR_RULE_REGISTRY, REACT_DOCTOR_SCAN_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor/core";
|
|
12
12
|
import * as Crypto from "node:crypto";
|
|
13
13
|
import crypto, { createHash, randomUUID } from "node:crypto";
|
|
14
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
14
15
|
import ts from "typescript";
|
|
16
|
+
import * as NodeUrl from "node:url";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
15
18
|
import * as OS from "node:os";
|
|
16
19
|
import os, { tmpdir } from "node:os";
|
|
17
20
|
import { parseJSON5 } from "confbox";
|
|
18
|
-
import * as NodeUrl from "node:url";
|
|
19
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
20
21
|
import { createJiti } from "jiti";
|
|
21
22
|
import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
|
|
23
|
+
import { convertToTSX } from "@astrojs/compiler/sync";
|
|
22
24
|
import { gzipSync } from "node:zlib";
|
|
23
25
|
import * as Sentry from "@sentry/node";
|
|
24
26
|
import { performance as performance$1 } from "node:perf_hooks";
|
|
@@ -13341,7 +13343,7 @@ const Number$4 = globalThis.Number;
|
|
|
13341
13343
|
* @category constructors
|
|
13342
13344
|
* @since 2.0.0
|
|
13343
13345
|
*/
|
|
13344
|
-
const parse = (s) => {
|
|
13346
|
+
const parse$1 = (s) => {
|
|
13345
13347
|
if (s === "NaN") return some(NaN);
|
|
13346
13348
|
if (s === "Infinity") return some(Infinity);
|
|
13347
13349
|
if (s === "-Infinity") return some(-Infinity);
|
|
@@ -17404,12 +17406,12 @@ TaggedError("EncodingError");
|
|
|
17404
17406
|
//#endregion
|
|
17405
17407
|
//#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/internal/schema/annotations.js
|
|
17406
17408
|
/** @internal */
|
|
17407
|
-
function resolve(ast) {
|
|
17409
|
+
function resolve$1(ast) {
|
|
17408
17410
|
return ast.checks ? ast.checks[ast.checks.length - 1].annotations : ast.annotations;
|
|
17409
17411
|
}
|
|
17410
17412
|
/** @internal */
|
|
17411
17413
|
function resolveAt(key) {
|
|
17412
|
-
return (ast) => resolve(ast)?.[key];
|
|
17414
|
+
return (ast) => resolve$1(ast)?.[key];
|
|
17413
17415
|
}
|
|
17414
17416
|
/** @internal */
|
|
17415
17417
|
const resolveIdentifier = /* @__PURE__ */ resolveAt("identifier");
|
|
@@ -21161,7 +21163,7 @@ function asSync(parser) {
|
|
|
21161
21163
|
}
|
|
21162
21164
|
const recur$1 = /* @__PURE__ */ memoize((ast) => {
|
|
21163
21165
|
let parser;
|
|
21164
|
-
const astOptions = resolve(ast)?.["parseOptions"];
|
|
21166
|
+
const astOptions = resolve$1(ast)?.["parseOptions"];
|
|
21165
21167
|
if (!ast.context && !ast.encoding && !ast.checks) return (ou, options) => {
|
|
21166
21168
|
parser ??= ast.getParser(recur$1);
|
|
21167
21169
|
if (astOptions) options = {
|
|
@@ -60766,7 +60768,7 @@ var UrlParamsError = class extends TaggedError("UrlParamsError") {};
|
|
|
60766
60768
|
* @category converting
|
|
60767
60769
|
* @since 4.0.0
|
|
60768
60770
|
*/
|
|
60769
|
-
const makeUrl = (url, params, hash) => {
|
|
60771
|
+
const makeUrl$1 = (url, params, hash) => {
|
|
60770
60772
|
try {
|
|
60771
60773
|
const urlInstance = new URL(url, baseUrl());
|
|
60772
60774
|
for (let i = 0; i < params.params.length; i++) {
|
|
@@ -61400,7 +61402,7 @@ const Proto$2 = {
|
|
|
61400
61402
|
const make$10 = (f) => makeWith$1((effect) => flatMap$2(effect, (request) => withFiber((fiber) => {
|
|
61401
61403
|
const scopedController = scopedRequests.get(request);
|
|
61402
61404
|
const controller = scopedController ?? new AbortController();
|
|
61403
|
-
const urlResult = makeUrl(request.url, request.urlParams, getOrUndefined(request.hash));
|
|
61405
|
+
const urlResult = makeUrl$1(request.url, request.urlParams, getOrUndefined(request.hash));
|
|
61404
61406
|
if (isFailure(urlResult)) return fail$4(new HttpClientError({ reason: new InvalidUrlError({
|
|
61405
61407
|
request,
|
|
61406
61408
|
cause: urlResult.failure
|
|
@@ -61839,7 +61841,7 @@ const layer$8 = (loggers, options) => effect(CurrentLoggers, withFiber$1(fnUntra
|
|
|
61839
61841
|
* @since 4.0.0
|
|
61840
61842
|
*/
|
|
61841
61843
|
const policy = /* @__PURE__ */ forever$1.pipe(passthrough$2, /* @__PURE__ */ addDelay((error) => {
|
|
61842
|
-
if (isHttpClientError(error) && error.reason._tag === "StatusCodeError" && error.reason.response.status === 429) return succeed$2(seconds(fromUndefinedOr(error.reason.response.headers["retry-after"]).pipe(flatMap$5(parse), getOrElse$1(() => 5))));
|
|
61844
|
+
if (isHttpClientError(error) && error.reason._tag === "StatusCodeError" && error.reason.response.status === 429) return succeed$2(seconds(fromUndefinedOr(error.reason.response.headers["retry-after"]).pipe(flatMap$5(parse$1), getOrElse$1(() => 5))));
|
|
61843
61845
|
return succeed$2(seconds(1));
|
|
61844
61846
|
}));
|
|
61845
61847
|
/**
|
|
@@ -64548,6 +64550,428 @@ const layer$1 = /* @__PURE__ */ succeed$3(Path$1)({
|
|
|
64548
64550
|
toFileUrl
|
|
64549
64551
|
});
|
|
64550
64552
|
//#endregion
|
|
64553
|
+
//#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
|
|
64554
|
+
var comma = ",".charCodeAt(0);
|
|
64555
|
+
";".charCodeAt(0);
|
|
64556
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
64557
|
+
var intToChar = new Uint8Array(64);
|
|
64558
|
+
var charToInt = new Uint8Array(128);
|
|
64559
|
+
for (let i = 0; i < chars.length; i++) {
|
|
64560
|
+
const c = chars.charCodeAt(i);
|
|
64561
|
+
intToChar[i] = c;
|
|
64562
|
+
charToInt[c] = i;
|
|
64563
|
+
}
|
|
64564
|
+
function decodeInteger(reader, relative) {
|
|
64565
|
+
let value = 0;
|
|
64566
|
+
let shift = 0;
|
|
64567
|
+
let integer = 0;
|
|
64568
|
+
do {
|
|
64569
|
+
integer = charToInt[reader.next()];
|
|
64570
|
+
value |= (integer & 31) << shift;
|
|
64571
|
+
shift += 5;
|
|
64572
|
+
} while (integer & 32);
|
|
64573
|
+
const shouldNegate = value & 1;
|
|
64574
|
+
value >>>= 1;
|
|
64575
|
+
if (shouldNegate) value = -2147483648 | -value;
|
|
64576
|
+
return relative + value;
|
|
64577
|
+
}
|
|
64578
|
+
function hasMoreVlq(reader, max) {
|
|
64579
|
+
if (reader.pos >= max) return false;
|
|
64580
|
+
return reader.peek() !== comma;
|
|
64581
|
+
}
|
|
64582
|
+
var StringReader = class {
|
|
64583
|
+
constructor(buffer) {
|
|
64584
|
+
this.pos = 0;
|
|
64585
|
+
this.buffer = buffer;
|
|
64586
|
+
}
|
|
64587
|
+
next() {
|
|
64588
|
+
return this.buffer.charCodeAt(this.pos++);
|
|
64589
|
+
}
|
|
64590
|
+
peek() {
|
|
64591
|
+
return this.buffer.charCodeAt(this.pos);
|
|
64592
|
+
}
|
|
64593
|
+
indexOf(char) {
|
|
64594
|
+
const { buffer, pos } = this;
|
|
64595
|
+
const idx = buffer.indexOf(char, pos);
|
|
64596
|
+
return idx === -1 ? buffer.length : idx;
|
|
64597
|
+
}
|
|
64598
|
+
};
|
|
64599
|
+
function decode(mappings) {
|
|
64600
|
+
const { length } = mappings;
|
|
64601
|
+
const reader = new StringReader(mappings);
|
|
64602
|
+
const decoded = [];
|
|
64603
|
+
let genColumn = 0;
|
|
64604
|
+
let sourcesIndex = 0;
|
|
64605
|
+
let sourceLine = 0;
|
|
64606
|
+
let sourceColumn = 0;
|
|
64607
|
+
let namesIndex = 0;
|
|
64608
|
+
do {
|
|
64609
|
+
const semi = reader.indexOf(";");
|
|
64610
|
+
const line = [];
|
|
64611
|
+
let sorted = true;
|
|
64612
|
+
let lastCol = 0;
|
|
64613
|
+
genColumn = 0;
|
|
64614
|
+
while (reader.pos < semi) {
|
|
64615
|
+
let seg;
|
|
64616
|
+
genColumn = decodeInteger(reader, genColumn);
|
|
64617
|
+
if (genColumn < lastCol) sorted = false;
|
|
64618
|
+
lastCol = genColumn;
|
|
64619
|
+
if (hasMoreVlq(reader, semi)) {
|
|
64620
|
+
sourcesIndex = decodeInteger(reader, sourcesIndex);
|
|
64621
|
+
sourceLine = decodeInteger(reader, sourceLine);
|
|
64622
|
+
sourceColumn = decodeInteger(reader, sourceColumn);
|
|
64623
|
+
if (hasMoreVlq(reader, semi)) {
|
|
64624
|
+
namesIndex = decodeInteger(reader, namesIndex);
|
|
64625
|
+
seg = [
|
|
64626
|
+
genColumn,
|
|
64627
|
+
sourcesIndex,
|
|
64628
|
+
sourceLine,
|
|
64629
|
+
sourceColumn,
|
|
64630
|
+
namesIndex
|
|
64631
|
+
];
|
|
64632
|
+
} else seg = [
|
|
64633
|
+
genColumn,
|
|
64634
|
+
sourcesIndex,
|
|
64635
|
+
sourceLine,
|
|
64636
|
+
sourceColumn
|
|
64637
|
+
];
|
|
64638
|
+
} else seg = [genColumn];
|
|
64639
|
+
line.push(seg);
|
|
64640
|
+
reader.pos++;
|
|
64641
|
+
}
|
|
64642
|
+
if (!sorted) sort(line);
|
|
64643
|
+
decoded.push(line);
|
|
64644
|
+
reader.pos = semi + 1;
|
|
64645
|
+
} while (reader.pos <= length);
|
|
64646
|
+
return decoded;
|
|
64647
|
+
}
|
|
64648
|
+
function sort(line) {
|
|
64649
|
+
line.sort(sortComparator$1);
|
|
64650
|
+
}
|
|
64651
|
+
function sortComparator$1(a, b) {
|
|
64652
|
+
return a[0] - b[0];
|
|
64653
|
+
}
|
|
64654
|
+
//#endregion
|
|
64655
|
+
//#region ../../node_modules/.pnpm/@jridgewell+resolve-uri@3.1.2/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs
|
|
64656
|
+
const schemeRegex = /^[\w+.-]+:\/\//;
|
|
64657
|
+
/**
|
|
64658
|
+
* Matches the parts of a URL:
|
|
64659
|
+
* 1. Scheme, including ":", guaranteed.
|
|
64660
|
+
* 2. User/password, including "@", optional.
|
|
64661
|
+
* 3. Host, guaranteed.
|
|
64662
|
+
* 4. Port, including ":", optional.
|
|
64663
|
+
* 5. Path, including "/", optional.
|
|
64664
|
+
* 6. Query, including "?", optional.
|
|
64665
|
+
* 7. Hash, including "#", optional.
|
|
64666
|
+
*/
|
|
64667
|
+
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
|
|
64668
|
+
/**
|
|
64669
|
+
* File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
|
|
64670
|
+
* with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
|
|
64671
|
+
*
|
|
64672
|
+
* 1. Host, optional.
|
|
64673
|
+
* 2. Path, which may include "/", guaranteed.
|
|
64674
|
+
* 3. Query, including "?", optional.
|
|
64675
|
+
* 4. Hash, including "#", optional.
|
|
64676
|
+
*/
|
|
64677
|
+
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
|
|
64678
|
+
function isAbsoluteUrl(input) {
|
|
64679
|
+
return schemeRegex.test(input);
|
|
64680
|
+
}
|
|
64681
|
+
function isSchemeRelativeUrl(input) {
|
|
64682
|
+
return input.startsWith("//");
|
|
64683
|
+
}
|
|
64684
|
+
function isAbsolutePath(input) {
|
|
64685
|
+
return input.startsWith("/");
|
|
64686
|
+
}
|
|
64687
|
+
function isFileUrl(input) {
|
|
64688
|
+
return input.startsWith("file:");
|
|
64689
|
+
}
|
|
64690
|
+
function isRelative(input) {
|
|
64691
|
+
return /^[.?#]/.test(input);
|
|
64692
|
+
}
|
|
64693
|
+
function parseAbsoluteUrl(input) {
|
|
64694
|
+
const match = urlRegex.exec(input);
|
|
64695
|
+
return makeUrl(match[1], match[2] || "", match[3], match[4] || "", match[5] || "/", match[6] || "", match[7] || "");
|
|
64696
|
+
}
|
|
64697
|
+
function parseFileUrl(input) {
|
|
64698
|
+
const match = fileRegex.exec(input);
|
|
64699
|
+
const path = match[2];
|
|
64700
|
+
return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path) ? path : "/" + path, match[3] || "", match[4] || "");
|
|
64701
|
+
}
|
|
64702
|
+
function makeUrl(scheme, user, host, port, path, query, hash) {
|
|
64703
|
+
return {
|
|
64704
|
+
scheme,
|
|
64705
|
+
user,
|
|
64706
|
+
host,
|
|
64707
|
+
port,
|
|
64708
|
+
path,
|
|
64709
|
+
query,
|
|
64710
|
+
hash,
|
|
64711
|
+
type: 7
|
|
64712
|
+
};
|
|
64713
|
+
}
|
|
64714
|
+
function parseUrl(input) {
|
|
64715
|
+
if (isSchemeRelativeUrl(input)) {
|
|
64716
|
+
const url = parseAbsoluteUrl("http:" + input);
|
|
64717
|
+
url.scheme = "";
|
|
64718
|
+
url.type = 6;
|
|
64719
|
+
return url;
|
|
64720
|
+
}
|
|
64721
|
+
if (isAbsolutePath(input)) {
|
|
64722
|
+
const url = parseAbsoluteUrl("http://foo.com" + input);
|
|
64723
|
+
url.scheme = "";
|
|
64724
|
+
url.host = "";
|
|
64725
|
+
url.type = 5;
|
|
64726
|
+
return url;
|
|
64727
|
+
}
|
|
64728
|
+
if (isFileUrl(input)) return parseFileUrl(input);
|
|
64729
|
+
if (isAbsoluteUrl(input)) return parseAbsoluteUrl(input);
|
|
64730
|
+
const url = parseAbsoluteUrl("http://foo.com/" + input);
|
|
64731
|
+
url.scheme = "";
|
|
64732
|
+
url.host = "";
|
|
64733
|
+
url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
|
|
64734
|
+
return url;
|
|
64735
|
+
}
|
|
64736
|
+
function stripPathFilename(path) {
|
|
64737
|
+
if (path.endsWith("/..")) return path;
|
|
64738
|
+
const index = path.lastIndexOf("/");
|
|
64739
|
+
return path.slice(0, index + 1);
|
|
64740
|
+
}
|
|
64741
|
+
function mergePaths(url, base) {
|
|
64742
|
+
normalizePath(base, base.type);
|
|
64743
|
+
if (url.path === "/") url.path = base.path;
|
|
64744
|
+
else url.path = stripPathFilename(base.path) + url.path;
|
|
64745
|
+
}
|
|
64746
|
+
/**
|
|
64747
|
+
* The path can have empty directories "//", unneeded parents "foo/..", or current directory
|
|
64748
|
+
* "foo/.". We need to normalize to a standard representation.
|
|
64749
|
+
*/
|
|
64750
|
+
function normalizePath(url, type) {
|
|
64751
|
+
const rel = type <= 4;
|
|
64752
|
+
const pieces = url.path.split("/");
|
|
64753
|
+
let pointer = 1;
|
|
64754
|
+
let positive = 0;
|
|
64755
|
+
let addTrailingSlash = false;
|
|
64756
|
+
for (let i = 1; i < pieces.length; i++) {
|
|
64757
|
+
const piece = pieces[i];
|
|
64758
|
+
if (!piece) {
|
|
64759
|
+
addTrailingSlash = true;
|
|
64760
|
+
continue;
|
|
64761
|
+
}
|
|
64762
|
+
addTrailingSlash = false;
|
|
64763
|
+
if (piece === ".") continue;
|
|
64764
|
+
if (piece === "..") {
|
|
64765
|
+
if (positive) {
|
|
64766
|
+
addTrailingSlash = true;
|
|
64767
|
+
positive--;
|
|
64768
|
+
pointer--;
|
|
64769
|
+
} else if (rel) pieces[pointer++] = piece;
|
|
64770
|
+
continue;
|
|
64771
|
+
}
|
|
64772
|
+
pieces[pointer++] = piece;
|
|
64773
|
+
positive++;
|
|
64774
|
+
}
|
|
64775
|
+
let path = "";
|
|
64776
|
+
for (let i = 1; i < pointer; i++) path += "/" + pieces[i];
|
|
64777
|
+
if (!path || addTrailingSlash && !path.endsWith("/..")) path += "/";
|
|
64778
|
+
url.path = path;
|
|
64779
|
+
}
|
|
64780
|
+
/**
|
|
64781
|
+
* Attempts to resolve `input` URL/path relative to `base`.
|
|
64782
|
+
*/
|
|
64783
|
+
function resolve(input, base) {
|
|
64784
|
+
if (!input && !base) return "";
|
|
64785
|
+
const url = parseUrl(input);
|
|
64786
|
+
let inputType = url.type;
|
|
64787
|
+
if (base && inputType !== 7) {
|
|
64788
|
+
const baseUrl = parseUrl(base);
|
|
64789
|
+
const baseType = baseUrl.type;
|
|
64790
|
+
switch (inputType) {
|
|
64791
|
+
case 1: url.hash = baseUrl.hash;
|
|
64792
|
+
case 2: url.query = baseUrl.query;
|
|
64793
|
+
case 3:
|
|
64794
|
+
case 4: mergePaths(url, baseUrl);
|
|
64795
|
+
case 5:
|
|
64796
|
+
url.user = baseUrl.user;
|
|
64797
|
+
url.host = baseUrl.host;
|
|
64798
|
+
url.port = baseUrl.port;
|
|
64799
|
+
case 6: url.scheme = baseUrl.scheme;
|
|
64800
|
+
}
|
|
64801
|
+
if (baseType > inputType) inputType = baseType;
|
|
64802
|
+
}
|
|
64803
|
+
normalizePath(url, inputType);
|
|
64804
|
+
const queryHash = url.query + url.hash;
|
|
64805
|
+
switch (inputType) {
|
|
64806
|
+
case 2:
|
|
64807
|
+
case 3: return queryHash;
|
|
64808
|
+
case 4: {
|
|
64809
|
+
const path = url.path.slice(1);
|
|
64810
|
+
if (!path) return queryHash || ".";
|
|
64811
|
+
if (isRelative(base || input) && !isRelative(path)) return "./" + path + queryHash;
|
|
64812
|
+
return path + queryHash;
|
|
64813
|
+
}
|
|
64814
|
+
case 5: return url.path + queryHash;
|
|
64815
|
+
default: return url.scheme + "//" + url.user + url.host + url.port + url.path + queryHash;
|
|
64816
|
+
}
|
|
64817
|
+
}
|
|
64818
|
+
//#endregion
|
|
64819
|
+
//#region ../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.31/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs
|
|
64820
|
+
function stripFilename(path) {
|
|
64821
|
+
if (!path) return "";
|
|
64822
|
+
const index = path.lastIndexOf("/");
|
|
64823
|
+
return path.slice(0, index + 1);
|
|
64824
|
+
}
|
|
64825
|
+
function resolver(mapUrl, sourceRoot) {
|
|
64826
|
+
const from = stripFilename(mapUrl);
|
|
64827
|
+
const prefix = sourceRoot ? sourceRoot + "/" : "";
|
|
64828
|
+
return (source) => resolve(prefix + (source || ""), from);
|
|
64829
|
+
}
|
|
64830
|
+
var COLUMN = 0;
|
|
64831
|
+
var SOURCES_INDEX = 1;
|
|
64832
|
+
var SOURCE_LINE = 2;
|
|
64833
|
+
var SOURCE_COLUMN = 3;
|
|
64834
|
+
var NAMES_INDEX = 4;
|
|
64835
|
+
function maybeSort(mappings, owned) {
|
|
64836
|
+
const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
|
|
64837
|
+
if (unsortedIndex === mappings.length) return mappings;
|
|
64838
|
+
if (!owned) mappings = mappings.slice();
|
|
64839
|
+
for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) mappings[i] = sortSegments(mappings[i], owned);
|
|
64840
|
+
return mappings;
|
|
64841
|
+
}
|
|
64842
|
+
function nextUnsortedSegmentLine(mappings, start) {
|
|
64843
|
+
for (let i = start; i < mappings.length; i++) if (!isSorted(mappings[i])) return i;
|
|
64844
|
+
return mappings.length;
|
|
64845
|
+
}
|
|
64846
|
+
function isSorted(line) {
|
|
64847
|
+
for (let j = 1; j < line.length; j++) if (line[j][COLUMN] < line[j - 1][COLUMN]) return false;
|
|
64848
|
+
return true;
|
|
64849
|
+
}
|
|
64850
|
+
function sortSegments(line, owned) {
|
|
64851
|
+
if (!owned) line = line.slice();
|
|
64852
|
+
return line.sort(sortComparator);
|
|
64853
|
+
}
|
|
64854
|
+
function sortComparator(a, b) {
|
|
64855
|
+
return a[COLUMN] - b[COLUMN];
|
|
64856
|
+
}
|
|
64857
|
+
var found = false;
|
|
64858
|
+
function binarySearch(haystack, needle, low, high) {
|
|
64859
|
+
while (low <= high) {
|
|
64860
|
+
const mid = low + (high - low >> 1);
|
|
64861
|
+
const cmp = haystack[mid][COLUMN] - needle;
|
|
64862
|
+
if (cmp === 0) {
|
|
64863
|
+
found = true;
|
|
64864
|
+
return mid;
|
|
64865
|
+
}
|
|
64866
|
+
if (cmp < 0) low = mid + 1;
|
|
64867
|
+
else high = mid - 1;
|
|
64868
|
+
}
|
|
64869
|
+
found = false;
|
|
64870
|
+
return low - 1;
|
|
64871
|
+
}
|
|
64872
|
+
function upperBound(haystack, needle, index) {
|
|
64873
|
+
for (let i = index + 1; i < haystack.length; index = i++) if (haystack[i][COLUMN] !== needle) break;
|
|
64874
|
+
return index;
|
|
64875
|
+
}
|
|
64876
|
+
function lowerBound(haystack, needle, index) {
|
|
64877
|
+
for (let i = index - 1; i >= 0; index = i--) if (haystack[i][COLUMN] !== needle) break;
|
|
64878
|
+
return index;
|
|
64879
|
+
}
|
|
64880
|
+
function memoizedState() {
|
|
64881
|
+
return {
|
|
64882
|
+
lastKey: -1,
|
|
64883
|
+
lastNeedle: -1,
|
|
64884
|
+
lastIndex: -1
|
|
64885
|
+
};
|
|
64886
|
+
}
|
|
64887
|
+
function memoizedBinarySearch(haystack, needle, state, key) {
|
|
64888
|
+
const { lastKey, lastNeedle, lastIndex } = state;
|
|
64889
|
+
let low = 0;
|
|
64890
|
+
let high = haystack.length - 1;
|
|
64891
|
+
if (key === lastKey) {
|
|
64892
|
+
if (needle === lastNeedle) {
|
|
64893
|
+
found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
|
|
64894
|
+
return lastIndex;
|
|
64895
|
+
}
|
|
64896
|
+
if (needle >= lastNeedle) low = lastIndex === -1 ? 0 : lastIndex;
|
|
64897
|
+
else high = lastIndex;
|
|
64898
|
+
}
|
|
64899
|
+
state.lastKey = key;
|
|
64900
|
+
state.lastNeedle = needle;
|
|
64901
|
+
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
64902
|
+
}
|
|
64903
|
+
function parse(map) {
|
|
64904
|
+
return typeof map === "string" ? JSON.parse(map) : map;
|
|
64905
|
+
}
|
|
64906
|
+
var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
|
|
64907
|
+
var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
|
|
64908
|
+
var TraceMap = class {
|
|
64909
|
+
constructor(map, mapUrl) {
|
|
64910
|
+
const isString = typeof map === "string";
|
|
64911
|
+
if (!isString && map._decodedMemo) return map;
|
|
64912
|
+
const parsed = parse(map);
|
|
64913
|
+
const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
|
|
64914
|
+
this.version = version;
|
|
64915
|
+
this.file = file;
|
|
64916
|
+
this.names = names || [];
|
|
64917
|
+
this.sourceRoot = sourceRoot;
|
|
64918
|
+
this.sources = sources;
|
|
64919
|
+
this.sourcesContent = sourcesContent;
|
|
64920
|
+
this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
|
|
64921
|
+
const resolve = resolver(mapUrl, sourceRoot);
|
|
64922
|
+
this.resolvedSources = sources.map(resolve);
|
|
64923
|
+
const { mappings } = parsed;
|
|
64924
|
+
if (typeof mappings === "string") {
|
|
64925
|
+
this._encoded = mappings;
|
|
64926
|
+
this._decoded = void 0;
|
|
64927
|
+
} else if (Array.isArray(mappings)) {
|
|
64928
|
+
this._encoded = void 0;
|
|
64929
|
+
this._decoded = maybeSort(mappings, isString);
|
|
64930
|
+
} else if (parsed.sections) throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
|
|
64931
|
+
else throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
|
|
64932
|
+
this._decodedMemo = memoizedState();
|
|
64933
|
+
this._bySources = void 0;
|
|
64934
|
+
this._bySourceMemos = void 0;
|
|
64935
|
+
}
|
|
64936
|
+
};
|
|
64937
|
+
function cast(map) {
|
|
64938
|
+
return map;
|
|
64939
|
+
}
|
|
64940
|
+
function decodedMappings(map) {
|
|
64941
|
+
var _a;
|
|
64942
|
+
return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
|
|
64943
|
+
}
|
|
64944
|
+
function originalPositionFor(map, needle) {
|
|
64945
|
+
let { line, column, bias } = needle;
|
|
64946
|
+
line--;
|
|
64947
|
+
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
64948
|
+
if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
|
|
64949
|
+
const decoded = decodedMappings(map);
|
|
64950
|
+
if (line >= decoded.length) return OMapping(null, null, null, null);
|
|
64951
|
+
const segments = decoded[line];
|
|
64952
|
+
const index = traceSegmentInternal(segments, cast(map)._decodedMemo, line, column, bias || 1);
|
|
64953
|
+
if (index === -1) return OMapping(null, null, null, null);
|
|
64954
|
+
const segment = segments[index];
|
|
64955
|
+
if (segment.length === 1) return OMapping(null, null, null, null);
|
|
64956
|
+
const { names, resolvedSources } = map;
|
|
64957
|
+
return OMapping(resolvedSources[segment[SOURCES_INDEX]], segment[SOURCE_LINE] + 1, segment[SOURCE_COLUMN], segment.length === 5 ? names[segment[NAMES_INDEX]] : null);
|
|
64958
|
+
}
|
|
64959
|
+
function OMapping(source, line, column, name) {
|
|
64960
|
+
return {
|
|
64961
|
+
source,
|
|
64962
|
+
line,
|
|
64963
|
+
column,
|
|
64964
|
+
name
|
|
64965
|
+
};
|
|
64966
|
+
}
|
|
64967
|
+
function traceSegmentInternal(segments, memo, line, column, bias) {
|
|
64968
|
+
let index = memoizedBinarySearch(segments, column, memo, line);
|
|
64969
|
+
if (found) index = (bias === -1 ? upperBound : lowerBound)(segments, column, index);
|
|
64970
|
+
else if (bias === -1) index++;
|
|
64971
|
+
if (index === -1 || index === segments.length) return -1;
|
|
64972
|
+
return index;
|
|
64973
|
+
}
|
|
64974
|
+
//#endregion
|
|
64551
64975
|
//#region ../core/dist/index.js
|
|
64552
64976
|
var __create = Object.create;
|
|
64553
64977
|
var __defProp = Object.defineProperty;
|
|
@@ -64616,7 +65040,8 @@ var AmbiguousProjectError = class extends Error {
|
|
|
64616
65040
|
}
|
|
64617
65041
|
};
|
|
64618
65042
|
const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
|
|
64619
|
-
const
|
|
65043
|
+
const HTML_FILE_PATTERN = /\.html$/i;
|
|
65044
|
+
const SOURCE_FILE_PATTERN = /\.(?:astro|tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
|
|
64620
65045
|
const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
|
|
64621
65046
|
const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
|
|
64622
65047
|
const MINIFIED_SNIFF_BYTES = 65536;
|
|
@@ -64994,7 +65419,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
64994
65419
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
64995
65420
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
64996
65421
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
64997
|
-
const CORE_PACKAGE_VERSION = "0.9.
|
|
65422
|
+
const CORE_PACKAGE_VERSION = "0.9.2";
|
|
64998
65423
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
64999
65424
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
65000
65425
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -65238,8 +65663,13 @@ const findMonorepoRoot = (startDirectory) => {
|
|
|
65238
65663
|
* byte-equivalent copy.
|
|
65239
65664
|
*/
|
|
65240
65665
|
const isProjectBoundary = (directory) => NFS.existsSync(Path.join(directory, ".git")) || isMonorepoRoot(directory);
|
|
65666
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
65667
|
+
let currentExpression = expression;
|
|
65668
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
65669
|
+
return currentExpression;
|
|
65670
|
+
};
|
|
65241
65671
|
const TSCONFIG_FILENAME = "tsconfig.json";
|
|
65242
|
-
const
|
|
65672
|
+
const isLocalModuleSpecifier = (moduleSpecifier) => moduleSpecifier === "." || moduleSpecifier === ".." || moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../") || Path.isAbsolute(moduleSpecifier);
|
|
65243
65673
|
const ensureJsonExtension = (filePath) => Path.extname(filePath) === "" ? `${filePath}.json` : filePath;
|
|
65244
65674
|
const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
65245
65675
|
const requireFromConfig = createRequire(Path.join(fromConfigDirectory, "tsconfig.json"));
|
|
@@ -65256,7 +65686,12 @@ const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
|
65256
65686
|
return null;
|
|
65257
65687
|
};
|
|
65258
65688
|
const resolveExtendsPath = (extendsValue, fromConfigDirectory) => {
|
|
65259
|
-
if (
|
|
65689
|
+
if (isLocalModuleSpecifier(extendsValue)) {
|
|
65690
|
+
const resolvedPath = Path.resolve(fromConfigDirectory, extendsValue);
|
|
65691
|
+
if (isFile(resolvedPath)) return resolvedPath;
|
|
65692
|
+
const directoryConfigPath = Path.join(resolvedPath, TSCONFIG_FILENAME);
|
|
65693
|
+
return isFile(directoryConfigPath) ? directoryConfigPath : ensureJsonExtension(resolvedPath);
|
|
65694
|
+
}
|
|
65260
65695
|
return resolvePackageExtendsPath(extendsValue, fromConfigDirectory);
|
|
65261
65696
|
};
|
|
65262
65697
|
const normalizeCompilerOptions = (compilerOptions) => {
|
|
@@ -65363,6 +65798,7 @@ const FRAMEWORK_PACKAGES = {
|
|
|
65363
65798
|
"@tanstack/react-start": "tanstack-start",
|
|
65364
65799
|
"@remix-run/react": "remix",
|
|
65365
65800
|
gatsby: "gatsby",
|
|
65801
|
+
astro: "astro",
|
|
65366
65802
|
vite: "vite",
|
|
65367
65803
|
"react-scripts": "cra",
|
|
65368
65804
|
expo: "expo",
|
|
@@ -65450,6 +65886,15 @@ const REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS = [
|
|
|
65450
65886
|
".cts",
|
|
65451
65887
|
".json"
|
|
65452
65888
|
];
|
|
65889
|
+
const REACT_COMPILER_CONFIG_RESOLVER = new ResolverFactory({
|
|
65890
|
+
conditionNames: [
|
|
65891
|
+
"import",
|
|
65892
|
+
"require",
|
|
65893
|
+
"node",
|
|
65894
|
+
"default"
|
|
65895
|
+
],
|
|
65896
|
+
extensions: REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS
|
|
65897
|
+
});
|
|
65453
65898
|
const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
|
|
65454
65899
|
const hasCompilerPackage = (packageJson, compilerPackages) => {
|
|
65455
65900
|
const allDependencies = {
|
|
@@ -65473,6 +65918,18 @@ const hasCompilerPackageInAncestors = (directory, compilerPackages) => {
|
|
|
65473
65918
|
return false;
|
|
65474
65919
|
};
|
|
65475
65920
|
const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
65921
|
+
if (!isLocalModuleSpecifier(moduleSpecifier)) {
|
|
65922
|
+
try {
|
|
65923
|
+
const resolvedPath = REACT_COMPILER_CONFIG_RESOLVER.resolveFileSync(fromFilePath, moduleSpecifier).path;
|
|
65924
|
+
if (resolvedPath && isFile(resolvedPath)) return resolvedPath;
|
|
65925
|
+
} catch {}
|
|
65926
|
+
try {
|
|
65927
|
+
const resolvedPath = createRequire(fromFilePath).resolve(moduleSpecifier);
|
|
65928
|
+
return isFile(resolvedPath) ? resolvedPath : null;
|
|
65929
|
+
} catch {
|
|
65930
|
+
return null;
|
|
65931
|
+
}
|
|
65932
|
+
}
|
|
65476
65933
|
const unresolvedPath = Path.resolve(Path.dirname(fromFilePath), moduleSpecifier);
|
|
65477
65934
|
const extension = Path.extname(unresolvedPath);
|
|
65478
65935
|
return (extension ? [unresolvedPath, ...REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS.map((sourceExtension) => `${unresolvedPath.slice(0, -extension.length)}${sourceExtension}`)] : [
|
|
@@ -65482,10 +65939,10 @@ const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
|
|
|
65482
65939
|
]).find(isFile) ?? null;
|
|
65483
65940
|
};
|
|
65484
65941
|
const parseConfigSourceFile = (filePath, content) => filePath.endsWith(".json") || Path.basename(filePath) === ".babelrc" ? ts.parseJsonText(filePath, content) : ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
65485
|
-
const getStaticPropertyName$
|
|
65942
|
+
const getStaticPropertyName$2 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
|
|
65486
65943
|
const isCommonJsConfigExportAssignment = (node, sourceFile) => ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && (node.left.getText(sourceFile) === "module.exports" || node.left.getText(sourceFile) === "exports.default");
|
|
65487
65944
|
const hasExportModifier = (node) => ts.canHaveModifiers(node) && Boolean(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
|
|
65488
|
-
const getRequireModuleSpecifier = (expression) => {
|
|
65945
|
+
const getRequireModuleSpecifier$1 = (expression) => {
|
|
65489
65946
|
if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "require" || expression.arguments.length !== 1) return null;
|
|
65490
65947
|
const moduleSpecifier = expression.arguments[0];
|
|
65491
65948
|
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
@@ -65498,7 +65955,7 @@ const hasTopLevelValueBinding = (sourceFile, bindingName) => sourceFile.statemen
|
|
|
65498
65955
|
const namedBindings = importClause?.namedBindings;
|
|
65499
65956
|
return namedBindings ? ts.isNamespaceImport(namedBindings) ? namedBindings.name.text === bindingName : namedBindings.elements.some((element) => element.name.text === bindingName) : false;
|
|
65500
65957
|
}
|
|
65501
|
-
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) =>
|
|
65958
|
+
if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContainsIdentifier(declaration.name, bindingName));
|
|
65502
65959
|
return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === bindingName;
|
|
65503
65960
|
});
|
|
65504
65961
|
const getImportBinding = (sourceFile, bindingName) => {
|
|
@@ -65529,24 +65986,24 @@ const getImportBinding = (sourceFile, bindingName) => {
|
|
|
65529
65986
|
for (const declaration of statement.declarationList.declarations) {
|
|
65530
65987
|
if (!declaration.initializer) continue;
|
|
65531
65988
|
if (ts.isIdentifier(declaration.name) && declaration.name.text === bindingName) {
|
|
65532
|
-
const directModuleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
65989
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
65533
65990
|
if (directModuleSpecifier) return {
|
|
65534
65991
|
moduleSpecifier: directModuleSpecifier,
|
|
65535
65992
|
exportName: "default",
|
|
65536
65993
|
isNamespace: true
|
|
65537
65994
|
};
|
|
65538
|
-
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier(declaration.initializer.expression) !== null) return {
|
|
65539
|
-
moduleSpecifier: getRequireModuleSpecifier(declaration.initializer.expression) ?? "",
|
|
65995
|
+
if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier$1(declaration.initializer.expression) !== null) return {
|
|
65996
|
+
moduleSpecifier: getRequireModuleSpecifier$1(declaration.initializer.expression) ?? "",
|
|
65540
65997
|
exportName: declaration.initializer.name.text,
|
|
65541
65998
|
isNamespace: false
|
|
65542
65999
|
};
|
|
65543
66000
|
}
|
|
65544
66001
|
if (!ts.isObjectBindingPattern(declaration.name)) continue;
|
|
65545
66002
|
const bindingElement = declaration.name.elements.find((element) => ts.isIdentifier(element.name) && element.name.text === bindingName);
|
|
65546
|
-
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
66003
|
+
const moduleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
|
|
65547
66004
|
if (bindingElement && moduleSpecifier) return {
|
|
65548
66005
|
moduleSpecifier,
|
|
65549
|
-
exportName: bindingElement.propertyName ? getStaticPropertyName$
|
|
66006
|
+
exportName: bindingElement.propertyName ? getStaticPropertyName$2(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
|
|
65550
66007
|
isNamespace: false
|
|
65551
66008
|
};
|
|
65552
66009
|
}
|
|
@@ -65563,10 +66020,16 @@ const getTopLevelBinding = (sourceFile, bindingName) => {
|
|
|
65563
66020
|
}
|
|
65564
66021
|
return null;
|
|
65565
66022
|
};
|
|
65566
|
-
const getFunctionLocalBindings = (functionNode, argumentsList) => {
|
|
66023
|
+
const getFunctionLocalBindings = (functionNode, argumentsList, argumentAnalysis, functionAnalysis) => {
|
|
65567
66024
|
const localBindings = /* @__PURE__ */ new Map();
|
|
65568
66025
|
functionNode.parameters.forEach((parameter, parameterIndex) => {
|
|
65569
|
-
if (ts.isIdentifier(parameter.name))
|
|
66026
|
+
if (ts.isIdentifier(parameter.name)) {
|
|
66027
|
+
const argument = argumentsList[parameterIndex];
|
|
66028
|
+
localBindings.set(parameter.name.text, {
|
|
66029
|
+
expression: argument ?? parameter.initializer ?? null,
|
|
66030
|
+
analysis: argument ? argumentAnalysis : functionAnalysis
|
|
66031
|
+
});
|
|
66032
|
+
}
|
|
65570
66033
|
});
|
|
65571
66034
|
return localBindings;
|
|
65572
66035
|
};
|
|
@@ -65599,6 +66062,48 @@ const getScopedConfigBinding = (identifier) => {
|
|
|
65599
66062
|
};
|
|
65600
66063
|
};
|
|
65601
66064
|
const isCompilerTransformModule = (moduleSpecifier, exportName) => moduleSpecifier === "babel-plugin-react-compiler" && exportName === "default" || moduleSpecifier === "@vitejs/plugin-react" && exportName === "reactCompilerPreset";
|
|
66065
|
+
const NODE_MODULE_SPECIFIERS = new Set(["module", "node:module"]);
|
|
66066
|
+
const isConstantVariableInitializer = (node) => ts.isExpression(node) && ts.isVariableDeclaration(node.parent) && ts.isVariableDeclarationList(node.parent.parent) && Boolean(node.parent.parent.flags & ts.NodeFlags.Const);
|
|
66067
|
+
const isNodeCreateRequireCall = (node, analysis) => {
|
|
66068
|
+
if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isTypeAssertionExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isAwaitExpression(node)) return isNodeCreateRequireCall(node.expression, analysis);
|
|
66069
|
+
if (!ts.isCallExpression(node)) return false;
|
|
66070
|
+
const target = node.expression;
|
|
66071
|
+
if (ts.isIdentifier(target)) {
|
|
66072
|
+
if (analysis.localBindings.has(target.text) || getScopedConfigBinding(target).wasFound) return false;
|
|
66073
|
+
const importBinding = getImportBinding(analysis.sourceFile, target.text);
|
|
66074
|
+
return Boolean(importBinding && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier) && importBinding.exportName === "createRequire");
|
|
66075
|
+
}
|
|
66076
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return false;
|
|
66077
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "createRequire") return false;
|
|
66078
|
+
const createRequireReceiver = target.expression;
|
|
66079
|
+
if (ts.isCallExpression(createRequireReceiver)) {
|
|
66080
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(createRequireReceiver);
|
|
66081
|
+
if (requiredModuleSpecifier === null || !NODE_MODULE_SPECIFIERS.has(requiredModuleSpecifier) || !ts.isIdentifier(createRequireReceiver.expression)) return false;
|
|
66082
|
+
const requireIdentifier = createRequireReceiver.expression;
|
|
66083
|
+
return !analysis.localBindings.has(requireIdentifier.text) && !getScopedConfigBinding(requireIdentifier).wasFound && !hasTopLevelValueBinding(analysis.sourceFile, requireIdentifier.text);
|
|
66084
|
+
}
|
|
66085
|
+
if (!ts.isIdentifier(createRequireReceiver)) return false;
|
|
66086
|
+
if (analysis.localBindings.has(createRequireReceiver.text) || getScopedConfigBinding(createRequireReceiver).wasFound) return false;
|
|
66087
|
+
const importBinding = getImportBinding(analysis.sourceFile, createRequireReceiver.text);
|
|
66088
|
+
return Boolean(importBinding?.isNamespace && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier));
|
|
66089
|
+
};
|
|
66090
|
+
const getNodeRequireResolveModuleSpecifier = (callExpression, analysis) => {
|
|
66091
|
+
const [moduleSpecifierNode] = callExpression.arguments;
|
|
66092
|
+
if (!moduleSpecifierNode || !ts.isStringLiteralLike(moduleSpecifierNode)) return null;
|
|
66093
|
+
const target = callExpression.expression;
|
|
66094
|
+
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
66095
|
+
if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "resolve") return null;
|
|
66096
|
+
if (isNodeCreateRequireCall(target.expression, analysis)) return moduleSpecifierNode.text;
|
|
66097
|
+
if (!ts.isIdentifier(target.expression)) return null;
|
|
66098
|
+
const resolverIdentifier = target.expression;
|
|
66099
|
+
if (analysis.localBindings.has(resolverIdentifier.text)) return null;
|
|
66100
|
+
const scopedBinding = getScopedConfigBinding(resolverIdentifier);
|
|
66101
|
+
const topLevelBinding = scopedBinding.wasFound ? null : getTopLevelBinding(analysis.sourceFile, resolverIdentifier.text);
|
|
66102
|
+
const resolverInitializer = scopedBinding.wasFound ? scopedBinding.initializer : topLevelBinding;
|
|
66103
|
+
if (resolverInitializer === null && !scopedBinding.wasFound && resolverIdentifier.text === "require" && !hasTopLevelValueBinding(analysis.sourceFile, resolverIdentifier.text) && getImportBinding(analysis.sourceFile, resolverIdentifier.text) === null) return moduleSpecifierNode.text;
|
|
66104
|
+
if (!resolverInitializer || !isConstantVariableInitializer(resolverInitializer) || !isNodeCreateRequireCall(resolverInitializer, analysis)) return null;
|
|
66105
|
+
return moduleSpecifierNode.text;
|
|
66106
|
+
};
|
|
65602
66107
|
const getAssignedPropertyInitializer = (identifier, propertyName) => {
|
|
65603
66108
|
let bindingScope = null;
|
|
65604
66109
|
let currentNode = identifier;
|
|
@@ -65641,9 +66146,11 @@ const getAssignedPropertyInitializer = (identifier, propertyName) => {
|
|
|
65641
66146
|
initializer: assignedInitializer
|
|
65642
66147
|
};
|
|
65643
66148
|
};
|
|
65644
|
-
const getStaticConfigValueState = (expression, analysis) => {
|
|
65645
|
-
|
|
65646
|
-
|
|
66149
|
+
const getStaticConfigValueState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
|
|
66150
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
66151
|
+
if (visitedExpressions.has(unwrappedExpression)) return null;
|
|
66152
|
+
const nextVisitedExpressions = new Set(visitedExpressions);
|
|
66153
|
+
nextVisitedExpressions.add(unwrappedExpression);
|
|
65647
66154
|
if (unwrappedExpression.kind === ts.SyntaxKind.NullKeyword || ts.isIdentifier(unwrappedExpression) && unwrappedExpression.text === "undefined") return {
|
|
65648
66155
|
isNullish: true,
|
|
65649
66156
|
isTruthy: false
|
|
@@ -65658,32 +66165,32 @@ const getStaticConfigValueState = (expression, analysis) => {
|
|
|
65658
66165
|
};
|
|
65659
66166
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
65660
66167
|
if (analysis.localBindings.has(unwrappedExpression.text)) {
|
|
65661
|
-
const
|
|
65662
|
-
return
|
|
66168
|
+
const localReference = analysis.localBindings.get(unwrappedExpression.text);
|
|
66169
|
+
return localReference?.expression ? getStaticConfigValueState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
|
|
65663
66170
|
}
|
|
65664
66171
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
|
|
65665
|
-
return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis) : null;
|
|
66172
|
+
return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis, nextVisitedExpressions) : null;
|
|
65666
66173
|
}
|
|
65667
66174
|
if (ts.isConditionalExpression(unwrappedExpression)) {
|
|
65668
|
-
const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis);
|
|
65669
|
-
if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis);
|
|
65670
|
-
const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis);
|
|
65671
|
-
const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis);
|
|
66175
|
+
const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis, nextVisitedExpressions);
|
|
66176
|
+
if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
|
|
66177
|
+
const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis, nextVisitedExpressions);
|
|
66178
|
+
const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
|
|
65672
66179
|
return whenTrueState !== null && whenFalseState !== null && whenTrueState.isNullish === whenFalseState.isNullish && whenTrueState.isTruthy === whenFalseState.isTruthy ? whenTrueState : null;
|
|
65673
66180
|
}
|
|
65674
66181
|
if (ts.isBinaryExpression(unwrappedExpression)) {
|
|
65675
|
-
const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis);
|
|
66182
|
+
const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis, nextVisitedExpressions);
|
|
65676
66183
|
if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
65677
66184
|
if (leftState === null) return null;
|
|
65678
|
-
return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
|
|
66185
|
+
return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
|
|
65679
66186
|
}
|
|
65680
66187
|
if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
|
|
65681
66188
|
if (leftState === null) return null;
|
|
65682
|
-
return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis);
|
|
66189
|
+
return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions);
|
|
65683
66190
|
}
|
|
65684
66191
|
if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) {
|
|
65685
66192
|
if (leftState === null) return null;
|
|
65686
|
-
return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
|
|
66193
|
+
return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
|
|
65687
66194
|
}
|
|
65688
66195
|
}
|
|
65689
66196
|
return null;
|
|
@@ -65692,25 +66199,27 @@ const isStaticallyDisabledConfigExpression = (expression, analysis) => getStatic
|
|
|
65692
66199
|
const isStaticallyTruthyConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isTruthy === true;
|
|
65693
66200
|
const isStaticallyNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === true;
|
|
65694
66201
|
const isStaticallyNonNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === false;
|
|
65695
|
-
const getReactCompilerFlagState = (expression, analysis) => {
|
|
65696
|
-
|
|
65697
|
-
|
|
66202
|
+
const getReactCompilerFlagState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
|
|
66203
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
66204
|
+
if (visitedExpressions.has(unwrappedExpression)) return null;
|
|
66205
|
+
const nextVisitedExpressions = new Set(visitedExpressions);
|
|
66206
|
+
nextVisitedExpressions.add(unwrappedExpression);
|
|
65698
66207
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
65699
66208
|
const assignedBinding = getAssignedPropertyInitializer(unwrappedExpression, "reactCompiler");
|
|
65700
66209
|
if (assignedBinding.wasFound && assignedBinding.initializer) return { isEnabled: !isStaticallyDisabledConfigExpression(assignedBinding.initializer, analysis) };
|
|
65701
66210
|
if (analysis.localBindings.has(unwrappedExpression.text)) {
|
|
65702
|
-
const
|
|
65703
|
-
return
|
|
66211
|
+
const localReference = analysis.localBindings.get(unwrappedExpression.text);
|
|
66212
|
+
return localReference?.expression ? getReactCompilerFlagState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
|
|
65704
66213
|
}
|
|
65705
66214
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
|
|
65706
|
-
return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis) : null;
|
|
66215
|
+
return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis, nextVisitedExpressions) : null;
|
|
65707
66216
|
}
|
|
65708
66217
|
if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
|
|
65709
66218
|
for (const property of [...unwrappedExpression.properties].reverse()) {
|
|
65710
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
66219
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
|
|
65711
66220
|
if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
|
|
65712
66221
|
if (ts.isSpreadAssignment(property)) {
|
|
65713
|
-
const spreadState = getReactCompilerFlagState(property.expression, analysis);
|
|
66222
|
+
const spreadState = getReactCompilerFlagState(property.expression, analysis, nextVisitedExpressions);
|
|
65714
66223
|
if (spreadState) return spreadState;
|
|
65715
66224
|
}
|
|
65716
66225
|
}
|
|
@@ -65723,8 +66232,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
65723
66232
|
visitedExpressions.add(resolvedExpression);
|
|
65724
66233
|
if (ts.isIdentifier(resolvedExpression)) {
|
|
65725
66234
|
if (analysis.localBindings.has(resolvedExpression.text)) {
|
|
65726
|
-
const
|
|
65727
|
-
return
|
|
66235
|
+
const localReference = analysis.localBindings.get(resolvedExpression.text);
|
|
66236
|
+
return localReference?.expression ? getSelectedObjectProperty(localReference.expression, propertyName, localReference.analysis, visitedExpressions) : null;
|
|
65728
66237
|
}
|
|
65729
66238
|
const scopedBinding = getScopedConfigBinding(resolvedExpression);
|
|
65730
66239
|
if (scopedBinding.wasFound) return scopedBinding.initializer ? getSelectedObjectProperty(scopedBinding.initializer, propertyName, analysis, visitedExpressions) : null;
|
|
@@ -65733,9 +66242,18 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
|
|
|
65733
66242
|
}
|
|
65734
66243
|
if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
|
|
65735
66244
|
for (const property of [...resolvedExpression.properties].reverse()) {
|
|
65736
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
65737
|
-
|
|
65738
|
-
|
|
66245
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return {
|
|
66246
|
+
node: property.initializer,
|
|
66247
|
+
analysis
|
|
66248
|
+
};
|
|
66249
|
+
if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return {
|
|
66250
|
+
node: property,
|
|
66251
|
+
analysis
|
|
66252
|
+
};
|
|
66253
|
+
if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return {
|
|
66254
|
+
node: property.name,
|
|
66255
|
+
analysis
|
|
66256
|
+
};
|
|
65739
66257
|
if (ts.isSpreadAssignment(property)) {
|
|
65740
66258
|
const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
|
|
65741
66259
|
if (spreadProperty) return spreadProperty;
|
|
@@ -65748,8 +66266,8 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
65748
66266
|
while (ts.isParenthesizedExpression(resolvedExpression) || ts.isAsExpression(resolvedExpression) || ts.isTypeAssertionExpression(resolvedExpression) || ts.isSatisfiesExpression(resolvedExpression) || ts.isNonNullExpression(resolvedExpression)) resolvedExpression = resolvedExpression.expression;
|
|
65749
66267
|
if (ts.isIdentifier(resolvedExpression)) {
|
|
65750
66268
|
if (analysis.localBindings.has(resolvedExpression.text)) {
|
|
65751
|
-
const
|
|
65752
|
-
return
|
|
66269
|
+
const localReference = analysis.localBindings.get(resolvedExpression.text);
|
|
66270
|
+
return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis) : true;
|
|
65753
66271
|
}
|
|
65754
66272
|
const scopedBinding = getScopedConfigBinding(resolvedExpression);
|
|
65755
66273
|
if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis) : true;
|
|
@@ -65765,7 +66283,7 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
|
|
|
65765
66283
|
return resolvedExpression.properties.some((property) => {
|
|
65766
66284
|
if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
|
|
65767
66285
|
if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
|
|
65768
|
-
const staticPropertyName = getStaticPropertyName$
|
|
66286
|
+
const staticPropertyName = getStaticPropertyName$2(property.name);
|
|
65769
66287
|
return staticPropertyName === null || staticPropertyName === propertyName;
|
|
65770
66288
|
}
|
|
65771
66289
|
return false;
|
|
@@ -65784,7 +66302,7 @@ const getExportedConfigNodes = (sourceFile, exportName) => {
|
|
|
65784
66302
|
continue;
|
|
65785
66303
|
}
|
|
65786
66304
|
if (ts.isExpressionStatement(statement) && isCommonJsConfigExportAssignment(statement.expression, sourceFile) && exportName !== "default" && ts.isObjectLiteralExpression(statement.expression.right)) for (const property of [...statement.expression.right.properties].reverse()) {
|
|
65787
|
-
if (ts.isPropertyAssignment(property) && getStaticPropertyName$
|
|
66305
|
+
if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === exportName) {
|
|
65788
66306
|
exportedNodes.push(property.initializer);
|
|
65789
66307
|
break;
|
|
65790
66308
|
}
|
|
@@ -65833,15 +66351,15 @@ const getReExportedConfigModules = (sourceFile, exportName) => {
|
|
|
65833
66351
|
}
|
|
65834
66352
|
return bindings;
|
|
65835
66353
|
};
|
|
65836
|
-
const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
|
|
66354
|
+
const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
|
|
65837
66355
|
if (!isFile(filePath) || importDepth > 4) return false;
|
|
65838
66356
|
const moduleVisitKey = `${filePath}:${exportName}:${allowCompilerTransform}`;
|
|
65839
66357
|
if (visitedModules.has(moduleVisitKey)) return false;
|
|
65840
66358
|
const nextVisitedModules = new Set(visitedModules);
|
|
65841
66359
|
nextVisitedModules.add(moduleVisitKey);
|
|
65842
|
-
return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList);
|
|
66360
|
+
return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
|
|
65843
66361
|
};
|
|
65844
|
-
const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
|
|
66362
|
+
const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
|
|
65845
66363
|
const analysis = {
|
|
65846
66364
|
filePath,
|
|
65847
66365
|
sourceFile,
|
|
@@ -65851,14 +66369,27 @@ const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCo
|
|
|
65851
66369
|
localBindings: /* @__PURE__ */ new Map(),
|
|
65852
66370
|
activeFunctions: /* @__PURE__ */ new Set()
|
|
65853
66371
|
};
|
|
66372
|
+
const resolvedArgumentAnalysis = argumentAnalysis ?? analysis;
|
|
65854
66373
|
const exportedConfigNodes = getExportedConfigNodes(sourceFile, exportName);
|
|
65855
|
-
return exportedConfigNodes.some((node) =>
|
|
66374
|
+
return exportedConfigNodes.some((node) => {
|
|
66375
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) return analyzeConfigFunction(node, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
|
|
66376
|
+
if (argumentsList.length > 0 && ts.isIdentifier(node)) {
|
|
66377
|
+
const topLevelBinding = getTopLevelBinding(sourceFile, node.text);
|
|
66378
|
+
if (topLevelBinding && ts.isFunctionLike(topLevelBinding)) return analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
|
|
66379
|
+
const importBinding = getImportBinding(sourceFile, node.text);
|
|
66380
|
+
if (importBinding) {
|
|
66381
|
+
const importedFilePath = resolveImportedConfigFile(filePath, importBinding.moduleSpecifier);
|
|
66382
|
+
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
|
|
66383
|
+
}
|
|
66384
|
+
}
|
|
66385
|
+
return analyzeConfigNode(node, analysis, allowCompilerTransform);
|
|
66386
|
+
}) || getReExportedConfigModules(sourceFile, exportName).some((binding) => {
|
|
65856
66387
|
if (exportedConfigNodes.length > 0 && binding.isNamespace) return false;
|
|
65857
66388
|
const importedFilePath = resolveImportedConfigFile(filePath, binding.moduleSpecifier);
|
|
65858
|
-
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList));
|
|
66389
|
+
return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
|
|
65859
66390
|
});
|
|
65860
66391
|
};
|
|
65861
|
-
const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = []) => {
|
|
66392
|
+
const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = [], argumentAnalysis = analysis) => {
|
|
65862
66393
|
if (!functionNode.body) return false;
|
|
65863
66394
|
if (analysis.activeFunctions.has(functionNode.pos)) return false;
|
|
65864
66395
|
const activeFunctions = new Set(analysis.activeFunctions);
|
|
@@ -65866,7 +66397,7 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
|
|
|
65866
66397
|
const functionAnalysis = {
|
|
65867
66398
|
...analysis,
|
|
65868
66399
|
visitedNodes: /* @__PURE__ */ new Set(),
|
|
65869
|
-
localBindings: getFunctionLocalBindings(functionNode, argumentsList),
|
|
66400
|
+
localBindings: getFunctionLocalBindings(functionNode, argumentsList, argumentAnalysis, analysis),
|
|
65870
66401
|
activeFunctions
|
|
65871
66402
|
};
|
|
65872
66403
|
if (!ts.isBlock(functionNode.body)) return analyzeConfigNode(functionNode.body, functionAnalysis, allowCompilerTransform);
|
|
@@ -65882,6 +66413,11 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
|
|
|
65882
66413
|
visitReturns(functionNode.body);
|
|
65883
66414
|
return hasCompiler;
|
|
65884
66415
|
};
|
|
66416
|
+
const analyzeImportedConfig = ({ analysis, moduleSpecifier, exportName, allowCompilerTransform, argumentsList }) => {
|
|
66417
|
+
const importedFilePath = resolveImportedConfigFile(analysis.filePath, moduleSpecifier);
|
|
66418
|
+
if (!importedFilePath) return null;
|
|
66419
|
+
return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList, analysis);
|
|
66420
|
+
};
|
|
65885
66421
|
const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, isCompilerTransformCollection, excludedPropertyNames) => {
|
|
65886
66422
|
const assignedReactCompiler = getAssignedPropertyInitializer(identifier, "reactCompiler");
|
|
65887
66423
|
if (assignedReactCompiler.initializer && !isStaticallyDisabledConfigExpression(assignedReactCompiler.initializer, analysis)) return true;
|
|
@@ -65894,42 +66430,74 @@ const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, i
|
|
|
65894
66430
|
if (assignedPlugins.wasFound) overriddenPropertyNames.add("plugins");
|
|
65895
66431
|
if (assignedPresets.wasFound) overriddenPropertyNames.add("presets");
|
|
65896
66432
|
if (analysis.localBindings.has(identifier.text)) {
|
|
65897
|
-
const
|
|
65898
|
-
return Boolean(
|
|
66433
|
+
const localReference = analysis.localBindings.get(identifier.text);
|
|
66434
|
+
return Boolean(localReference?.expression && analyzeConfigNode(localReference.expression, localReference.analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
65899
66435
|
}
|
|
65900
66436
|
const scopedBinding = getScopedConfigBinding(identifier);
|
|
65901
66437
|
if (scopedBinding.wasFound) return Boolean(scopedBinding.initializer && analyzeConfigNode(scopedBinding.initializer, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
65902
66438
|
const importBinding = getImportBinding(analysis.sourceFile, identifier.text);
|
|
65903
66439
|
if (importBinding) {
|
|
65904
66440
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
|
|
65905
|
-
|
|
65906
|
-
|
|
65907
|
-
|
|
66441
|
+
return Boolean(analyzeImportedConfig({
|
|
66442
|
+
analysis,
|
|
66443
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66444
|
+
exportName: importBinding.exportName,
|
|
66445
|
+
allowCompilerTransform
|
|
66446
|
+
}));
|
|
65908
66447
|
}
|
|
65909
66448
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, identifier.text);
|
|
65910
66449
|
return Boolean(topLevelBinding && analyzeConfigNode(topLevelBinding, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
|
|
65911
66450
|
};
|
|
65912
66451
|
const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransform) => {
|
|
65913
66452
|
const target = callExpression.expression;
|
|
66453
|
+
const callableRequiredModuleSpecifier = getRequireModuleSpecifier$1(target);
|
|
66454
|
+
if (callableRequiredModuleSpecifier !== null) {
|
|
66455
|
+
if (ts.isCallExpression(target) && ts.isIdentifier(target.expression) && (analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66456
|
+
if (allowCompilerTransform && isCompilerTransformModule(callableRequiredModuleSpecifier, "default")) return true;
|
|
66457
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66458
|
+
analysis,
|
|
66459
|
+
moduleSpecifier: callableRequiredModuleSpecifier,
|
|
66460
|
+
exportName: "default",
|
|
66461
|
+
allowCompilerTransform,
|
|
66462
|
+
argumentsList: callExpression.arguments
|
|
66463
|
+
});
|
|
66464
|
+
if (isLocalModuleSpecifier(callableRequiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66465
|
+
return null;
|
|
66466
|
+
}
|
|
65914
66467
|
if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
|
|
65915
66468
|
const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
|
|
65916
66469
|
if (propertyName === null) return null;
|
|
65917
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(target.expression);
|
|
66470
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
|
|
65918
66471
|
if (requiredModuleSpecifier !== null) {
|
|
65919
|
-
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
65920
|
-
if (
|
|
65921
|
-
const
|
|
65922
|
-
|
|
66472
|
+
if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (analysis.localBindings.has(target.expression.expression.text) || getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66473
|
+
if (allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, propertyName)) return true;
|
|
66474
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66475
|
+
analysis,
|
|
66476
|
+
moduleSpecifier: requiredModuleSpecifier,
|
|
66477
|
+
exportName: propertyName,
|
|
66478
|
+
allowCompilerTransform,
|
|
66479
|
+
argumentsList: callExpression.arguments
|
|
66480
|
+
});
|
|
66481
|
+
if (isLocalModuleSpecifier(requiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66482
|
+
return null;
|
|
65923
66483
|
}
|
|
65924
66484
|
if (!ts.isIdentifier(target.expression)) return null;
|
|
65925
|
-
const importBinding = getImportBinding(analysis.sourceFile, target.expression.text);
|
|
65926
|
-
if (importBinding?.isNamespace
|
|
65927
|
-
|
|
65928
|
-
|
|
66485
|
+
const importBinding = analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound ? null : getImportBinding(analysis.sourceFile, target.expression.text);
|
|
66486
|
+
if (importBinding?.isNamespace) {
|
|
66487
|
+
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, propertyName)) return true;
|
|
66488
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66489
|
+
analysis,
|
|
66490
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66491
|
+
exportName: propertyName,
|
|
66492
|
+
allowCompilerTransform,
|
|
66493
|
+
argumentsList: callExpression.arguments
|
|
66494
|
+
});
|
|
66495
|
+
if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66496
|
+
return null;
|
|
65929
66497
|
}
|
|
65930
66498
|
const selectedProperty = getSelectedObjectProperty(target.expression, propertyName, analysis);
|
|
65931
66499
|
if (selectedProperty === null) return null;
|
|
65932
|
-
return ts.isFunctionLike(selectedProperty) ? analyzeConfigFunction(selectedProperty, analysis, allowCompilerTransform, callExpression.arguments) : analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66500
|
+
return ts.isFunctionLike(selectedProperty.node) ? analyzeConfigFunction(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform, callExpression.arguments, analysis) : analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
65933
66501
|
};
|
|
65934
66502
|
const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTransformCollection = false, excludedPropertyNames) => {
|
|
65935
66503
|
const excludedPropertiesVisitKey = excludedPropertyNames ? [...excludedPropertyNames].sort().join(",") : "";
|
|
@@ -65943,25 +66511,29 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65943
66511
|
const reactCompilerFlagState = excludedPropertyNames?.has("reactCompiler") ? null : getReactCompilerFlagState(node, analysis);
|
|
65944
66512
|
if (reactCompilerFlagState?.isEnabled) return true;
|
|
65945
66513
|
for (const [propertyIndex, property] of node.properties.entries()) if (ts.isPropertyAssignment(property)) {
|
|
65946
|
-
const propertyName = getStaticPropertyName$
|
|
66514
|
+
const propertyName = getStaticPropertyName$2(property.name);
|
|
65947
66515
|
if (propertyName && excludedPropertyNames?.has(propertyName)) continue;
|
|
65948
66516
|
if (propertyName === "reactCompiler") continue;
|
|
65949
|
-
if ((propertyName === "plugins" || propertyName === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, propertyName, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$
|
|
66517
|
+
if ((propertyName === "plugins" || propertyName === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, propertyName, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$2(laterProperty.name) === propertyName)) continue;
|
|
65950
66518
|
const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
|
|
65951
|
-
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)
|
|
65952
|
-
|
|
65953
|
-
|
|
66519
|
+
if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)) {
|
|
66520
|
+
if (analyzeImportedConfig({
|
|
66521
|
+
analysis,
|
|
66522
|
+
moduleSpecifier: property.initializer.text,
|
|
66523
|
+
exportName: "default",
|
|
66524
|
+
allowCompilerTransform: false
|
|
66525
|
+
})) return true;
|
|
65954
66526
|
}
|
|
65955
66527
|
if (analyzeConfigNode(property.initializer, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
65956
66528
|
} else if (ts.isShorthandPropertyAssignment(property)) {
|
|
65957
66529
|
if (excludedPropertyNames?.has(property.name.text)) continue;
|
|
65958
66530
|
if (property.name.text === "reactCompiler") continue;
|
|
65959
|
-
if ((property.name.text === "plugins" || property.name.text === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, property.name.text, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$
|
|
66531
|
+
if ((property.name.text === "plugins" || property.name.text === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, property.name.text, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$2(laterProperty.name) === property.name.text)) continue;
|
|
65960
66532
|
const propertyAllowsCompilerTransform = property.name.text === "plugins" || property.name.text === "presets";
|
|
65961
66533
|
if (analyzeConfigNode(property.name, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
|
|
65962
66534
|
} else if (ts.isSpreadAssignment(property)) {
|
|
65963
66535
|
if (reactCompilerFlagState && getReactCompilerFlagState(property.expression, analysis) !== null) continue;
|
|
65964
|
-
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$
|
|
66536
|
+
if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$2(laterProperty.name) === "plugins" || getStaticPropertyName$2(laterProperty.name) === "presets"))) continue;
|
|
65965
66537
|
if (analyzeConfigNode(property.expression, analysis, allowCompilerTransform, false, excludedPropertyNames)) return true;
|
|
65966
66538
|
}
|
|
65967
66539
|
return false;
|
|
@@ -65974,23 +66546,36 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65974
66546
|
});
|
|
65975
66547
|
}
|
|
65976
66548
|
if (ts.isCallExpression(node)) {
|
|
66549
|
+
const resolvedModuleSpecifier = getNodeRequireResolveModuleSpecifier(node, analysis);
|
|
66550
|
+
if (resolvedModuleSpecifier !== null) return allowCompilerTransform && isCompilerTransformModule(resolvedModuleSpecifier, "default");
|
|
65977
66551
|
const callTargetResult = analyzeConfigCallTarget(node, analysis, allowCompilerTransform);
|
|
65978
66552
|
if (callTargetResult !== null) return callTargetResult;
|
|
65979
|
-
const directModuleSpecifier = getRequireModuleSpecifier(node);
|
|
66553
|
+
const directModuleSpecifier = getRequireModuleSpecifier$1(node);
|
|
65980
66554
|
const isRequireShadowed = analysis.localBindings.has("require") || ts.isIdentifier(node.expression) && getScopedConfigBinding(node.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require");
|
|
65981
66555
|
if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
65982
66556
|
if (directModuleSpecifier && !isRequireShadowed) {
|
|
65983
66557
|
if (allowCompilerTransform && isCompilerTransformModule(directModuleSpecifier, "default")) return true;
|
|
65984
|
-
if (
|
|
65985
|
-
|
|
65986
|
-
|
|
65987
|
-
|
|
66558
|
+
if (analyzeImportedConfig({
|
|
66559
|
+
analysis,
|
|
66560
|
+
moduleSpecifier: directModuleSpecifier,
|
|
66561
|
+
exportName: "default",
|
|
66562
|
+
allowCompilerTransform
|
|
66563
|
+
})) return true;
|
|
65988
66564
|
}
|
|
65989
66565
|
if (ts.isIdentifier(node.expression)) {
|
|
65990
|
-
|
|
65991
|
-
|
|
65992
|
-
|
|
65993
|
-
|
|
66566
|
+
if (!analysis.localBindings.has(node.expression.text) && !getScopedConfigBinding(node.expression).wasFound) {
|
|
66567
|
+
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66568
|
+
if (importBinding) {
|
|
66569
|
+
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
|
|
66570
|
+
const hasCompilerTransform = analyzeImportedConfig({
|
|
66571
|
+
analysis,
|
|
66572
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66573
|
+
exportName: importBinding.exportName,
|
|
66574
|
+
allowCompilerTransform,
|
|
66575
|
+
argumentsList: node.arguments
|
|
66576
|
+
});
|
|
66577
|
+
if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
|
|
66578
|
+
}
|
|
65994
66579
|
}
|
|
65995
66580
|
const topLevelBinding = getTopLevelBinding(analysis.sourceFile, node.expression.text);
|
|
65996
66581
|
if (topLevelBinding && ts.isFunctionLike(topLevelBinding) && analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, node.arguments)) return true;
|
|
@@ -65998,47 +66583,57 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
65998
66583
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform) || node.arguments.some((argument) => analyzeConfigNode(argument, analysis, false));
|
|
65999
66584
|
}
|
|
66000
66585
|
if (ts.isPropertyAccessExpression(node)) {
|
|
66001
|
-
const requiredModuleSpecifier = getRequireModuleSpecifier(node.expression);
|
|
66586
|
+
const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
|
|
66002
66587
|
if (requiredModuleSpecifier) {
|
|
66003
|
-
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66004
|
-
if (
|
|
66005
|
-
|
|
66006
|
-
|
|
66007
|
-
|
|
66588
|
+
if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (analysis.localBindings.has(node.expression.expression.text) || getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
|
|
66589
|
+
if (analyzeImportedConfig({
|
|
66590
|
+
analysis,
|
|
66591
|
+
moduleSpecifier: requiredModuleSpecifier,
|
|
66592
|
+
exportName: node.name.text,
|
|
66593
|
+
allowCompilerTransform
|
|
66594
|
+
})) return true;
|
|
66008
66595
|
return allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, node.name.text);
|
|
66009
66596
|
}
|
|
66010
66597
|
if (ts.isIdentifier(node.expression)) {
|
|
66011
|
-
if (analysis.localBindings.has(node.expression.text)) {
|
|
66012
|
-
const
|
|
66013
|
-
return Boolean(
|
|
66598
|
+
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66599
|
+
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
66600
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
|
|
66014
66601
|
}
|
|
66015
66602
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66016
66603
|
if (importBinding?.isNamespace) {
|
|
66017
66604
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.name.text)) return true;
|
|
66018
|
-
if (
|
|
66019
|
-
|
|
66020
|
-
|
|
66021
|
-
|
|
66605
|
+
if (analyzeImportedConfig({
|
|
66606
|
+
analysis,
|
|
66607
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66608
|
+
exportName: node.name.text,
|
|
66609
|
+
allowCompilerTransform
|
|
66610
|
+
})) return true;
|
|
66022
66611
|
return false;
|
|
66023
66612
|
}
|
|
66024
66613
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
|
|
66025
|
-
if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66614
|
+
if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
66026
66615
|
return false;
|
|
66027
66616
|
}
|
|
66028
66617
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
66029
66618
|
}
|
|
66030
66619
|
if (ts.isElementAccessExpression(node) && node.argumentExpression && ts.isStringLiteralLike(node.argumentExpression)) {
|
|
66031
66620
|
if (ts.isIdentifier(node.expression)) {
|
|
66621
|
+
if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
|
|
66622
|
+
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66623
|
+
return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
|
|
66624
|
+
}
|
|
66032
66625
|
const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
|
|
66033
66626
|
if (importBinding?.isNamespace) {
|
|
66034
66627
|
if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.argumentExpression.text)) return true;
|
|
66035
|
-
|
|
66036
|
-
|
|
66037
|
-
|
|
66038
|
-
|
|
66628
|
+
return Boolean(analyzeImportedConfig({
|
|
66629
|
+
analysis,
|
|
66630
|
+
moduleSpecifier: importBinding.moduleSpecifier,
|
|
66631
|
+
exportName: node.argumentExpression.text,
|
|
66632
|
+
allowCompilerTransform
|
|
66633
|
+
}));
|
|
66039
66634
|
}
|
|
66040
66635
|
const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
|
|
66041
|
-
if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
|
|
66636
|
+
if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
|
|
66042
66637
|
return false;
|
|
66043
66638
|
}
|
|
66044
66639
|
return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
|
|
@@ -66073,14 +66668,19 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
|
|
|
66073
66668
|
};
|
|
66074
66669
|
const hasCompilerInConfigFile = (filePath) => analyzeConfigModuleExport(filePath, "default", false, 0, /* @__PURE__ */ new Set());
|
|
66075
66670
|
const hasCompilerInConfigFiles = (directory, filenames) => filenames.some((filename) => hasCompilerInConfigFile(Path.join(directory, filename)));
|
|
66076
|
-
const hasCompilerInPackageJsonConfig = (
|
|
66077
|
-
|
|
66671
|
+
const hasCompilerInPackageJsonConfig = (directory, packageJson) => {
|
|
66672
|
+
if (!isPlainObject(packageJson.babel)) return false;
|
|
66673
|
+
const packageJsonPath = Path.join(directory, "package.json");
|
|
66674
|
+
return analyzeConfigSourceFileExport(ts.parseJsonText(packageJsonPath, JSON.stringify(packageJson.babel)), packageJsonPath, "default", false, 0, /* @__PURE__ */ new Set());
|
|
66675
|
+
};
|
|
66676
|
+
const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(directory, packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
|
|
66078
66677
|
const hasCompilerConfigurationInAncestors = (directory) => {
|
|
66079
66678
|
if (isProjectBoundary(directory)) return false;
|
|
66080
66679
|
let ancestorDirectory = Path.dirname(directory);
|
|
66081
66680
|
while (ancestorDirectory !== Path.dirname(ancestorDirectory)) {
|
|
66082
66681
|
const ancestorPackagePath = Path.join(ancestorDirectory, "package.json");
|
|
66083
|
-
|
|
66682
|
+
const ancestorPackageJson = isFile(ancestorPackagePath) ? readPackageJson$1(ancestorPackagePath) : {};
|
|
66683
|
+
if (hasCompilerInPackageJsonConfig(ancestorDirectory, ancestorPackageJson) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
|
|
66084
66684
|
if (isProjectBoundary(ancestorDirectory)) return false;
|
|
66085
66685
|
ancestorDirectory = Path.dirname(ancestorDirectory);
|
|
66086
66686
|
}
|
|
@@ -68274,7 +68874,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
68274
68874
|
const getDiagnosticRuleIdentity = (diagnostic) => ({
|
|
68275
68875
|
ruleKey: `${diagnostic.plugin}/${diagnostic.rule}`,
|
|
68276
68876
|
category: diagnostic.category,
|
|
68277
|
-
tags: diagnostic.plugin === "react-doctor" ?
|
|
68877
|
+
tags: diagnostic.plugin === "react-doctor" ? REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule]?.tags ?? [] : []
|
|
68278
68878
|
});
|
|
68279
68879
|
const compileIgnoredFilePatterns = (userConfig) => {
|
|
68280
68880
|
const files = userConfig?.ignore?.files;
|
|
@@ -68410,6 +69010,7 @@ const classifyPackageRole = (filename) => {
|
|
|
68410
69010
|
* Resolves the absolute path to read for a diagnostic's `filePath`,
|
|
68411
69011
|
* accounting for the various shapes oxlint emits:
|
|
68412
69012
|
*
|
|
69013
|
+
* - `file://` URL — decode to an absolute filesystem path.
|
|
68413
69014
|
* - Absolute POSIX (`/abs/path/file.tsx`) — pass through.
|
|
68414
69015
|
* - Absolute Windows (`C:/...` or `C:\...`) — pass through.
|
|
68415
69016
|
* - `./relative` or bare relative — join against `rootDirectory`.
|
|
@@ -68419,6 +69020,7 @@ const classifyPackageRole = (filename) => {
|
|
|
68419
69020
|
* use one canonical resolution path.
|
|
68420
69021
|
*/
|
|
68421
69022
|
const resolveCandidateReadPath = (rootDirectory, filePath) => {
|
|
69023
|
+
if (filePath.startsWith("file://")) return fileURLToPath(filePath);
|
|
68422
69024
|
const normalizedFile = filePath.replace(/\\/g, "/");
|
|
68423
69025
|
if (normalizedFile.startsWith("/") || /^[a-zA-Z]:\//.test(normalizedFile) || /^[a-zA-Z]:\\/.test(filePath)) return filePath;
|
|
68424
69026
|
return `${rootDirectory.replace(/\\/g, "/").replace(/\/$/, "")}/${normalizedFile.replace(/^\.\//, "")}`;
|
|
@@ -68620,7 +69222,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
68620
69222
|
};
|
|
68621
69223
|
const shouldAutoSuppress = (diagnostic) => {
|
|
68622
69224
|
if (diagnostic.plugin !== "react-doctor") return false;
|
|
68623
|
-
const rule =
|
|
69225
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule];
|
|
68624
69226
|
if (!rule?.tags?.includes("test-noise")) return false;
|
|
68625
69227
|
if (rule.tags.includes("migration-hint")) return false;
|
|
68626
69228
|
return getFileContext(diagnostic.filePath) !== "production";
|
|
@@ -69052,6 +69654,7 @@ var OxlintConcurrency = class extends Reference("react-doctor/OxlintConcurrency"
|
|
|
69052
69654
|
if (Number.isInteger(parsed) && parsed > 0) return resolveScanConcurrency(parsed);
|
|
69053
69655
|
return resolveAutoScanConcurrency();
|
|
69054
69656
|
} }) {};
|
|
69657
|
+
var OxlintSpawnSlots = class extends Reference("react-doctor/OxlintSpawnSlots", { defaultValue: () => null }) {};
|
|
69055
69658
|
/**
|
|
69056
69659
|
* Three-state control for overlapping the dead-code pass with the lint pass —
|
|
69057
69660
|
* forking dead-code as a child fiber that runs DURING lint instead of strictly
|
|
@@ -69335,7 +69938,7 @@ const warn = (message) => {
|
|
|
69335
69938
|
runSync(warn$1(message));
|
|
69336
69939
|
};
|
|
69337
69940
|
const CONFIG_BASENAME = "doctor.config";
|
|
69338
|
-
const CONFIG_EXTENSIONS = [
|
|
69941
|
+
const CONFIG_EXTENSIONS$1 = [
|
|
69339
69942
|
"ts",
|
|
69340
69943
|
"mts",
|
|
69341
69944
|
"cts",
|
|
@@ -69439,7 +70042,7 @@ const loadLegacyConfig = (directory) => {
|
|
|
69439
70042
|
};
|
|
69440
70043
|
const loadConfigFromDirectory = async (directory) => {
|
|
69441
70044
|
let sawBrokenConfigFile = false;
|
|
69442
|
-
for (const extension of CONFIG_EXTENSIONS) {
|
|
70045
|
+
for (const extension of CONFIG_EXTENSIONS$1) {
|
|
69443
70046
|
const filePath = Path.join(directory, `${CONFIG_BASENAME}.${extension}`);
|
|
69444
70047
|
if (!isFile(filePath)) continue;
|
|
69445
70048
|
const isDataFile = DATA_CONFIG_EXTENSIONS.has(extension);
|
|
@@ -69498,7 +70101,7 @@ const loadConfigWithSource = (rootDirectory) => {
|
|
|
69498
70101
|
return loadPromise;
|
|
69499
70102
|
};
|
|
69500
70103
|
const directoryHasCurrentConfig = (directory) => {
|
|
69501
|
-
for (const extension of CONFIG_EXTENSIONS) if (isFile(Path.join(directory, `${CONFIG_BASENAME}.${extension}`))) return true;
|
|
70104
|
+
for (const extension of CONFIG_EXTENSIONS$1) if (isFile(Path.join(directory, `${CONFIG_BASENAME}.${extension}`))) return true;
|
|
69502
70105
|
return readEmbeddedPackageJsonConfig(directory) !== null;
|
|
69503
70106
|
};
|
|
69504
70107
|
/**
|
|
@@ -70202,6 +70805,316 @@ const buildReactNativeDiagnostic = (input) => ({
|
|
|
70202
70805
|
column: input.column ?? 0,
|
|
70203
70806
|
category: input.category ?? "Correctness"
|
|
70204
70807
|
});
|
|
70808
|
+
const ANDROID_APP_BUILD_FILE_NAMES = ["build.gradle", "build.gradle.kts"];
|
|
70809
|
+
const BUILD_TYPES_BLOCK_PATTERN = /\bbuildTypes\s*\{/g;
|
|
70810
|
+
const RELEASE_STRING_MARKER = "__RD_RELEASE__";
|
|
70811
|
+
const RELEASE_BLOCK_PATTERNS = [/\brelease\s*\{/g, /\b(?:getByName|named)\s*\(\s*(?:["']release["']|__RD_RELEASE__)\s*\)\s*\{/g];
|
|
70812
|
+
const MINIFY_ASSIGNMENT_PATTERN = /\b(?:isMinifyEnabled|minifyEnabled)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
70813
|
+
const SHRINK_RESOURCES_ASSIGNMENT_PATTERN = /\b(?:isShrinkResources|shrinkResources)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
|
|
70814
|
+
const stripGradleComments = (contents) => {
|
|
70815
|
+
let result = "";
|
|
70816
|
+
let index = 0;
|
|
70817
|
+
let quote = null;
|
|
70818
|
+
while (index < contents.length) {
|
|
70819
|
+
const character = contents[index];
|
|
70820
|
+
const nextCharacter = contents[index + 1];
|
|
70821
|
+
if (quote !== null) {
|
|
70822
|
+
result += character;
|
|
70823
|
+
if (character === "\\") {
|
|
70824
|
+
result += nextCharacter ?? "";
|
|
70825
|
+
index += 2;
|
|
70826
|
+
continue;
|
|
70827
|
+
}
|
|
70828
|
+
if (character === quote) quote = null;
|
|
70829
|
+
index += 1;
|
|
70830
|
+
continue;
|
|
70831
|
+
}
|
|
70832
|
+
if (character === "\"" || character === "'") {
|
|
70833
|
+
quote = character;
|
|
70834
|
+
result += character;
|
|
70835
|
+
index += 1;
|
|
70836
|
+
continue;
|
|
70837
|
+
}
|
|
70838
|
+
if (character === "/" && nextCharacter === "/") {
|
|
70839
|
+
while (index < contents.length && contents[index] !== "\n") {
|
|
70840
|
+
result += " ";
|
|
70841
|
+
index += 1;
|
|
70842
|
+
}
|
|
70843
|
+
continue;
|
|
70844
|
+
}
|
|
70845
|
+
if (character === "/" && nextCharacter === "*") {
|
|
70846
|
+
result += " ";
|
|
70847
|
+
index += 2;
|
|
70848
|
+
while (index < contents.length && !(contents[index] === "*" && contents[index + 1] === "/")) {
|
|
70849
|
+
result += contents[index] === "\n" ? "\n" : " ";
|
|
70850
|
+
index += 1;
|
|
70851
|
+
}
|
|
70852
|
+
if (index < contents.length) {
|
|
70853
|
+
result += " ";
|
|
70854
|
+
index += 2;
|
|
70855
|
+
}
|
|
70856
|
+
continue;
|
|
70857
|
+
}
|
|
70858
|
+
result += character;
|
|
70859
|
+
index += 1;
|
|
70860
|
+
}
|
|
70861
|
+
return result;
|
|
70862
|
+
};
|
|
70863
|
+
const maskGradleStrings = (contents) => {
|
|
70864
|
+
let result = "";
|
|
70865
|
+
let index = 0;
|
|
70866
|
+
let quote = null;
|
|
70867
|
+
while (index < contents.length) {
|
|
70868
|
+
const character = contents[index];
|
|
70869
|
+
if (quote === null) {
|
|
70870
|
+
if (character === "\"" || character === "'") {
|
|
70871
|
+
quote = character;
|
|
70872
|
+
result += " ";
|
|
70873
|
+
} else result += character;
|
|
70874
|
+
index += 1;
|
|
70875
|
+
continue;
|
|
70876
|
+
}
|
|
70877
|
+
if (character === "\\") {
|
|
70878
|
+
result += " ";
|
|
70879
|
+
index += 2;
|
|
70880
|
+
continue;
|
|
70881
|
+
}
|
|
70882
|
+
if (character === quote) quote = null;
|
|
70883
|
+
result += character === "\n" ? "\n" : " ";
|
|
70884
|
+
index += 1;
|
|
70885
|
+
}
|
|
70886
|
+
return result;
|
|
70887
|
+
};
|
|
70888
|
+
const findBlockContents = (contents, pattern) => {
|
|
70889
|
+
const blocks = [];
|
|
70890
|
+
pattern.lastIndex = 0;
|
|
70891
|
+
let match = pattern.exec(contents);
|
|
70892
|
+
while (match !== null) {
|
|
70893
|
+
const openingBraceIndex = pattern.lastIndex - 1;
|
|
70894
|
+
let depth = 1;
|
|
70895
|
+
let index = openingBraceIndex + 1;
|
|
70896
|
+
let quote = null;
|
|
70897
|
+
while (index < contents.length && depth > 0) {
|
|
70898
|
+
const character = contents[index];
|
|
70899
|
+
if (quote !== null) {
|
|
70900
|
+
if (character === "\\") {
|
|
70901
|
+
index += 2;
|
|
70902
|
+
continue;
|
|
70903
|
+
}
|
|
70904
|
+
if (character === quote) quote = null;
|
|
70905
|
+
} else if (character === "\"" || character === "'") quote = character;
|
|
70906
|
+
else if (character === "{") depth += 1;
|
|
70907
|
+
else if (character === "}") depth -= 1;
|
|
70908
|
+
index += 1;
|
|
70909
|
+
}
|
|
70910
|
+
if (depth === 0) blocks.push(contents.slice(openingBraceIndex + 1, index - 1));
|
|
70911
|
+
match = pattern.exec(contents);
|
|
70912
|
+
}
|
|
70913
|
+
return blocks;
|
|
70914
|
+
};
|
|
70915
|
+
const getFinalStaticBoolean = (contents, pattern) => {
|
|
70916
|
+
pattern.lastIndex = 0;
|
|
70917
|
+
let finalValue = null;
|
|
70918
|
+
let match = pattern.exec(contents);
|
|
70919
|
+
while (match !== null) {
|
|
70920
|
+
const staticValue = match[1]?.trim().replace(/\)$/, "").trim();
|
|
70921
|
+
if (staticValue === "true") finalValue = true;
|
|
70922
|
+
else if (staticValue === "false") finalValue = false;
|
|
70923
|
+
else finalValue = null;
|
|
70924
|
+
match = pattern.exec(contents);
|
|
70925
|
+
}
|
|
70926
|
+
return finalValue;
|
|
70927
|
+
};
|
|
70928
|
+
const getReleaseBlocks = (contents) => findBlockContents(contents, BUILD_TYPES_BLOCK_PATTERN).flatMap((buildTypesBlock) => RELEASE_BLOCK_PATTERNS.flatMap((pattern) => findBlockContents(buildTypesBlock, pattern)));
|
|
70929
|
+
const readAndroidReleaseShrinking = (rootDirectory) => {
|
|
70930
|
+
for (const buildFileName of ANDROID_APP_BUILD_FILE_NAMES) {
|
|
70931
|
+
const filePath = Path.posix.join("android", "app", buildFileName);
|
|
70932
|
+
const absoluteFilePath = Path.join(rootDirectory, filePath);
|
|
70933
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
70934
|
+
let contents;
|
|
70935
|
+
try {
|
|
70936
|
+
contents = stripGradleComments(NFS.readFileSync(absoluteFilePath, "utf-8"));
|
|
70937
|
+
} catch {
|
|
70938
|
+
return null;
|
|
70939
|
+
}
|
|
70940
|
+
const releaseBlocks = getReleaseBlocks(maskGradleStrings(contents.replace(/(["'])release\1/g, RELEASE_STRING_MARKER)));
|
|
70941
|
+
const [releaseBlock] = releaseBlocks;
|
|
70942
|
+
if (releaseBlock === void 0 || releaseBlocks.length !== 1) return null;
|
|
70943
|
+
const hasDisabledMinification = getFinalStaticBoolean(releaseBlock, MINIFY_ASSIGNMENT_PATTERN) === false;
|
|
70944
|
+
const hasDisabledResourceShrinking = getFinalStaticBoolean(releaseBlock, SHRINK_RESOURCES_ASSIGNMENT_PATTERN) === false;
|
|
70945
|
+
if (!hasDisabledMinification && !hasDisabledResourceShrinking) return null;
|
|
70946
|
+
return {
|
|
70947
|
+
filePath,
|
|
70948
|
+
hasDisabledMinification,
|
|
70949
|
+
hasDisabledResourceShrinking
|
|
70950
|
+
};
|
|
70951
|
+
}
|
|
70952
|
+
return null;
|
|
70953
|
+
};
|
|
70954
|
+
const checkReactNativeAndroidReleaseShrinking = (rootDirectory) => {
|
|
70955
|
+
const releaseShrinking = readAndroidReleaseShrinking(rootDirectory);
|
|
70956
|
+
if (releaseShrinking === null) return [];
|
|
70957
|
+
const disabledFeatures = [releaseShrinking.hasDisabledMinification ? "code minification" : null, releaseShrinking.hasDisabledResourceShrinking ? "resource shrinking" : null].filter((feature) => feature !== null);
|
|
70958
|
+
return [buildReactNativeDiagnostic({
|
|
70959
|
+
filePath: releaseShrinking.filePath,
|
|
70960
|
+
rule: "rn-android-release-shrinking-disabled",
|
|
70961
|
+
category: "Performance",
|
|
70962
|
+
message: `The Android release build explicitly disables ${disabledFeatures.join(" and ")}, leaving unreachable code or resources in the shipped app.`,
|
|
70963
|
+
help: "Enable release code minification and resource shrinking, then test the optimized build and add keep rules for libraries that require them."
|
|
70964
|
+
})];
|
|
70965
|
+
};
|
|
70966
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
70967
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
70968
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
70969
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
70970
|
+
return ts.ScriptKind.JS;
|
|
70971
|
+
};
|
|
70972
|
+
const BABEL_CONFIG_FILE_NAMES$1 = [
|
|
70973
|
+
"babel.config.js",
|
|
70974
|
+
"babel.config.cjs",
|
|
70975
|
+
"babel.config.mjs",
|
|
70976
|
+
"babel.config.ts",
|
|
70977
|
+
"babel.config.cts",
|
|
70978
|
+
"babel.config.json",
|
|
70979
|
+
".babelrc",
|
|
70980
|
+
".babelrc.js",
|
|
70981
|
+
".babelrc.cjs",
|
|
70982
|
+
".babelrc.mjs",
|
|
70983
|
+
".babelrc.cts",
|
|
70984
|
+
".babelrc.json"
|
|
70985
|
+
];
|
|
70986
|
+
const readUnknownPluginNames = (value) => {
|
|
70987
|
+
if (!Array.isArray(value)) return null;
|
|
70988
|
+
const pluginNames = [];
|
|
70989
|
+
for (const entry of value) {
|
|
70990
|
+
if (typeof entry === "string") {
|
|
70991
|
+
pluginNames.push(entry);
|
|
70992
|
+
continue;
|
|
70993
|
+
}
|
|
70994
|
+
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
70995
|
+
pluginNames.push(entry[0]);
|
|
70996
|
+
continue;
|
|
70997
|
+
}
|
|
70998
|
+
return null;
|
|
70999
|
+
}
|
|
71000
|
+
return pluginNames;
|
|
71001
|
+
};
|
|
71002
|
+
const getStaticPropertyName$1 = (propertyName) => {
|
|
71003
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName)) return propertyName.text;
|
|
71004
|
+
return null;
|
|
71005
|
+
};
|
|
71006
|
+
const getStaticPluginName = (expression) => {
|
|
71007
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
71008
|
+
if (ts.isStringLiteralLike(unwrappedExpression)) return unwrappedExpression.text;
|
|
71009
|
+
if (!ts.isArrayLiteralExpression(unwrappedExpression)) return null;
|
|
71010
|
+
const pluginExpression = unwrappedExpression.elements[0];
|
|
71011
|
+
return pluginExpression && ts.isStringLiteralLike(pluginExpression) ? pluginExpression.text : null;
|
|
71012
|
+
};
|
|
71013
|
+
const getPluginNamesFromObject = (objectExpression) => {
|
|
71014
|
+
if (objectExpression.properties.some((property) => ts.isSpreadAssignment(property))) return null;
|
|
71015
|
+
const pluginProperties = objectExpression.properties.filter((property) => ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "plugins");
|
|
71016
|
+
if (pluginProperties.length !== 1) return pluginProperties.length === 0 ? [] : null;
|
|
71017
|
+
const pluginListExpression = unwrapTypescriptExpression(pluginProperties[0].initializer);
|
|
71018
|
+
if (!ts.isArrayLiteralExpression(pluginListExpression)) return null;
|
|
71019
|
+
const pluginNames = [];
|
|
71020
|
+
for (const element of pluginListExpression.elements) {
|
|
71021
|
+
if (ts.isSpreadElement(element)) return null;
|
|
71022
|
+
const pluginName = getStaticPluginName(element);
|
|
71023
|
+
if (pluginName === null) return null;
|
|
71024
|
+
pluginNames.push(pluginName);
|
|
71025
|
+
}
|
|
71026
|
+
return pluginNames;
|
|
71027
|
+
};
|
|
71028
|
+
const isModuleExports = (expression) => ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "module" && expression.name.text === "exports" || ts.isElementAccessExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "module" && expression.argumentExpression !== void 0 && ts.isStringLiteralLike(expression.argumentExpression) && expression.argumentExpression.text === "exports";
|
|
71029
|
+
const getDirectExportedObject = (sourceFile) => {
|
|
71030
|
+
const exportedExpressions = [];
|
|
71031
|
+
for (const statement of sourceFile.statements) {
|
|
71032
|
+
if (ts.isExportAssignment(statement)) {
|
|
71033
|
+
exportedExpressions.push(statement.expression);
|
|
71034
|
+
continue;
|
|
71035
|
+
}
|
|
71036
|
+
if (ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(statement.expression.left)) exportedExpressions.push(statement.expression.right);
|
|
71037
|
+
}
|
|
71038
|
+
if (exportedExpressions.length !== 1) return null;
|
|
71039
|
+
const exportedExpression = unwrapTypescriptExpression(exportedExpressions[0]);
|
|
71040
|
+
return ts.isObjectLiteralExpression(exportedExpression) ? exportedExpression : null;
|
|
71041
|
+
};
|
|
71042
|
+
const parseConfigPluginNames = (filePath, contents) => {
|
|
71043
|
+
try {
|
|
71044
|
+
const parsedJson = JSON.parse(contents);
|
|
71045
|
+
return isPlainObject(parsedJson) ? readUnknownPluginNames(parsedJson.plugins) : null;
|
|
71046
|
+
} catch {
|
|
71047
|
+
if (ts.transpileModule(contents, {
|
|
71048
|
+
fileName: filePath,
|
|
71049
|
+
reportDiagnostics: true,
|
|
71050
|
+
compilerOptions: { allowJs: true }
|
|
71051
|
+
}).diagnostics?.some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error)) return null;
|
|
71052
|
+
const exportedObject = getDirectExportedObject(ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filePath)));
|
|
71053
|
+
return exportedObject === null ? null : getPluginNamesFromObject(exportedObject);
|
|
71054
|
+
}
|
|
71055
|
+
};
|
|
71056
|
+
const readStaticBabelPluginNames = (rootDirectory) => {
|
|
71057
|
+
for (const fileName of BABEL_CONFIG_FILE_NAMES$1) {
|
|
71058
|
+
const absoluteFilePath = Path.join(rootDirectory, fileName);
|
|
71059
|
+
if (!isFile(absoluteFilePath)) continue;
|
|
71060
|
+
try {
|
|
71061
|
+
return {
|
|
71062
|
+
filePath: fileName,
|
|
71063
|
+
pluginNames: parseConfigPluginNames(fileName, NFS.readFileSync(absoluteFilePath, "utf-8"))
|
|
71064
|
+
};
|
|
71065
|
+
} catch {
|
|
71066
|
+
return {
|
|
71067
|
+
filePath: fileName,
|
|
71068
|
+
pluginNames: null
|
|
71069
|
+
};
|
|
71070
|
+
}
|
|
71071
|
+
}
|
|
71072
|
+
const packageJson = readPackageJson$1(Path.join(rootDirectory, "package.json"));
|
|
71073
|
+
if (!isPlainObject(packageJson.babel)) return null;
|
|
71074
|
+
return {
|
|
71075
|
+
filePath: "package.json",
|
|
71076
|
+
pluginNames: readUnknownPluginNames(packageJson.babel.plugins)
|
|
71077
|
+
};
|
|
71078
|
+
};
|
|
71079
|
+
const REACT_COMPILER_PLUGIN_NAMES = new Set(["babel-plugin-react-compiler", "react-compiler"]);
|
|
71080
|
+
const REANIMATED_PLUGIN_NAME = "react-native-reanimated/plugin";
|
|
71081
|
+
const WORKLETS_PLUGIN_NAME = "react-native-worklets/plugin";
|
|
71082
|
+
const checkReactCompilerPluginOrder = (filePath, pluginNames) => {
|
|
71083
|
+
if (pluginNames.findIndex((pluginName) => REACT_COMPILER_PLUGIN_NAMES.has(pluginName)) <= 0) return [];
|
|
71084
|
+
return [buildReactNativeDiagnostic({
|
|
71085
|
+
filePath,
|
|
71086
|
+
rule: "rn-react-compiler-plugin-first",
|
|
71087
|
+
category: "Performance",
|
|
71088
|
+
message: "The React Compiler Babel plugin is not first, so an earlier transform can change component or hook code before the compiler analyzes it.",
|
|
71089
|
+
help: "Move `babel-plugin-react-compiler` to the first entry in the Babel `plugins` array."
|
|
71090
|
+
})];
|
|
71091
|
+
};
|
|
71092
|
+
const checkReanimatedPluginOrder = (project, filePath, pluginNames) => {
|
|
71093
|
+
const reanimatedMajorVersion = project.reanimatedVersion === null || project.reanimatedVersion === void 0 ? null : getLowestDependencyMajor(project.reanimatedVersion);
|
|
71094
|
+
if (reanimatedMajorVersion === null || reanimatedMajorVersion < 4) return [];
|
|
71095
|
+
const diagnostics = [];
|
|
71096
|
+
if (pluginNames.includes(REANIMATED_PLUGIN_NAME)) diagnostics.push(buildReactNativeDiagnostic({
|
|
71097
|
+
filePath,
|
|
71098
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
71099
|
+
category: "Performance",
|
|
71100
|
+
message: "This Reanimated 4 project still uses `react-native-reanimated/plugin`, which was renamed to the Worklets Babel plugin.",
|
|
71101
|
+
help: "Replace it with `react-native-worklets/plugin` and keep that plugin last in the Babel `plugins` array."
|
|
71102
|
+
}));
|
|
71103
|
+
const workletsPluginIndex = pluginNames.lastIndexOf(WORKLETS_PLUGIN_NAME);
|
|
71104
|
+
if (workletsPluginIndex !== -1 && workletsPluginIndex !== pluginNames.length - 1) diagnostics.push(buildReactNativeDiagnostic({
|
|
71105
|
+
filePath,
|
|
71106
|
+
rule: "rn-reanimated-worklets-plugin-last",
|
|
71107
|
+
category: "Performance",
|
|
71108
|
+
message: "`react-native-worklets/plugin` is not last in the Babel `plugins` array, so later transforms can prevent worklets from being compiled correctly.",
|
|
71109
|
+
help: "Move `react-native-worklets/plugin` to the final entry in the Babel `plugins` array."
|
|
71110
|
+
}));
|
|
71111
|
+
return diagnostics;
|
|
71112
|
+
};
|
|
71113
|
+
const checkReactNativeBabelPluginOrder = (rootDirectory, project) => {
|
|
71114
|
+
const babelPlugins = readStaticBabelPluginNames(rootDirectory);
|
|
71115
|
+
if (babelPlugins === null || babelPlugins.pluginNames === null) return [];
|
|
71116
|
+
return [...checkReactCompilerPluginOrder(babelPlugins.filePath, babelPlugins.pluginNames), ...checkReanimatedPluginOrder(project, babelPlugins.filePath, babelPlugins.pluginNames)];
|
|
71117
|
+
};
|
|
70205
71118
|
const BUILDER_BOB_PACKAGE = "react-native-builder-bob";
|
|
70206
71119
|
const isBuilderBobLibrary = (packageJson) => {
|
|
70207
71120
|
const bobConfig = packageJson[BUILDER_BOB_PACKAGE];
|
|
@@ -70278,7 +71191,12 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
|
70278
71191
|
const isReactNativeProject = (project) => project.framework === "react-native" || project.framework === "expo" || project.hasReactNativeWorkspace || project.expoVersion !== null;
|
|
70279
71192
|
const checkReactNativeProject = (rootDirectory, project) => {
|
|
70280
71193
|
if (!isReactNativeProject(project)) return [];
|
|
70281
|
-
return [
|
|
71194
|
+
return [
|
|
71195
|
+
...checkReactNativeMetroBabelPreset(rootDirectory),
|
|
71196
|
+
...checkReactNativeBabelPluginOrder(rootDirectory, project),
|
|
71197
|
+
...checkReactNativeAndroidReleaseShrinking(rootDirectory),
|
|
71198
|
+
...checkReactNativeLibraryDependencies(rootDirectory)
|
|
71199
|
+
];
|
|
70282
71200
|
};
|
|
70283
71201
|
const RULE_KEY = "no-vulnerable-react-server-components";
|
|
70284
71202
|
const REACT_RSC_ADVISORIES_BY_MINOR = {
|
|
@@ -70429,17 +71347,6 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
70429
71347
|
}
|
|
70430
71348
|
return diagnostics;
|
|
70431
71349
|
};
|
|
70432
|
-
const getTypescriptScriptKind = (fileName) => {
|
|
70433
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
70434
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
70435
|
-
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
70436
|
-
return ts.ScriptKind.JS;
|
|
70437
|
-
};
|
|
70438
|
-
const unwrapTypescriptExpression = (expression) => {
|
|
70439
|
-
let currentExpression = expression;
|
|
70440
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
70441
|
-
return currentExpression;
|
|
70442
|
-
};
|
|
70443
71350
|
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
70444
71351
|
isAnimationFunction: false,
|
|
70445
71352
|
isMotionComponent: false,
|
|
@@ -70995,7 +71902,11 @@ const buildCapabilities = (project) => {
|
|
|
70995
71902
|
capabilities.add(project.framework);
|
|
70996
71903
|
if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
|
|
70997
71904
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
70998
|
-
if (project.expoVersion !== null)
|
|
71905
|
+
if (project.expoVersion !== null) {
|
|
71906
|
+
capabilities.add("expo");
|
|
71907
|
+
const expoSdkMajorVersion = getLowestDependencyMajor(project.expoVersion);
|
|
71908
|
+
if (expoSdkMajorVersion !== null && expoSdkMajorVersion >= 54) capabilities.add("expo:54");
|
|
71909
|
+
}
|
|
70999
71910
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
71000
71911
|
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
71001
71912
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
@@ -71059,6 +71970,11 @@ const buildCapabilities = (project) => {
|
|
|
71059
71970
|
if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
|
|
71060
71971
|
if (project.isPreES2023Target) capabilities.add("pre-es2023");
|
|
71061
71972
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
71973
|
+
if (project.reanimatedVersion !== void 0 && project.reanimatedVersion !== null) {
|
|
71974
|
+
capabilities.add("reanimated");
|
|
71975
|
+
const reanimatedMajorVersion = getLowestDependencyMajor(project.reanimatedVersion);
|
|
71976
|
+
if (reanimatedMajorVersion !== null && reanimatedMajorVersion >= 4) capabilities.add("reanimated:4");
|
|
71977
|
+
}
|
|
71062
71978
|
if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
|
|
71063
71979
|
if (project.styledComponentsVersion) {
|
|
71064
71980
|
capabilities.add("styled-components");
|
|
@@ -71089,8 +72005,8 @@ const getCapabilities = (project) => {
|
|
|
71089
72005
|
const cached = capabilitiesByProject.get(project);
|
|
71090
72006
|
if (cached !== void 0) return cached;
|
|
71091
72007
|
const capabilities = new Set(buildCapabilities(project));
|
|
71092
|
-
const
|
|
71093
|
-
const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(
|
|
72008
|
+
const capabilityRootDirectory = isFile(Path.join(project.rootDirectory, "package.json")) ? project.rootDirectory : findNearestAncestorPackageJson(project.rootDirectory) ?? project.rootDirectory;
|
|
72009
|
+
const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(capabilityRootDirectory, readPackageJson$1(Path.join(capabilityRootDirectory, "package.json")));
|
|
71094
72010
|
if (targetBlankOpenerProtection !== void 0) capabilities.add("target-blank-needs-explicit-protection");
|
|
71095
72011
|
if (targetBlankOpenerProtection === "noreferrer") capabilities.add("target-blank-needs-noreferrer");
|
|
71096
72012
|
capabilitiesByProject.set(project, capabilities);
|
|
@@ -71120,7 +72036,7 @@ const createSecurityScanSession = (rootDirectory, options) => {
|
|
|
71120
72036
|
const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
|
|
71121
72037
|
const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
|
|
71122
72038
|
const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
|
|
71123
|
-
const enabledScanRules =
|
|
72039
|
+
const enabledScanRules = REACT_DOCTOR_SCAN_RULES.flatMap((entry) => {
|
|
71124
72040
|
const rule = entry.rule;
|
|
71125
72041
|
const scan = rule.scan;
|
|
71126
72042
|
if (typeof scan !== "function") return [];
|
|
@@ -71581,47 +72497,55 @@ const resolveDeadCodeConcurrency = (facts = readSystemFacts()) => {
|
|
|
71581
72497
|
const memoryBoundedWorkers = Math.floor(availableMemoryBytes / DEAD_CODE_WORKER_MEM_BUDGET_BYTES);
|
|
71582
72498
|
return Math.max(1, Math.min(facts.availableCores, memoryBoundedWorkers));
|
|
71583
72499
|
};
|
|
71584
|
-
|
|
71585
|
-
|
|
71586
|
-
const
|
|
71587
|
-
const
|
|
71588
|
-
|
|
71589
|
-
|
|
72500
|
+
const createWorkerSlots = (input) => {
|
|
72501
|
+
let availableSlotCount = input.slotCount;
|
|
72502
|
+
const waiters = [];
|
|
72503
|
+
const releaseSlot = () => {
|
|
72504
|
+
const nextWaiter = waiters.shift();
|
|
72505
|
+
if (nextWaiter === void 0) {
|
|
72506
|
+
availableSlotCount += 1;
|
|
72507
|
+
return;
|
|
72508
|
+
}
|
|
72509
|
+
nextWaiter.abortSignal?.removeEventListener("abort", nextWaiter.onAbort);
|
|
72510
|
+
nextWaiter.resolve();
|
|
72511
|
+
};
|
|
72512
|
+
const acquireSlot = async (abortSignal) => {
|
|
72513
|
+
if (abortSignal?.aborted) throw input.createAbortError();
|
|
72514
|
+
if (availableSlotCount > 0) {
|
|
72515
|
+
availableSlotCount -= 1;
|
|
72516
|
+
return;
|
|
72517
|
+
}
|
|
72518
|
+
await new Promise((resolve, reject) => {
|
|
72519
|
+
const onAbort = () => {
|
|
72520
|
+
const waiterIndex = waiters.indexOf(waiter);
|
|
72521
|
+
if (waiterIndex !== -1) waiters.splice(waiterIndex, 1);
|
|
72522
|
+
reject(input.createAbortError());
|
|
72523
|
+
};
|
|
72524
|
+
const waiter = {
|
|
72525
|
+
resolve,
|
|
72526
|
+
abortSignal,
|
|
72527
|
+
onAbort
|
|
72528
|
+
};
|
|
72529
|
+
waiters.push(waiter);
|
|
72530
|
+
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
72531
|
+
});
|
|
72532
|
+
};
|
|
72533
|
+
return { run: async (task, abortSignal) => {
|
|
72534
|
+
await acquireSlot(abortSignal);
|
|
72535
|
+
try {
|
|
72536
|
+
return await task();
|
|
72537
|
+
} finally {
|
|
72538
|
+
releaseSlot();
|
|
72539
|
+
}
|
|
72540
|
+
} };
|
|
71590
72541
|
};
|
|
71591
|
-
|
|
71592
|
-
* Runs `task` once a dead-code worker slot is free, releasing the slot when the
|
|
71593
|
-
* task settles (success or failure). With a high cap (roomy machine) every
|
|
71594
|
-
* caller proceeds immediately; with a low cap (constrained runner) callers
|
|
71595
|
-
* queue and run as slots free.
|
|
71596
|
-
*
|
|
71597
|
-
* `abortSignal` short-circuits the WAIT: if it's already aborted, or fires while
|
|
71598
|
-
* this caller is queued, the call rejects without acquiring a slot or running
|
|
71599
|
-
* `task` — so a cancelled scan (e.g. lint failed) doesn't sit in the queue and
|
|
71600
|
-
* then spawn a child only to tear it down. A queued caller that aborts removes
|
|
71601
|
-
* its own waiter so a later release never hands a slot to a dead request.
|
|
71602
|
-
*/
|
|
72542
|
+
let deadCodeWorkerSlots = null;
|
|
71603
72543
|
const withDeadCodeWorkerSlot = async (task, abortSignal) => {
|
|
71604
|
-
|
|
71605
|
-
|
|
71606
|
-
|
|
71607
|
-
else await new Promise((resolve, reject) => {
|
|
71608
|
-
const waiter = () => {
|
|
71609
|
-
abortSignal?.removeEventListener("abort", onAbort);
|
|
71610
|
-
resolve();
|
|
71611
|
-
};
|
|
71612
|
-
const onAbort = () => {
|
|
71613
|
-
const queuedIndex = waiters.indexOf(waiter);
|
|
71614
|
-
if (queuedIndex !== -1) waiters.splice(queuedIndex, 1);
|
|
71615
|
-
reject(/* @__PURE__ */ new Error("Dead-code worker aborted."));
|
|
71616
|
-
};
|
|
71617
|
-
waiters.push(waiter);
|
|
71618
|
-
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
72544
|
+
deadCodeWorkerSlots ??= createWorkerSlots({
|
|
72545
|
+
slotCount: resolveDeadCodeConcurrency(),
|
|
72546
|
+
createAbortError: () => /* @__PURE__ */ new Error("Dead-code worker aborted.")
|
|
71619
72547
|
});
|
|
71620
|
-
|
|
71621
|
-
return await task();
|
|
71622
|
-
} finally {
|
|
71623
|
-
releaseSlot();
|
|
71624
|
-
}
|
|
72548
|
+
return deadCodeWorkerSlots.run(task, abortSignal);
|
|
71625
72549
|
};
|
|
71626
72550
|
const projectCacheSubdir = (projectDirectory) => crypto.createHash("sha256").update(projectDirectory).digest("hex").slice(0, 16);
|
|
71627
72551
|
const resolveReactDoctorCacheDir = (projectDirectory) => {
|
|
@@ -72414,7 +73338,10 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
72414
73338
|
if (argvLengthChars > spawnArgsLengthCap) return yield* foldSpawnFailure(`spawn ENAMETOOLONG (${argvLengthChars} argv chars exceed ${spawnArgsLengthCap})`);
|
|
72415
73339
|
const handle = yield* spawner.spawn(make$1(input.command, [...input.args], {
|
|
72416
73340
|
cwd: input.directory,
|
|
72417
|
-
env: input.
|
|
73341
|
+
env: input.command === "git" ? {
|
|
73342
|
+
...input.env,
|
|
73343
|
+
GIT_DIR: void 0
|
|
73344
|
+
} : input.env,
|
|
72418
73345
|
extendEnv: true
|
|
72419
73346
|
}));
|
|
72420
73347
|
const maxStdoutBytes = input.maxStdoutBytes;
|
|
@@ -72687,7 +73614,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
72687
73614
|
"--diff-filter=ACMR",
|
|
72688
73615
|
"--relative"
|
|
72689
73616
|
]).pipe(map$3((result) => {
|
|
72690
|
-
if (result.status !== 0) return
|
|
73617
|
+
if (result.status !== 0) return null;
|
|
72691
73618
|
return splitNullSeparated(result.stdout);
|
|
72692
73619
|
})),
|
|
72693
73620
|
showStagedContent: (directory, relativePath, options) => runCommand({
|
|
@@ -72972,7 +73899,11 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
|
|
|
72972
73899
|
const ROOT_DIRECTORY_PLACEHOLDER = "<root>";
|
|
72973
73900
|
const normalizeConfigForHash = (config) => {
|
|
72974
73901
|
const clone = JSON.parse(JSON.stringify(config));
|
|
72975
|
-
if (clone?.settings?.["react-doctor"])
|
|
73902
|
+
if (clone?.settings?.["react-doctor"]) {
|
|
73903
|
+
const reactDoctorSettings = clone.settings["react-doctor"];
|
|
73904
|
+
reactDoctorSettings.rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
|
|
73905
|
+
if (Array.isArray(reactDoctorSettings.unpluginAutoImportRootDirectories)) reactDoctorSettings.unpluginAutoImportRootDirectories = [ROOT_DIRECTORY_PLACEHOLDER];
|
|
73906
|
+
}
|
|
72976
73907
|
if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
|
|
72977
73908
|
return clone;
|
|
72978
73909
|
};
|
|
@@ -73131,21 +74062,22 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
73131
74062
|
}
|
|
73132
74063
|
return enabled;
|
|
73133
74064
|
};
|
|
73134
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
|
|
74065
|
+
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 }) => {
|
|
73135
74066
|
const hasIncludedTags = includedTags.size > 0;
|
|
73136
74067
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
|
|
73137
74068
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
73138
74069
|
const jsPlugins = [];
|
|
73139
74070
|
if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
|
|
73140
74071
|
const capabilities = getCapabilities(project);
|
|
74072
|
+
const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
|
|
73141
74073
|
const enabledReactDoctorRules = {};
|
|
73142
74074
|
for (const registryEntry of REACT_DOCTOR_RULES) {
|
|
73143
|
-
const rule =
|
|
74075
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[registryEntry.id];
|
|
73144
74076
|
if (!rule) continue;
|
|
73145
74077
|
if (ruleSelection === "cacheable" && CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
73146
74078
|
if (ruleSelection === "sidecar" && !CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
73147
74079
|
if (ruleSelection === "sidecar" && sidecarRuleIdFilter !== void 0 && !sidecarRuleIdFilter.has(registryEntry.id)) continue;
|
|
73148
|
-
if (rule.
|
|
74080
|
+
if (rule.isScanRule) continue;
|
|
73149
74081
|
if (customRulesOnly && registryEntry.originallyExternal) continue;
|
|
73150
74082
|
if (rule.framework !== "global" && !rule.requires) continue;
|
|
73151
74083
|
if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
|
|
@@ -73183,8 +74115,16 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
73183
74115
|
jsPlugins: [...jsPlugins, pluginPath],
|
|
73184
74116
|
settings: { "react-doctor": {
|
|
73185
74117
|
framework: project.framework,
|
|
73186
|
-
rootDirectory:
|
|
74118
|
+
rootDirectory: settingsRootDirectory,
|
|
73187
74119
|
capabilities: [...capabilities].sort(),
|
|
74120
|
+
...runtimeGlobals && runtimeGlobals.length > 0 ? { runtimeGlobals: [...runtimeGlobals] } : {},
|
|
74121
|
+
...unpluginAutoImportGlobalScopes && unpluginAutoImportGlobalScopes.length > 0 ? {
|
|
74122
|
+
unpluginAutoImportRootDirectories: [...new Set([settingsRootDirectory, project.rootDirectory])],
|
|
74123
|
+
unpluginAutoImportGlobalScopes: unpluginAutoImportGlobalScopes.map((scope) => ({
|
|
74124
|
+
directory: scope.directory,
|
|
74125
|
+
names: [...scope.names]
|
|
74126
|
+
}))
|
|
74127
|
+
} : {},
|
|
73188
74128
|
...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
|
|
73189
74129
|
...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
|
|
73190
74130
|
} },
|
|
@@ -73195,6 +74135,245 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
73195
74135
|
}
|
|
73196
74136
|
};
|
|
73197
74137
|
};
|
|
74138
|
+
const AUTO_IMPORT_ADAPTER_PATTERN = /^unplugin-auto-import\/(?:astro|esbuild|rollup|rolldown|rspack|vite|webpack)$/;
|
|
74139
|
+
const CONFIG_BASENAMES = [
|
|
74140
|
+
"astro.config",
|
|
74141
|
+
"esbuild.config",
|
|
74142
|
+
"rollup.config",
|
|
74143
|
+
"rolldown.config",
|
|
74144
|
+
"rspack.config",
|
|
74145
|
+
"vite.config",
|
|
74146
|
+
"webpack.config"
|
|
74147
|
+
];
|
|
74148
|
+
const CONFIG_EXTENSIONS = [
|
|
74149
|
+
".cjs",
|
|
74150
|
+
".cts",
|
|
74151
|
+
".js",
|
|
74152
|
+
".mjs",
|
|
74153
|
+
".mts",
|
|
74154
|
+
".ts"
|
|
74155
|
+
];
|
|
74156
|
+
const CONFIG_FILENAMES = new Set(CONFIG_BASENAMES.flatMap((basename) => CONFIG_EXTENSIONS.map((extension) => `${basename}${extension}`)));
|
|
74157
|
+
const DEFAULT_ESLINT_GLOBALS_PATH = ".eslintrc-auto-import.json";
|
|
74158
|
+
const SUPPORTED_GLOBAL_VALUES = new Set([
|
|
74159
|
+
true,
|
|
74160
|
+
false,
|
|
74161
|
+
"readable",
|
|
74162
|
+
"readonly",
|
|
74163
|
+
"writable",
|
|
74164
|
+
"writeable"
|
|
74165
|
+
]);
|
|
74166
|
+
const getStaticProperty = (objectExpression, propertyName) => objectExpression.properties.find((property) => {
|
|
74167
|
+
if (ts.isSpreadAssignment(property)) return false;
|
|
74168
|
+
const name = ts.isComputedPropertyName(property.name) ? unwrapTypescriptExpression(property.name.expression) : property.name;
|
|
74169
|
+
return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && name.text === propertyName;
|
|
74170
|
+
}) ?? null;
|
|
74171
|
+
const hasNonLiteralComputedProperty = (objectExpression) => objectExpression.properties.some((property) => !ts.isSpreadAssignment(property) && ts.isComputedPropertyName(property.name) && !ts.isStringLiteralLike(unwrapTypescriptExpression(property.name.expression)));
|
|
74172
|
+
const getStaticPropertyAssignment = (objectExpression, propertyName) => {
|
|
74173
|
+
const property = getStaticProperty(objectExpression, propertyName);
|
|
74174
|
+
return property && ts.isPropertyAssignment(property) ? property : null;
|
|
74175
|
+
};
|
|
74176
|
+
const getRequireModuleSpecifier = (expression) => {
|
|
74177
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
74178
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === "default") return getRequireModuleSpecifier(unwrappedExpression.expression);
|
|
74179
|
+
if (!ts.isCallExpression(unwrappedExpression) || !ts.isIdentifier(unwrappedExpression.expression) || unwrappedExpression.expression.text !== "require" || unwrappedExpression.arguments.length !== 1) return null;
|
|
74180
|
+
const moduleSpecifier = unwrappedExpression.arguments[0];
|
|
74181
|
+
return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
|
|
74182
|
+
};
|
|
74183
|
+
const getRequiredPropertyModuleSpecifier = (expression, propertyName) => {
|
|
74184
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
74185
|
+
return ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === propertyName ? getRequireModuleSpecifier(unwrappedExpression.expression) : null;
|
|
74186
|
+
};
|
|
74187
|
+
const isCommonJsExportAssignment = (node, sourceFile) => ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken && (node.left.getText(sourceFile) === "module.exports" || node.left.getText(sourceFile) === "exports.default");
|
|
74188
|
+
const isTopLevelExpression = (node) => {
|
|
74189
|
+
let ancestor = node.parent;
|
|
74190
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
74191
|
+
if (ts.isExpressionStatement(ancestor)) return ts.isSourceFile(ancestor.parent);
|
|
74192
|
+
if (!ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isAwaitExpression(ancestor)) return false;
|
|
74193
|
+
ancestor = ancestor.parent;
|
|
74194
|
+
}
|
|
74195
|
+
return false;
|
|
74196
|
+
};
|
|
74197
|
+
const isInsideActiveConfigProperty = (node, propertyName, sourceFile, esbuildBindings, esbuildNamespaceBindings) => {
|
|
74198
|
+
let ancestor = node.parent;
|
|
74199
|
+
let didFindConfigProperty = false;
|
|
74200
|
+
while (ancestor && !ts.isSourceFile(ancestor)) {
|
|
74201
|
+
if (!didFindConfigProperty && !ts.isArrayLiteralExpression(ancestor) && !ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isPropertyAssignment(ancestor)) return false;
|
|
74202
|
+
if (ts.isPropertyAssignment(ancestor)) {
|
|
74203
|
+
const isConfigProperty = (ts.isIdentifier(ancestor.name) || ts.isStringLiteralLike(ancestor.name)) && ancestor.name.text === propertyName;
|
|
74204
|
+
if (didFindConfigProperty || !isConfigProperty) return false;
|
|
74205
|
+
if (!ts.isObjectLiteralExpression(ancestor.parent) || ancestor.parent.properties.some(ts.isSpreadAssignment)) return false;
|
|
74206
|
+
didFindConfigProperty = true;
|
|
74207
|
+
ancestor = ancestor.parent;
|
|
74208
|
+
continue;
|
|
74209
|
+
}
|
|
74210
|
+
if (didFindConfigProperty) {
|
|
74211
|
+
if (ts.isExportAssignment(ancestor)) return true;
|
|
74212
|
+
if (isCommonJsExportAssignment(ancestor, sourceFile)) return isTopLevelExpression(ancestor);
|
|
74213
|
+
if (propertyName === "plugins" && ts.isCallExpression(ancestor) && (ts.isIdentifier(ancestor.expression) ? esbuildBindings.has(ancestor.expression.text) : ts.isPropertyAccessExpression(ancestor.expression) && ancestor.expression.name.text === "build" && (ts.isIdentifier(ancestor.expression.expression) && esbuildNamespaceBindings.has(ancestor.expression.expression.text) || getRequireModuleSpecifier(ancestor.expression.expression) === "esbuild"))) return isTopLevelExpression(ancestor);
|
|
74214
|
+
if (!(ts.isObjectLiteralExpression(ancestor) || ts.isParenthesizedExpression(ancestor) || ts.isAsExpression(ancestor) || ts.isSatisfiesExpression(ancestor) || ts.isNonNullExpression(ancestor) || ts.isTypeAssertionExpression(ancestor) || ts.isCallExpression(ancestor) && ts.isIdentifier(ancestor.expression) && ancestor.expression.text === "defineConfig")) return false;
|
|
74215
|
+
}
|
|
74216
|
+
ancestor = ancestor.parent;
|
|
74217
|
+
}
|
|
74218
|
+
return false;
|
|
74219
|
+
};
|
|
74220
|
+
const getGlobalsPathFromActiveAutoImportCall = (callExpression, packageDirectory) => {
|
|
74221
|
+
const optionsExpression = callExpression.arguments[0];
|
|
74222
|
+
if (!optionsExpression) return null;
|
|
74223
|
+
const unwrappedOptions = unwrapTypescriptExpression(optionsExpression);
|
|
74224
|
+
if (!ts.isObjectLiteralExpression(unwrappedOptions)) return null;
|
|
74225
|
+
if (unwrappedOptions.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(unwrappedOptions)) return null;
|
|
74226
|
+
if (getStaticProperty(unwrappedOptions, "include") || getStaticProperty(unwrappedOptions, "exclude")) return null;
|
|
74227
|
+
const eslintrcProperty = getStaticPropertyAssignment(unwrappedOptions, "eslintrc");
|
|
74228
|
+
if (!eslintrcProperty) return null;
|
|
74229
|
+
const eslintrcExpression = unwrapTypescriptExpression(eslintrcProperty.initializer);
|
|
74230
|
+
if (!ts.isObjectLiteralExpression(eslintrcExpression)) return null;
|
|
74231
|
+
if (eslintrcExpression.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(eslintrcExpression)) return null;
|
|
74232
|
+
const enabledProperty = getStaticPropertyAssignment(eslintrcExpression, "enabled");
|
|
74233
|
+
if (!enabledProperty || unwrapTypescriptExpression(enabledProperty.initializer).kind !== ts.SyntaxKind.TrueKeyword) return null;
|
|
74234
|
+
const filepathProperty = getStaticProperty(eslintrcExpression, "filepath");
|
|
74235
|
+
if (!filepathProperty) return Path.join(packageDirectory, DEFAULT_ESLINT_GLOBALS_PATH);
|
|
74236
|
+
if (!ts.isPropertyAssignment(filepathProperty)) return null;
|
|
74237
|
+
const filepathExpression = unwrapTypescriptExpression(filepathProperty.initializer);
|
|
74238
|
+
return ts.isStringLiteralLike(filepathExpression) ? Path.resolve(packageDirectory, filepathExpression.text) : null;
|
|
74239
|
+
};
|
|
74240
|
+
const collectGlobalsPathsFromConfig = (configPath, packageDirectory) => {
|
|
74241
|
+
let sourceText;
|
|
74242
|
+
try {
|
|
74243
|
+
sourceText = NFS.readFileSync(configPath, "utf8");
|
|
74244
|
+
} catch {
|
|
74245
|
+
return {
|
|
74246
|
+
didFindActiveAutoImport: false,
|
|
74247
|
+
globalsPaths: []
|
|
74248
|
+
};
|
|
74249
|
+
}
|
|
74250
|
+
const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true);
|
|
74251
|
+
const autoImportBindings = /* @__PURE__ */ new Map();
|
|
74252
|
+
const esbuildBindings = /* @__PURE__ */ new Set();
|
|
74253
|
+
const esbuildNamespaceBindings = /* @__PURE__ */ new Set();
|
|
74254
|
+
for (const statement of sourceFile.statements) {
|
|
74255
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
74256
|
+
const moduleSpecifier = statement.moduleSpecifier.text;
|
|
74257
|
+
if (AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
74258
|
+
const defaultBinding = statement.importClause?.name;
|
|
74259
|
+
if (defaultBinding) autoImportBindings.set(defaultBinding.text, moduleSpecifier);
|
|
74260
|
+
}
|
|
74261
|
+
if (moduleSpecifier === "esbuild") {
|
|
74262
|
+
const defaultBinding = statement.importClause?.name;
|
|
74263
|
+
if (defaultBinding) esbuildNamespaceBindings.add(defaultBinding.text);
|
|
74264
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
74265
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
74266
|
+
for (const importSpecifier of namedBindings.elements) if ((importSpecifier.propertyName ?? importSpecifier.name).text === "build") esbuildBindings.add(importSpecifier.name.text);
|
|
74267
|
+
}
|
|
74268
|
+
if (namedBindings && ts.isNamespaceImport(namedBindings)) esbuildNamespaceBindings.add(namedBindings.name.text);
|
|
74269
|
+
}
|
|
74270
|
+
}
|
|
74271
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
74272
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
74273
|
+
if (!declaration.initializer) continue;
|
|
74274
|
+
const declarationName = ts.isIdentifier(declaration.name) ? declaration.name.text : null;
|
|
74275
|
+
const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
|
|
74276
|
+
if (declarationName && moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) autoImportBindings.set(declarationName, moduleSpecifier);
|
|
74277
|
+
if (moduleSpecifier === "esbuild") {
|
|
74278
|
+
if (declarationName) esbuildNamespaceBindings.add(declarationName);
|
|
74279
|
+
if (ts.isObjectBindingPattern(declaration.name)) for (const bindingElement of declaration.name.elements) {
|
|
74280
|
+
const importedName = bindingElement.propertyName ?? bindingElement.name;
|
|
74281
|
+
if (ts.isIdentifier(importedName) && importedName.text === "build" && ts.isIdentifier(bindingElement.name)) esbuildBindings.add(bindingElement.name.text);
|
|
74282
|
+
}
|
|
74283
|
+
}
|
|
74284
|
+
if (declarationName && getRequiredPropertyModuleSpecifier(declaration.initializer, "build") === "esbuild") esbuildBindings.add(declarationName);
|
|
74285
|
+
}
|
|
74286
|
+
}
|
|
74287
|
+
const globalsPaths = /* @__PURE__ */ new Set();
|
|
74288
|
+
let didFindActiveAutoImport = false;
|
|
74289
|
+
let didFindUnsafeActiveAutoImport = false;
|
|
74290
|
+
const visit = (node) => {
|
|
74291
|
+
if (ts.isCallExpression(node)) {
|
|
74292
|
+
const moduleSpecifier = ts.isIdentifier(node.expression) ? autoImportBindings.get(node.expression.text) : getRequireModuleSpecifier(node.expression);
|
|
74293
|
+
if (moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
|
|
74294
|
+
if (isInsideActiveConfigProperty(node, moduleSpecifier.endsWith("/astro") ? "integrations" : "plugins", sourceFile, esbuildBindings, esbuildNamespaceBindings)) {
|
|
74295
|
+
didFindActiveAutoImport = true;
|
|
74296
|
+
const globalsPath = getGlobalsPathFromActiveAutoImportCall(node, packageDirectory);
|
|
74297
|
+
if (globalsPath) globalsPaths.add(globalsPath);
|
|
74298
|
+
else didFindUnsafeActiveAutoImport = true;
|
|
74299
|
+
}
|
|
74300
|
+
}
|
|
74301
|
+
}
|
|
74302
|
+
ts.forEachChild(node, visit);
|
|
74303
|
+
};
|
|
74304
|
+
visit(sourceFile);
|
|
74305
|
+
return {
|
|
74306
|
+
didFindActiveAutoImport,
|
|
74307
|
+
globalsPaths: didFindUnsafeActiveAutoImport ? [] : [...globalsPaths]
|
|
74308
|
+
};
|
|
74309
|
+
};
|
|
74310
|
+
const collectGeneratedGlobalNames = (globalsPath, rootDirectory) => {
|
|
74311
|
+
const relativePath = Path.relative(rootDirectory, globalsPath);
|
|
74312
|
+
if (relativePath.startsWith("..") || Path.isAbsolute(relativePath)) return [];
|
|
74313
|
+
const parsed = failOpenReadJson(globalsPath, null);
|
|
74314
|
+
if (!isPlainObject(parsed) || !isPlainObject(parsed.globals)) return [];
|
|
74315
|
+
return Object.entries(parsed.globals).filter((entry) => entry[0].length > 0 && (typeof entry[1] === "boolean" || typeof entry[1] === "string") && SUPPORTED_GLOBAL_VALUES.has(entry[1])).map(([name]) => name).sort();
|
|
74316
|
+
};
|
|
74317
|
+
const findOwningPackageDirectory = (absoluteFilePath, rootDirectory, cache) => {
|
|
74318
|
+
let currentDirectory = Path.dirname(absoluteFilePath);
|
|
74319
|
+
const visitedDirectories = [];
|
|
74320
|
+
while (true) {
|
|
74321
|
+
const cachedDirectory = cache.get(currentDirectory);
|
|
74322
|
+
if (cachedDirectory !== void 0) {
|
|
74323
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, cachedDirectory);
|
|
74324
|
+
return cachedDirectory;
|
|
74325
|
+
}
|
|
74326
|
+
const relativeDirectory = Path.relative(rootDirectory, currentDirectory);
|
|
74327
|
+
if (relativeDirectory.startsWith("..") || Path.isAbsolute(relativeDirectory)) {
|
|
74328
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
74329
|
+
return null;
|
|
74330
|
+
}
|
|
74331
|
+
visitedDirectories.push(currentDirectory);
|
|
74332
|
+
if (NFS.existsSync(Path.join(currentDirectory, "package.json"))) {
|
|
74333
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, currentDirectory);
|
|
74334
|
+
return currentDirectory;
|
|
74335
|
+
}
|
|
74336
|
+
if (currentDirectory === rootDirectory) {
|
|
74337
|
+
for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
|
|
74338
|
+
return null;
|
|
74339
|
+
}
|
|
74340
|
+
currentDirectory = Path.dirname(currentDirectory);
|
|
74341
|
+
}
|
|
74342
|
+
};
|
|
74343
|
+
const collectPackageGlobalNames = (packageDirectory, rootDirectory) => {
|
|
74344
|
+
let directoryEntries;
|
|
74345
|
+
try {
|
|
74346
|
+
directoryEntries = NFS.readdirSync(packageDirectory, { withFileTypes: true });
|
|
74347
|
+
} catch {
|
|
74348
|
+
return [];
|
|
74349
|
+
}
|
|
74350
|
+
const configuredGlobalsPaths = [];
|
|
74351
|
+
for (const entry of directoryEntries) {
|
|
74352
|
+
if (!entry.isFile() && !entry.isSymbolicLink() || !CONFIG_FILENAMES.has(entry.name)) continue;
|
|
74353
|
+
const configGlobalsPaths = collectGlobalsPathsFromConfig(Path.join(packageDirectory, entry.name), packageDirectory);
|
|
74354
|
+
if (configGlobalsPaths.didFindActiveAutoImport) configuredGlobalsPaths.push(configGlobalsPaths.globalsPaths.toSorted());
|
|
74355
|
+
}
|
|
74356
|
+
if (configuredGlobalsPaths.length === 0) return [];
|
|
74357
|
+
const globalsPaths = configuredGlobalsPaths[0];
|
|
74358
|
+
if (configuredGlobalsPaths.some((candidatePaths) => candidatePaths.length !== globalsPaths.length || candidatePaths.some((candidatePath, index) => candidatePath !== globalsPaths[index]))) return [];
|
|
74359
|
+
const names = /* @__PURE__ */ new Set();
|
|
74360
|
+
for (const globalsPath of globalsPaths) for (const name of collectGeneratedGlobalNames(globalsPath, rootDirectory)) names.add(name);
|
|
74361
|
+
return [...names].sort();
|
|
74362
|
+
};
|
|
74363
|
+
const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }) => {
|
|
74364
|
+
const absoluteRootDirectory = Path.resolve(rootDirectory);
|
|
74365
|
+
const packageDirectoryCache = /* @__PURE__ */ new Map();
|
|
74366
|
+
const packageDirectories = /* @__PURE__ */ new Set();
|
|
74367
|
+
for (const candidateFile of candidateFiles) {
|
|
74368
|
+
const packageDirectory = findOwningPackageDirectory(Path.resolve(absoluteRootDirectory, candidateFile), absoluteRootDirectory, packageDirectoryCache);
|
|
74369
|
+
if (packageDirectory) packageDirectories.add(packageDirectory);
|
|
74370
|
+
}
|
|
74371
|
+
const scopes = [...packageDirectories].map((packageDirectory) => ({
|
|
74372
|
+
directory: Path.relative(absoluteRootDirectory, packageDirectory).replaceAll("\\", "/"),
|
|
74373
|
+
names: collectPackageGlobalNames(packageDirectory, absoluteRootDirectory)
|
|
74374
|
+
})).sort((firstScope, secondScope) => firstScope.directory.localeCompare(secondScope.directory));
|
|
74375
|
+
return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
|
|
74376
|
+
};
|
|
73198
74377
|
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
73199
74378
|
const decodeFileDiagnostics = (raw) => {
|
|
73200
74379
|
if (!Array.isArray(raw)) return null;
|
|
@@ -73517,6 +74696,56 @@ const appendReanimatedSharedValueHint = (help, rule, project) => {
|
|
|
73517
74696
|
if (!help) return REANIMATED_SHARED_VALUE_HINT;
|
|
73518
74697
|
return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
|
|
73519
74698
|
};
|
|
74699
|
+
const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
74700
|
+
const boundedOffset = Math.min(Math.max(utf8Offset, 0), sourceBuffer.length);
|
|
74701
|
+
let lineStartOffset = boundedOffset;
|
|
74702
|
+
while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
|
|
74703
|
+
return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
|
|
74704
|
+
};
|
|
74705
|
+
const utf8OffsetFromSourcePosition = (sourceBuffer, lineNumber, zeroBasedColumn) => {
|
|
74706
|
+
if (lineNumber < 1 || zeroBasedColumn < 0) return null;
|
|
74707
|
+
const sourceLines = sourceBuffer.toString("utf8").split("\n");
|
|
74708
|
+
const sourceLine = sourceLines[lineNumber - 1];
|
|
74709
|
+
if (sourceLine === void 0 || zeroBasedColumn > sourceLine.length) return null;
|
|
74710
|
+
const precedingLines = sourceLines.slice(0, lineNumber - 1).join("\n");
|
|
74711
|
+
return (lineNumber === 1 ? 0 : Buffer.byteLength(precedingLines) + Buffer.byteLength("\n")) + Buffer.byteLength(sourceLine.slice(0, zeroBasedColumn));
|
|
74712
|
+
};
|
|
74713
|
+
const mapPreparedSourceSpan = (span, preparedSourceMap) => {
|
|
74714
|
+
const generatedLine = lineOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset);
|
|
74715
|
+
const generatedColumn = columnOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset) - 1;
|
|
74716
|
+
const originalStart = originalPositionFor(preparedSourceMap.traceMap, {
|
|
74717
|
+
line: generatedLine,
|
|
74718
|
+
column: generatedColumn
|
|
74719
|
+
});
|
|
74720
|
+
if (originalStart.source === null || originalStart.line === null || originalStart.column === null) return null;
|
|
74721
|
+
const originalOffset = utf8OffsetFromSourcePosition(preparedSourceMap.sourceBuffer, originalStart.line, originalStart.column);
|
|
74722
|
+
if (originalOffset === null) return null;
|
|
74723
|
+
const generatedSpan = preparedSourceMap.generatedBuffer.subarray(span.offset, span.offset + span.length);
|
|
74724
|
+
return {
|
|
74725
|
+
offset: originalOffset,
|
|
74726
|
+
length: preparedSourceMap.sourceBuffer.subarray(originalOffset, originalOffset + generatedSpan.length).equals(generatedSpan) ? generatedSpan.length : 0,
|
|
74727
|
+
line: originalStart.line,
|
|
74728
|
+
column: originalStart.column + 1
|
|
74729
|
+
};
|
|
74730
|
+
};
|
|
74731
|
+
const mapPreparedSourceLabels = (labels, preparedSourceMap) => {
|
|
74732
|
+
const primaryLabel = labels[0];
|
|
74733
|
+
if (primaryLabel === void 0) return null;
|
|
74734
|
+
const primarySpan = mapPreparedSourceSpan(primaryLabel.span, preparedSourceMap);
|
|
74735
|
+
if (primarySpan === null) return null;
|
|
74736
|
+
const mappedLabels = [{
|
|
74737
|
+
...primaryLabel,
|
|
74738
|
+
span: primarySpan
|
|
74739
|
+
}];
|
|
74740
|
+
for (const relatedLabel of labels.slice(1)) {
|
|
74741
|
+
const relatedSpan = mapPreparedSourceSpan(relatedLabel.span, preparedSourceMap);
|
|
74742
|
+
if (relatedSpan !== null) mappedLabels.push({
|
|
74743
|
+
...relatedLabel,
|
|
74744
|
+
span: relatedSpan
|
|
74745
|
+
});
|
|
74746
|
+
}
|
|
74747
|
+
return mappedLabels;
|
|
74748
|
+
};
|
|
73520
74749
|
const REDACTED_PLACEHOLDER = "<redacted>";
|
|
73521
74750
|
const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
|
|
73522
74751
|
const KNOWN_SECRET_RULES = [
|
|
@@ -74159,7 +75388,7 @@ const PLUGIN_CATEGORY_MAP = {
|
|
|
74159
75388
|
};
|
|
74160
75389
|
const lookupOwnString = (record, key) => Object.hasOwn(record, key) ? record[key] : void 0;
|
|
74161
75390
|
const getRuleRecommendation = (ruleName, project) => {
|
|
74162
|
-
const rule =
|
|
75391
|
+
const rule = REACT_DOCTOR_RULE_REGISTRY[ruleName];
|
|
74163
75392
|
if (!rule) return void 0;
|
|
74164
75393
|
if (rule.recommendationFor) {
|
|
74165
75394
|
const capabilities = getCapabilities(project);
|
|
@@ -74168,8 +75397,8 @@ const getRuleRecommendation = (ruleName, project) => {
|
|
|
74168
75397
|
}
|
|
74169
75398
|
return rule.recommendation;
|
|
74170
75399
|
};
|
|
74171
|
-
const getRuleCategory = (ruleName) =>
|
|
74172
|
-
const getRuleTitle = (ruleName) =>
|
|
75400
|
+
const getRuleCategory = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.category;
|
|
75401
|
+
const getRuleTitle = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.title;
|
|
74173
75402
|
const resolveDiagnosticTitle = (plugin, rule) => {
|
|
74174
75403
|
if (plugin !== "react-hooks-js") return getRuleTitle(rule);
|
|
74175
75404
|
if (rule === "error-boundaries") return REACT_ERROR_BOUNDARY_TITLE;
|
|
@@ -74224,7 +75453,7 @@ const resolveDiagnosticCategory = (plugin, rule) => {
|
|
|
74224
75453
|
if (plugin === "react-hooks-js" && rule === "error-boundaries") return "Bugs";
|
|
74225
75454
|
return getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
|
|
74226
75455
|
};
|
|
74227
|
-
const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(
|
|
75456
|
+
const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(REACT_DOCTOR_RULE_REGISTRY[rule]?.matchByOccurrence);
|
|
74228
75457
|
/**
|
|
74229
75458
|
* Maps oxlint's non-primary labels (`labels[1..]`) into related source
|
|
74230
75459
|
* locations. Editors surface these as a diagnostic's
|
|
@@ -74232,7 +75461,7 @@ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORI
|
|
|
74232
75461
|
* with empty text still carry a useful jump target, so they're kept
|
|
74233
75462
|
* with a neutral message.
|
|
74234
75463
|
*/
|
|
74235
|
-
const buildRelatedLocations = (labels, filePath) => {
|
|
75464
|
+
const buildRelatedLocations = (labels, filePath, sourceBuffer) => {
|
|
74236
75465
|
if (labels.length <= 1) return [];
|
|
74237
75466
|
const related = [];
|
|
74238
75467
|
for (let labelIndex = 1; labelIndex < labels.length; labelIndex++) {
|
|
@@ -74240,8 +75469,8 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
74240
75469
|
if (!label?.span) continue;
|
|
74241
75470
|
related.push({
|
|
74242
75471
|
filePath,
|
|
74243
|
-
line: label.span.line ?? 0,
|
|
74244
|
-
column: label.span.column ?? 0,
|
|
75472
|
+
line: sourceBuffer === null ? label.span.line ?? 0 : lineOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
75473
|
+
column: sourceBuffer === null ? label.span.column ?? 0 : columnOfUtf8Offset(sourceBuffer, label.span.offset),
|
|
74245
75474
|
offset: label.span.offset,
|
|
74246
75475
|
length: label.span.length,
|
|
74247
75476
|
message: label.label ?? ""
|
|
@@ -74261,7 +75490,7 @@ const isOxlintOutput = (value) => isRecord$1(value) && Array.isArray(value.diagn
|
|
|
74261
75490
|
* to the first `{`. Raises `OxlintOutputUnparseable` when the
|
|
74262
75491
|
* stdout isn't valid JSON or doesn't carry a `diagnostics` array.
|
|
74263
75492
|
*/
|
|
74264
|
-
const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
75493
|
+
const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath) => {
|
|
74265
75494
|
if (!stdout) return [];
|
|
74266
75495
|
const jsonStart = stdout.indexOf("{");
|
|
74267
75496
|
const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
|
|
@@ -74278,8 +75507,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74278
75507
|
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
74279
75508
|
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
74280
75509
|
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
75510
|
+
const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
75511
|
+
const resolvePreparedSourceMap = (filename) => sourceMapByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
|
|
75512
|
+
const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
|
|
74281
75513
|
const readSourceBuffer = (filename) => {
|
|
74282
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
75514
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74283
75515
|
const cached = sourceBufferCache.get(absolutePath);
|
|
74284
75516
|
if (cached !== void 0) return cached;
|
|
74285
75517
|
let sourceBuffer;
|
|
@@ -74292,7 +75524,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74292
75524
|
return sourceBuffer;
|
|
74293
75525
|
};
|
|
74294
75526
|
const readSourceLines = (filename) => {
|
|
74295
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
75527
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74296
75528
|
const cached = sourceLinesCache.get(absolutePath);
|
|
74297
75529
|
if (cached !== void 0) return cached;
|
|
74298
75530
|
const sourceBuffer = readSourceBuffer(filename);
|
|
@@ -74301,27 +75533,42 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74301
75533
|
return sourceLines;
|
|
74302
75534
|
};
|
|
74303
75535
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
74304
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
75536
|
+
const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
|
|
74305
75537
|
const cached = minifiedFileCache.get(absolutePath);
|
|
74306
75538
|
if (cached !== void 0) return cached;
|
|
74307
75539
|
const minified = isMinifiedSource(absolutePath);
|
|
74308
75540
|
minifiedFileCache.set(absolutePath, minified);
|
|
74309
75541
|
return minified;
|
|
74310
75542
|
};
|
|
74311
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.
|
|
75543
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.flatMap((diagnostic) => {
|
|
75544
|
+
const preparedSourceMap = resolvePreparedSourceMap(diagnostic.filename);
|
|
75545
|
+
if (preparedSourceMap === void 0) return [diagnostic];
|
|
75546
|
+
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
75547
|
+
if (plugin !== "react-doctor" || !REACT_DOCTOR_RULE_REGISTRY[rule]?.tags?.includes("design")) return [];
|
|
75548
|
+
const labels = mapPreparedSourceLabels(diagnostic.labels, preparedSourceMap);
|
|
75549
|
+
const sourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
75550
|
+
return labels === null || sourceFilename === void 0 ? [] : [{
|
|
75551
|
+
...diagnostic,
|
|
75552
|
+
filename: sourceFilename,
|
|
75553
|
+
labels
|
|
75554
|
+
}];
|
|
75555
|
+
}).filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(resolveSourceFilename(diagnostic.filename)) && !(TYPESCRIPT_DECLARATION_FILE_PATTERN.test(diagnostic.filename) && OXLINT_IGNORED_DECLARATION_DIAGNOSTIC_CODES.has(diagnostic.code)) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
74312
75556
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
74313
75557
|
const primaryLabel = diagnostic.labels[0];
|
|
74314
75558
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
74315
|
-
const
|
|
75559
|
+
const mappedSourceFilename = resolveMappedSourceFilename(diagnostic.filename);
|
|
75560
|
+
const normalizedFilePath = (mappedSourceFilename ?? diagnostic.filename).replaceAll("\\", "/");
|
|
74316
75561
|
const primarySpan = primaryLabel?.span;
|
|
74317
75562
|
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
74318
|
-
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
75563
|
+
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath, mappedSourceFilename === void 0 ? null : sourceBuffer);
|
|
74319
75564
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
74320
75565
|
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
74321
75566
|
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
74322
|
-
const
|
|
75567
|
+
const primaryLineNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.line ?? 0;
|
|
75568
|
+
const primaryColumnNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? columnOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.column ?? 0;
|
|
75569
|
+
const primaryLineIndex = primarySpan ? primaryLineNumber - 1 : -1;
|
|
74323
75570
|
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
74324
|
-
const primaryColumnIndex = primarySpan ?
|
|
75571
|
+
const primaryColumnIndex = primarySpan ? primaryColumnNumber - 1 : -1;
|
|
74325
75572
|
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
74326
75573
|
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
74327
75574
|
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
@@ -74334,8 +75581,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
74334
75581
|
message: cleaned.message,
|
|
74335
75582
|
help: cleaned.help,
|
|
74336
75583
|
url: diagnostic.url,
|
|
74337
|
-
line:
|
|
74338
|
-
column:
|
|
75584
|
+
line: primaryLineNumber,
|
|
75585
|
+
column: primaryColumnNumber,
|
|
74339
75586
|
...primarySpan ? {
|
|
74340
75587
|
offset: primarySpan.offset,
|
|
74341
75588
|
length: primarySpan.length,
|
|
@@ -74383,11 +75630,12 @@ const SANITIZED_ENV = buildOxlintChildEnv(process.env);
|
|
|
74383
75630
|
* The first three are splittable (the caller's binary-split retry
|
|
74384
75631
|
* shrinks the batch and re-spawns); the fourth isn't.
|
|
74385
75632
|
*/
|
|
74386
|
-
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal) => new Promise((resolve, reject) => {
|
|
75633
|
+
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal, onSpawn) => new Promise((resolve, reject) => {
|
|
74387
75634
|
if (abortSignal?.aborted) {
|
|
74388
75635
|
reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
|
|
74389
75636
|
return;
|
|
74390
75637
|
}
|
|
75638
|
+
onSpawn?.();
|
|
74391
75639
|
const child = spawn(nodeBinaryPath, buildProfiledNodeArguments({
|
|
74392
75640
|
argumentsList: args,
|
|
74393
75641
|
cpuProfileDirectory: SANITIZED_ENV.REACT_DOCTOR_CPU_PROFILE_DIR,
|
|
@@ -74523,7 +75771,11 @@ const isParallelismRelatedSpawnError = (error) => {
|
|
|
74523
75771
|
* loop with a slimmer config in that case.
|
|
74524
75772
|
*/
|
|
74525
75773
|
const spawnLintBatches = async (input) => {
|
|
74526
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75774
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
|
|
75775
|
+
const resolveSourcePath = (filePath) => {
|
|
75776
|
+
const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
|
|
75777
|
+
return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
|
|
75778
|
+
};
|
|
74527
75779
|
const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
|
|
74528
75780
|
let rescueDeadlineEpochMs;
|
|
74529
75781
|
const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
|
|
@@ -74543,7 +75795,21 @@ const spawnLintBatches = async (input) => {
|
|
|
74543
75795
|
}
|
|
74544
75796
|
const batchArgs = [...baseArgs, ...batch];
|
|
74545
75797
|
try {
|
|
74546
|
-
|
|
75798
|
+
const spawnBatch = () => {
|
|
75799
|
+
if (isPastDeadline()) {
|
|
75800
|
+
deadlineSkippedFiles.push(...batch);
|
|
75801
|
+
batchState.deadlineSkippedFileCount += batch.length;
|
|
75802
|
+
return Promise.resolve(null);
|
|
75803
|
+
}
|
|
75804
|
+
return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal, () => {
|
|
75805
|
+
if (batchState.didStart) return;
|
|
75806
|
+
batchState.didStart = true;
|
|
75807
|
+
startedFileCount += batchState.initialFileCount;
|
|
75808
|
+
});
|
|
75809
|
+
};
|
|
75810
|
+
const stdout = input.spawnSlots === void 0 ? await spawnBatch() : await input.spawnSlots.run(spawnBatch, signal);
|
|
75811
|
+
if (stdout === null) return [];
|
|
75812
|
+
return parseOxlintOutput(stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath);
|
|
74547
75813
|
} catch (error) {
|
|
74548
75814
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
74549
75815
|
if (isPastDeadline()) {
|
|
@@ -74587,14 +75853,15 @@ const spawnLintBatches = async (input) => {
|
|
|
74587
75853
|
deadlineSkippedFiles.push(...batch);
|
|
74588
75854
|
return [];
|
|
74589
75855
|
}
|
|
74590
|
-
startedFileCount += batch.length;
|
|
74591
75856
|
const batchState = {
|
|
74592
75857
|
deadlineMs: null,
|
|
74593
|
-
deadlineSkippedFileCount: 0
|
|
75858
|
+
deadlineSkippedFileCount: 0,
|
|
75859
|
+
didStart: false,
|
|
75860
|
+
initialFileCount: batch.length
|
|
74594
75861
|
};
|
|
74595
75862
|
const batchDiagnostics = await spawnLintBatch(batch, 0, batchState);
|
|
74596
75863
|
scannedFileCount += batch.length - batchState.deadlineSkippedFileCount;
|
|
74597
|
-
if (passOnFileProgress) {
|
|
75864
|
+
if (passOnFileProgress && batchState.didStart) {
|
|
74598
75865
|
displayedFileCount = Math.min(Math.max(displayedFileCount, scannedFileCount), totalFileCount);
|
|
74599
75866
|
passOnFileProgress(displayedFileCount, totalFileCount);
|
|
74600
75867
|
}
|
|
@@ -74649,10 +75916,12 @@ const spawnLintBatches = async (input) => {
|
|
|
74649
75916
|
onPartialFailure(buildMessage(`${skippedFiles.slice(0, 3).join(", ")}${skippedFiles.length > 3 ? `, +${skippedFiles.length - 3} more` : ""}`));
|
|
74650
75917
|
};
|
|
74651
75918
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
74652
|
-
|
|
74653
|
-
|
|
75919
|
+
const droppedSourceFiles = [...new Set(droppedFiles.map(resolveSourcePath))];
|
|
75920
|
+
const deadlineSkippedSourceFiles = [...new Set(outcome.deadlineSkippedFiles.map(resolveSourcePath))];
|
|
75921
|
+
reportSkippedFiles(droppedSourceFiles, (fileListPreview) => `${droppedSourceFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
75922
|
+
reportSkippedFiles(deadlineSkippedSourceFiles, (fileListPreview) => `${deadlineSkippedSourceFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
74654
75923
|
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
74655
|
-
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
75924
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)).map(resolveSourcePath))].sort());
|
|
74656
75925
|
return dedupeDiagnostics(diagnostics);
|
|
74657
75926
|
};
|
|
74658
75927
|
let didValidate = false;
|
|
@@ -74676,8 +75945,8 @@ const validateRuleRegistration = () => {
|
|
|
74676
75945
|
for (const fullKey of ALL_REACT_DOCTOR_RULE_KEYS) {
|
|
74677
75946
|
const ruleName = fullKey.replace(/^react-doctor\//, "");
|
|
74678
75947
|
if (!getRuleCategory(ruleName)) missingCategory.push(fullKey);
|
|
74679
|
-
if (!
|
|
74680
|
-
if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !
|
|
75948
|
+
if (!REACT_DOCTOR_RULE_REGISTRY[ruleName]?.recommendation) missingHelp.push(fullKey);
|
|
75949
|
+
if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !REACT_DOCTOR_RULE_REGISTRY[ruleName]?.requires) missingMetadata.push(fullKey);
|
|
74681
75950
|
}
|
|
74682
75951
|
if (missingCategory.length === 0 && missingHelp.length === 0 && missingMetadata.length === 0) return;
|
|
74683
75952
|
const detail = [
|
|
@@ -74751,6 +76020,294 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
|
|
|
74751
76020
|
}
|
|
74752
76021
|
return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
|
|
74753
76022
|
};
|
|
76023
|
+
const THREE_MODULE_IMPORT_PATTERN = /\b(?:from\s*|import\s*(?:\(\s*)?|require\s*\(\s*)["']three(?:\/[^"']*)?["']/;
|
|
76024
|
+
const containsThreeModuleImport = (sourceText) => THREE_MODULE_IMPORT_PATTERN.test(sourceText);
|
|
76025
|
+
const COMMENT_OPEN = "<!--";
|
|
76026
|
+
const COMMENT_CLOSE = "-->";
|
|
76027
|
+
const FRONTMATTER_FENCE = "---";
|
|
76028
|
+
const SCRIPT_TAG_NAME = "script";
|
|
76029
|
+
const SCRIPT_OPEN = `<${SCRIPT_TAG_NAME}`;
|
|
76030
|
+
const SCRIPT_CLOSE = `</${SCRIPT_TAG_NAME}`;
|
|
76031
|
+
const TEMPLATE_TAG_NAME = "template";
|
|
76032
|
+
const TEMPLATE_CLOSE = `</${TEMPLATE_TAG_NAME}`;
|
|
76033
|
+
const JAVASCRIPT_MIME_TYPES = new Set([
|
|
76034
|
+
"application/ecmascript",
|
|
76035
|
+
"application/javascript",
|
|
76036
|
+
"application/x-ecmascript",
|
|
76037
|
+
"application/x-javascript",
|
|
76038
|
+
"text/ecmascript",
|
|
76039
|
+
"text/javascript",
|
|
76040
|
+
"text/javascript1.0",
|
|
76041
|
+
"text/javascript1.1",
|
|
76042
|
+
"text/javascript1.2",
|
|
76043
|
+
"text/javascript1.3",
|
|
76044
|
+
"text/javascript1.4",
|
|
76045
|
+
"text/javascript1.5",
|
|
76046
|
+
"text/jscript",
|
|
76047
|
+
"text/livescript",
|
|
76048
|
+
"text/x-ecmascript",
|
|
76049
|
+
"text/x-javascript"
|
|
76050
|
+
]);
|
|
76051
|
+
const RAW_TEXT_TAG_NAMES = new Set([
|
|
76052
|
+
"iframe",
|
|
76053
|
+
"noembed",
|
|
76054
|
+
"noframes",
|
|
76055
|
+
"noscript",
|
|
76056
|
+
"style",
|
|
76057
|
+
"textarea",
|
|
76058
|
+
"title",
|
|
76059
|
+
"xmp"
|
|
76060
|
+
]);
|
|
76061
|
+
const PLAINTEXT_TAG_NAME = "plaintext";
|
|
76062
|
+
const TAG_OPEN_UTF8_BYTE = "<".charCodeAt(0);
|
|
76063
|
+
const TAG_CLOSE_UTF8_BYTE = ">".charCodeAt(0);
|
|
76064
|
+
const SINGLE_QUOTE_UTF8_BYTE = "'".charCodeAt(0);
|
|
76065
|
+
const DOUBLE_QUOTE_UTF8_BYTE = "\"".charCodeAt(0);
|
|
76066
|
+
const ATTRIBUTE_ASSIGNMENT_UTF8_BYTE = "=".charCodeAt(0);
|
|
76067
|
+
const TAG_SELF_CLOSE_UTF8_BYTE = "/".charCodeAt(0);
|
|
76068
|
+
const TAB_UTF8_BYTE = " ".charCodeAt(0);
|
|
76069
|
+
const FORM_FEED_UTF8_BYTE = "\f".charCodeAt(0);
|
|
76070
|
+
const isHtmlWhitespace = (byte) => byte === TAB_UTF8_BYTE || byte === 10 || byte === FORM_FEED_UTF8_BYTE || byte === 13 || byte === 32;
|
|
76071
|
+
const matchesAsciiCaseInsensitive = (sourceBuffer, startByte, expected) => {
|
|
76072
|
+
if (startByte + expected.length > sourceBuffer.length) return false;
|
|
76073
|
+
for (let expectedIndex = 0; expectedIndex < expected.length; expectedIndex++) {
|
|
76074
|
+
const sourceByte = sourceBuffer[startByte + expectedIndex];
|
|
76075
|
+
if (sourceByte === void 0 || String.fromCharCode(sourceByte).toLowerCase() !== expected[expectedIndex]) return false;
|
|
76076
|
+
}
|
|
76077
|
+
return true;
|
|
76078
|
+
};
|
|
76079
|
+
const isTagBoundary = (byte) => byte === TAG_CLOSE_UTF8_BYTE || byte === TAG_SELF_CLOSE_UTF8_BYTE || isHtmlWhitespace(byte);
|
|
76080
|
+
const isPotentialTagStart = (byte) => {
|
|
76081
|
+
if (byte === void 0) return false;
|
|
76082
|
+
return /[A-Za-z!/?]/.test(String.fromCharCode(byte));
|
|
76083
|
+
};
|
|
76084
|
+
const findLineEnd = (sourceBuffer, lineStartByte) => {
|
|
76085
|
+
let byteIndex = lineStartByte;
|
|
76086
|
+
while (byteIndex < sourceBuffer.length && sourceBuffer[byteIndex] !== 10 && sourceBuffer[byteIndex] !== 13) byteIndex++;
|
|
76087
|
+
return byteIndex;
|
|
76088
|
+
};
|
|
76089
|
+
const findNextLineStart = (sourceBuffer, lineStartByte) => {
|
|
76090
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
76091
|
+
if (sourceBuffer[lineEndByte] === 13 && sourceBuffer[lineEndByte + 1] === 10) return lineEndByte + 2;
|
|
76092
|
+
return Math.min(lineEndByte + 1, sourceBuffer.length);
|
|
76093
|
+
};
|
|
76094
|
+
const isFrontmatterFenceLine = (sourceBuffer, lineStartByte) => {
|
|
76095
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, lineStartByte, FRONTMATTER_FENCE)) return false;
|
|
76096
|
+
const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
|
|
76097
|
+
for (let byteIndex = lineStartByte + 3; byteIndex < lineEndByte; byteIndex++) if (!isHtmlWhitespace(sourceBuffer[byteIndex])) return false;
|
|
76098
|
+
return true;
|
|
76099
|
+
};
|
|
76100
|
+
const findFrontmatterEnd = (sourceBuffer) => {
|
|
76101
|
+
if (!isFrontmatterFenceLine(sourceBuffer, 0)) return 0;
|
|
76102
|
+
const openingFenceEndByte = findLineEnd(sourceBuffer, 0);
|
|
76103
|
+
let lineStartByte = findNextLineStart(sourceBuffer, 0);
|
|
76104
|
+
while (lineStartByte < sourceBuffer.length) {
|
|
76105
|
+
if (isFrontmatterFenceLine(sourceBuffer, lineStartByte)) return findLineEnd(sourceBuffer, lineStartByte);
|
|
76106
|
+
lineStartByte = findNextLineStart(sourceBuffer, lineStartByte);
|
|
76107
|
+
}
|
|
76108
|
+
return openingFenceEndByte;
|
|
76109
|
+
};
|
|
76110
|
+
const maskByteRange = (maskedBuffer, startByte, endByte) => {
|
|
76111
|
+
for (let byteIndex = startByte; byteIndex < endByte; byteIndex++) {
|
|
76112
|
+
const byte = maskedBuffer[byteIndex];
|
|
76113
|
+
if (byte !== 10 && byte !== 13) maskedBuffer[byteIndex] = 32;
|
|
76114
|
+
}
|
|
76115
|
+
};
|
|
76116
|
+
const readStartTagName = (sourceBuffer, tagStartByte) => {
|
|
76117
|
+
const firstNameByte = sourceBuffer[tagStartByte + 1];
|
|
76118
|
+
if (firstNameByte === void 0 || !/[A-Za-z]/.test(String.fromCharCode(firstNameByte))) return null;
|
|
76119
|
+
let nameEndByte = tagStartByte + 2;
|
|
76120
|
+
while (nameEndByte < sourceBuffer.length && /[A-Za-z0-9:-]/.test(String.fromCharCode(sourceBuffer[nameEndByte] ?? 32))) nameEndByte++;
|
|
76121
|
+
return sourceBuffer.subarray(tagStartByte + 1, nameEndByte).toString("ascii").toLowerCase();
|
|
76122
|
+
};
|
|
76123
|
+
const findTagEnd = (sourceBuffer, startByte) => {
|
|
76124
|
+
let quoteByte = null;
|
|
76125
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) {
|
|
76126
|
+
const byte = sourceBuffer[byteIndex];
|
|
76127
|
+
if (quoteByte !== null) {
|
|
76128
|
+
if (byte === quoteByte) quoteByte = null;
|
|
76129
|
+
continue;
|
|
76130
|
+
}
|
|
76131
|
+
if (byte === SINGLE_QUOTE_UTF8_BYTE || byte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
76132
|
+
quoteByte = byte;
|
|
76133
|
+
continue;
|
|
76134
|
+
}
|
|
76135
|
+
if (byte === TAG_CLOSE_UTF8_BYTE) return byteIndex;
|
|
76136
|
+
}
|
|
76137
|
+
return sourceBuffer.length;
|
|
76138
|
+
};
|
|
76139
|
+
const parseScriptAttributes = (sourceBuffer, attributesStartByte, tagEndByte) => {
|
|
76140
|
+
let byteIndex = attributesStartByte;
|
|
76141
|
+
let hasSource = false;
|
|
76142
|
+
let language = null;
|
|
76143
|
+
let scriptType = null;
|
|
76144
|
+
while (byteIndex < tagEndByte) {
|
|
76145
|
+
while (byteIndex < tagEndByte && (isHtmlWhitespace(sourceBuffer[byteIndex]) || sourceBuffer[byteIndex] === TAG_SELF_CLOSE_UTF8_BYTE)) byteIndex++;
|
|
76146
|
+
const attributeNameStartByte = byteIndex;
|
|
76147
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== ATTRIBUTE_ASSIGNMENT_UTF8_BYTE && sourceBuffer[byteIndex] !== TAG_SELF_CLOSE_UTF8_BYTE) byteIndex++;
|
|
76148
|
+
const attributeName = sourceBuffer.subarray(attributeNameStartByte, byteIndex).toString("ascii").toLowerCase();
|
|
76149
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
76150
|
+
let attributeValue = "";
|
|
76151
|
+
if (sourceBuffer[byteIndex] === ATTRIBUTE_ASSIGNMENT_UTF8_BYTE) {
|
|
76152
|
+
byteIndex++;
|
|
76153
|
+
while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
|
|
76154
|
+
const quoteByte = sourceBuffer[byteIndex];
|
|
76155
|
+
if (quoteByte === SINGLE_QUOTE_UTF8_BYTE || quoteByte === DOUBLE_QUOTE_UTF8_BYTE) {
|
|
76156
|
+
const valueStartByte = byteIndex + 1;
|
|
76157
|
+
byteIndex = valueStartByte;
|
|
76158
|
+
while (byteIndex < tagEndByte && sourceBuffer[byteIndex] !== quoteByte) byteIndex++;
|
|
76159
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
76160
|
+
if (byteIndex < tagEndByte) byteIndex++;
|
|
76161
|
+
} else {
|
|
76162
|
+
const valueStartByte = byteIndex;
|
|
76163
|
+
while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== TAG_CLOSE_UTF8_BYTE) byteIndex++;
|
|
76164
|
+
attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
|
|
76165
|
+
}
|
|
76166
|
+
}
|
|
76167
|
+
if (attributeName === "src") hasSource = true;
|
|
76168
|
+
else if (attributeName === "type" && scriptType === null) scriptType = attributeValue;
|
|
76169
|
+
else if (attributeName === "language" && language === null) language = attributeValue;
|
|
76170
|
+
}
|
|
76171
|
+
return {
|
|
76172
|
+
hasSource,
|
|
76173
|
+
language,
|
|
76174
|
+
type: scriptType
|
|
76175
|
+
};
|
|
76176
|
+
};
|
|
76177
|
+
const isExecutableScript = (attributes) => {
|
|
76178
|
+
if (attributes.hasSource) return false;
|
|
76179
|
+
const type = attributes.type?.trim().toLowerCase() ?? "";
|
|
76180
|
+
if (type !== "") {
|
|
76181
|
+
const mimeType = type.split(";")[0]?.trim() ?? "";
|
|
76182
|
+
return mimeType === "module" || JAVASCRIPT_MIME_TYPES.has(mimeType);
|
|
76183
|
+
}
|
|
76184
|
+
const language = attributes.language?.trim().toLowerCase() ?? "";
|
|
76185
|
+
return language === "" || JAVASCRIPT_MIME_TYPES.has(`text/${language}`);
|
|
76186
|
+
};
|
|
76187
|
+
const findElementClose = (sourceBuffer, startByte, tagName) => {
|
|
76188
|
+
const closeTagStart = `</${tagName}`;
|
|
76189
|
+
for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) if (sourceBuffer[byteIndex] === TAG_OPEN_UTF8_BYTE && matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, closeTagStart) && isTagBoundary(sourceBuffer[byteIndex + closeTagStart.length])) return byteIndex;
|
|
76190
|
+
return sourceBuffer.length;
|
|
76191
|
+
};
|
|
76192
|
+
const prepareHtmlScriptSource = (sourceBuffer) => {
|
|
76193
|
+
const frontmatterEndByte = findFrontmatterEnd(sourceBuffer);
|
|
76194
|
+
let maskedBuffer = frontmatterEndByte > 0 ? Buffer.from(sourceBuffer) : null;
|
|
76195
|
+
if (maskedBuffer !== null) maskByteRange(maskedBuffer, 0, frontmatterEndByte);
|
|
76196
|
+
const executableScriptBodies = [];
|
|
76197
|
+
let byteIndex = frontmatterEndByte;
|
|
76198
|
+
let templateDepth = 0;
|
|
76199
|
+
while (byteIndex < sourceBuffer.length) {
|
|
76200
|
+
if (sourceBuffer[byteIndex] !== TAG_OPEN_UTF8_BYTE) {
|
|
76201
|
+
byteIndex++;
|
|
76202
|
+
continue;
|
|
76203
|
+
}
|
|
76204
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, COMMENT_OPEN)) {
|
|
76205
|
+
const commentEndByte = sourceBuffer.indexOf(COMMENT_CLOSE, byteIndex + 4);
|
|
76206
|
+
byteIndex = commentEndByte === -1 ? sourceBuffer.length : commentEndByte + 3;
|
|
76207
|
+
continue;
|
|
76208
|
+
}
|
|
76209
|
+
if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, TEMPLATE_CLOSE) && isTagBoundary(sourceBuffer[byteIndex + TEMPLATE_CLOSE.length])) {
|
|
76210
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + TEMPLATE_CLOSE.length);
|
|
76211
|
+
if (templateDepth > 0) templateDepth--;
|
|
76212
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
76213
|
+
continue;
|
|
76214
|
+
}
|
|
76215
|
+
if (!matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, SCRIPT_OPEN) || !isTagBoundary(sourceBuffer[byteIndex + SCRIPT_OPEN.length])) {
|
|
76216
|
+
if (!isPotentialTagStart(sourceBuffer[byteIndex + 1])) {
|
|
76217
|
+
byteIndex++;
|
|
76218
|
+
continue;
|
|
76219
|
+
}
|
|
76220
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + 1);
|
|
76221
|
+
const tagName = readStartTagName(sourceBuffer, byteIndex);
|
|
76222
|
+
if (tagName === PLAINTEXT_TAG_NAME) break;
|
|
76223
|
+
if (tagName === TEMPLATE_TAG_NAME) templateDepth++;
|
|
76224
|
+
if (tagName !== null && RAW_TEXT_TAG_NAMES.has(tagName)) {
|
|
76225
|
+
const closeTagStartByte = findElementClose(sourceBuffer, tagEndByte + 1, tagName);
|
|
76226
|
+
if (closeTagStartByte === sourceBuffer.length) break;
|
|
76227
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, closeTagStartByte + tagName.length + 2);
|
|
76228
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
76229
|
+
continue;
|
|
76230
|
+
}
|
|
76231
|
+
byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
|
|
76232
|
+
continue;
|
|
76233
|
+
}
|
|
76234
|
+
const tagEndByte = findTagEnd(sourceBuffer, byteIndex + SCRIPT_OPEN.length);
|
|
76235
|
+
if (tagEndByte === sourceBuffer.length) break;
|
|
76236
|
+
const bodyStartByte = tagEndByte + 1;
|
|
76237
|
+
const bodyEndByte = findElementClose(sourceBuffer, bodyStartByte, SCRIPT_TAG_NAME);
|
|
76238
|
+
const attributes = parseScriptAttributes(sourceBuffer, byteIndex + SCRIPT_OPEN.length, tagEndByte);
|
|
76239
|
+
if (attributes.hasSource || templateDepth > 0) {
|
|
76240
|
+
maskedBuffer ??= Buffer.from(sourceBuffer);
|
|
76241
|
+
maskByteRange(maskedBuffer, bodyStartByte, bodyEndByte);
|
|
76242
|
+
} else if (isExecutableScript(attributes)) executableScriptBodies.push(sourceBuffer.subarray(bodyStartByte, bodyEndByte));
|
|
76243
|
+
if (bodyEndByte === sourceBuffer.length) break;
|
|
76244
|
+
const closeTagEndByte = findTagEnd(sourceBuffer, bodyEndByte + SCRIPT_CLOSE.length);
|
|
76245
|
+
byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
|
|
76246
|
+
}
|
|
76247
|
+
return {
|
|
76248
|
+
executableScriptBodies,
|
|
76249
|
+
lintBuffer: maskedBuffer ?? sourceBuffer
|
|
76250
|
+
};
|
|
76251
|
+
};
|
|
76252
|
+
const ASTRO_FILE_PATTERN = /\.astro$/;
|
|
76253
|
+
const prepareLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
|
|
76254
|
+
const lintFiles = [];
|
|
76255
|
+
const sourcePathByLintPath = /* @__PURE__ */ new Map();
|
|
76256
|
+
const sourceMapByLintPath = /* @__PURE__ */ new Map();
|
|
76257
|
+
const sizeByLintPath = /* @__PURE__ */ new Map();
|
|
76258
|
+
const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
|
|
76259
|
+
const astroSourcesDirectory = Path.join(temporaryDirectory, "astro-sources");
|
|
76260
|
+
let htmlFileIndex = 0;
|
|
76261
|
+
let astroFileIndex = 0;
|
|
76262
|
+
let hasThreeModuleImport = false;
|
|
76263
|
+
for (const candidateFile of candidateFiles) {
|
|
76264
|
+
if (!HTML_FILE_PATTERN.test(candidateFile) && !ASTRO_FILE_PATTERN.test(candidateFile)) {
|
|
76265
|
+
lintFiles.push(candidateFile);
|
|
76266
|
+
continue;
|
|
76267
|
+
}
|
|
76268
|
+
const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
|
|
76269
|
+
const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
|
|
76270
|
+
if (ASTRO_FILE_PATTERN.test(candidateFile)) {
|
|
76271
|
+
const compilerSourcePath = absoluteSourcePath.replaceAll("\\", "/");
|
|
76272
|
+
const convertedSource = convertToTSX(sourceBuffer.toString("utf8"), {
|
|
76273
|
+
filename: compilerSourcePath,
|
|
76274
|
+
sourcemap: "external",
|
|
76275
|
+
includeScripts: true
|
|
76276
|
+
});
|
|
76277
|
+
if (astroFileIndex === 0) NFS.mkdirSync(astroSourcesDirectory, { recursive: true });
|
|
76278
|
+
const lintPath = Path.join(astroSourcesDirectory, `${astroFileIndex}.tsx`);
|
|
76279
|
+
const generatedBuffer = Buffer.from(convertedSource.code);
|
|
76280
|
+
NFS.writeFileSync(lintPath, generatedBuffer);
|
|
76281
|
+
lintFiles.push(candidateFile);
|
|
76282
|
+
lintFiles.push(lintPath);
|
|
76283
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
76284
|
+
sourceMapByLintPath.set(Path.resolve(lintPath), {
|
|
76285
|
+
traceMap: new TraceMap(JSON.stringify(convertedSource.map)),
|
|
76286
|
+
generatedBuffer,
|
|
76287
|
+
sourceBuffer
|
|
76288
|
+
});
|
|
76289
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
76290
|
+
astroFileIndex++;
|
|
76291
|
+
continue;
|
|
76292
|
+
}
|
|
76293
|
+
const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
|
|
76294
|
+
if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
|
|
76295
|
+
const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
|
|
76296
|
+
NFS.writeFileSync(lintPath, lintBuffer);
|
|
76297
|
+
lintFiles.push(lintPath);
|
|
76298
|
+
sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
|
|
76299
|
+
sizeByLintPath.set(lintPath, sourceBuffer.length);
|
|
76300
|
+
hasThreeModuleImport ||= executableScriptBodies.some((scriptBody) => containsThreeModuleImport(scriptBody.toString("utf8")));
|
|
76301
|
+
htmlFileIndex++;
|
|
76302
|
+
}
|
|
76303
|
+
return {
|
|
76304
|
+
lintFiles,
|
|
76305
|
+
sourcePathByLintPath,
|
|
76306
|
+
sourceMapByLintPath,
|
|
76307
|
+
sizeByLintPath,
|
|
76308
|
+
hasThreeModuleImport
|
|
76309
|
+
};
|
|
76310
|
+
};
|
|
74754
76311
|
/**
|
|
74755
76312
|
* Atomically (re)writes the generated oxlintrc.json. Used twice in
|
|
74756
76313
|
* the runner: once for the primary scan, once for the
|
|
@@ -74911,6 +76468,8 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
74911
76468
|
const runOxlint = async (options) => {
|
|
74912
76469
|
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
74913
76470
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
76471
|
+
const runtimeGlobals = Array.isArray(userConfig?.runtimeGlobals) ? userConfig.runtimeGlobals.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
76472
|
+
let unpluginAutoImportGlobalScopes = [];
|
|
74914
76473
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
74915
76474
|
validateRuleRegistration();
|
|
74916
76475
|
resetManifestCaches();
|
|
@@ -74924,21 +76483,6 @@ const runOxlint = async (options) => {
|
|
|
74924
76483
|
const pluginPath = resolvePluginPath();
|
|
74925
76484
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
74926
76485
|
const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
74927
|
-
const buildConfig = (overrides) => createOxlintConfig({
|
|
74928
|
-
pluginPath,
|
|
74929
|
-
project,
|
|
74930
|
-
customRulesOnly,
|
|
74931
|
-
extendsPaths: overrides.extendsPaths,
|
|
74932
|
-
ignoredTags,
|
|
74933
|
-
includedTags,
|
|
74934
|
-
includeTagDefaults,
|
|
74935
|
-
serverAuthFunctionNames,
|
|
74936
|
-
severityControls,
|
|
74937
|
-
userPlugins,
|
|
74938
|
-
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
74939
|
-
ruleSelection: overrides.ruleSelection,
|
|
74940
|
-
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
74941
|
-
});
|
|
74942
76486
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
74943
76487
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
74944
76488
|
const configPath = Path.join(configDirectory, "oxlintrc.json");
|
|
@@ -74974,7 +76518,36 @@ const runOxlint = async (options) => {
|
|
|
74974
76518
|
await yieldToEventLoop();
|
|
74975
76519
|
const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
|
|
74976
76520
|
const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
|
|
76521
|
+
unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
|
|
76522
|
+
rootDirectory,
|
|
76523
|
+
candidateFiles
|
|
76524
|
+
});
|
|
76525
|
+
const preparedLintSources = prepareLintSources(rootDirectory, configDirectory, candidateFiles);
|
|
76526
|
+
const lintFiles = preparedLintSources.lintFiles;
|
|
76527
|
+
const hasPreparedFiles = preparedLintSources.sourcePathByLintPath.size > 0;
|
|
76528
|
+
const lintProject = !project.hasThree && preparedLintSources.hasThreeModuleImport ? {
|
|
76529
|
+
...project,
|
|
76530
|
+
hasThree: true
|
|
76531
|
+
} : project;
|
|
76532
|
+
const buildConfig = (overrides) => createOxlintConfig({
|
|
76533
|
+
pluginPath,
|
|
76534
|
+
project: lintProject,
|
|
76535
|
+
customRulesOnly,
|
|
76536
|
+
extendsPaths: overrides.extendsPaths,
|
|
76537
|
+
ignoredTags,
|
|
76538
|
+
includedTags,
|
|
76539
|
+
includeTagDefaults,
|
|
76540
|
+
runtimeGlobals,
|
|
76541
|
+
unpluginAutoImportGlobalScopes,
|
|
76542
|
+
serverAuthFunctionNames,
|
|
76543
|
+
severityControls,
|
|
76544
|
+
userPlugins,
|
|
76545
|
+
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
76546
|
+
ruleSelection: overrides.ruleSelection,
|
|
76547
|
+
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
76548
|
+
});
|
|
74977
76549
|
const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
|
|
76550
|
+
if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedLintSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
|
|
74978
76551
|
const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
|
|
74979
76552
|
baseArgs: passBaseArgs,
|
|
74980
76553
|
files: passFiles,
|
|
@@ -75003,7 +76576,9 @@ const runOxlint = async (options) => {
|
|
|
75003
76576
|
fileBatches: passFileBatches,
|
|
75004
76577
|
rootDirectory,
|
|
75005
76578
|
nodeBinaryPath,
|
|
75006
|
-
project,
|
|
76579
|
+
project: lintProject,
|
|
76580
|
+
sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
|
|
76581
|
+
sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
|
|
75007
76582
|
onPartialFailure: reportPartialFailure,
|
|
75008
76583
|
onAnalyzedFiles: (filePaths) => {
|
|
75009
76584
|
analyzedFiles = filePaths;
|
|
@@ -75012,6 +76587,7 @@ const runOxlint = async (options) => {
|
|
|
75012
76587
|
spawnTimeoutMs,
|
|
75013
76588
|
outputMaxBytes,
|
|
75014
76589
|
concurrency: options.concurrency,
|
|
76590
|
+
spawnSlots: options.spawnSlots,
|
|
75015
76591
|
signal: options.signal,
|
|
75016
76592
|
deadlineEpochMs: options.deadlineEpochMs
|
|
75017
76593
|
});
|
|
@@ -75038,7 +76614,7 @@ const runOxlint = async (options) => {
|
|
|
75038
76614
|
};
|
|
75039
76615
|
}
|
|
75040
76616
|
};
|
|
75041
|
-
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0) {
|
|
76617
|
+
if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasPreparedFiles) {
|
|
75042
76618
|
const rulesetHash = computeRulesetHash({
|
|
75043
76619
|
config: buildConfig({
|
|
75044
76620
|
extendsPaths: [],
|
|
@@ -75196,14 +76772,16 @@ const runOxlint = async (options) => {
|
|
|
75196
76772
|
]);
|
|
75197
76773
|
}
|
|
75198
76774
|
const baseArgs = makeBaseArgs(configPath);
|
|
75199
|
-
const fileBatches = buildFileBatches(baseArgs,
|
|
76775
|
+
const fileBatches = buildFileBatches(baseArgs, lintFiles);
|
|
75200
76776
|
let analyzedFiles = [];
|
|
75201
76777
|
const runBatches = () => spawnLintBatches({
|
|
75202
76778
|
baseArgs,
|
|
75203
76779
|
fileBatches,
|
|
75204
76780
|
rootDirectory,
|
|
75205
76781
|
nodeBinaryPath,
|
|
75206
|
-
project,
|
|
76782
|
+
project: lintProject,
|
|
76783
|
+
sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
|
|
76784
|
+
sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
|
|
75207
76785
|
onPartialFailure,
|
|
75208
76786
|
onAnalyzedFiles: (filePaths) => {
|
|
75209
76787
|
analyzedFiles = filePaths;
|
|
@@ -75212,6 +76790,7 @@ const runOxlint = async (options) => {
|
|
|
75212
76790
|
spawnTimeoutMs,
|
|
75213
76791
|
outputMaxBytes,
|
|
75214
76792
|
concurrency: options.concurrency,
|
|
76793
|
+
spawnSlots: options.spawnSlots,
|
|
75215
76794
|
signal: options.signal,
|
|
75216
76795
|
deadlineEpochMs: options.deadlineEpochMs
|
|
75217
76796
|
});
|
|
@@ -75306,6 +76885,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
75306
76885
|
const spawnTimeoutMs = yield* OxlintSpawnTimeoutMs;
|
|
75307
76886
|
const outputMaxBytes = yield* OxlintOutputMaxBytes;
|
|
75308
76887
|
const concurrency = yield* OxlintConcurrency;
|
|
76888
|
+
const spawnSlots = yield* OxlintSpawnSlots;
|
|
75309
76889
|
const lintBatchOrdering = yield* LintBatchOrdering;
|
|
75310
76890
|
const perFileLintCacheEnabled = yield* PerFileLintCacheEnabled;
|
|
75311
76891
|
const sidecarLintCacheEnabled = yield* SidecarLintCacheEnabled;
|
|
@@ -75335,6 +76915,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
75335
76915
|
onSidecarStats: input.onSidecarStats,
|
|
75336
76916
|
spawnTimeoutMs,
|
|
75337
76917
|
outputMaxBytes,
|
|
76918
|
+
spawnSlots: spawnSlots ?? void 0,
|
|
75338
76919
|
concurrency,
|
|
75339
76920
|
signal,
|
|
75340
76921
|
lintBatchOrdering,
|
|
@@ -76563,10 +78144,14 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
76563
78144
|
materializedFiles.push(relativePath);
|
|
76564
78145
|
}
|
|
76565
78146
|
yield* sync(() => {
|
|
76566
|
-
for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
|
|
76567
|
-
const sourcePath = path.join(input.directory, configFilename);
|
|
76568
|
-
const targetPath = path.
|
|
76569
|
-
if (
|
|
78147
|
+
for (const subdirectory of ["", ...input.configSubdirectories ?? []]) for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
|
|
78148
|
+
const sourcePath = path.join(input.directory, subdirectory, configFilename);
|
|
78149
|
+
const targetPath = path.resolve(resolvedTempDirectory, subdirectory, configFilename);
|
|
78150
|
+
if (!isPathInsideDirectory(targetPath, resolvedTempDirectory)) continue;
|
|
78151
|
+
if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) {
|
|
78152
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
78153
|
+
fs.cpSync(sourcePath, targetPath);
|
|
78154
|
+
}
|
|
76570
78155
|
}
|
|
76571
78156
|
});
|
|
76572
78157
|
return {
|
|
@@ -76599,15 +78184,17 @@ var StagedFiles = class StagedFiles extends Service()("react-doctor/StagedFiles"
|
|
|
76599
78184
|
static layerNode = effect(StagedFiles, gen(function* () {
|
|
76600
78185
|
const git = yield* Git;
|
|
76601
78186
|
return StagedFiles.of({
|
|
76602
|
-
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
|
|
76603
|
-
materialize: ({ directory, stagedFiles, tempDirectory }) => materializeSourceTree({
|
|
78187
|
+
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries === null ? null : entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
|
|
78188
|
+
materialize: ({ directory, stagedFiles, tempDirectory, configSubdirectories }) => materializeSourceTree({
|
|
76604
78189
|
directory,
|
|
76605
78190
|
files: stagedFiles,
|
|
76606
78191
|
tempDirectory,
|
|
78192
|
+
configSubdirectories,
|
|
76607
78193
|
readContent: (relativePath) => git.showStagedContent(directory, relativePath, { maxBufferBytes: GIT_SHOW_MAX_BUFFER_BYTES })
|
|
76608
78194
|
}).pipe(map$3((tree) => ({
|
|
76609
78195
|
tempDirectory: tree.tempDirectory,
|
|
76610
78196
|
stagedFiles: tree.materializedFiles,
|
|
78197
|
+
unmaterializedFiles: tree.unmaterializedFiles,
|
|
76611
78198
|
cleanup: tree.cleanup
|
|
76612
78199
|
})), withSpan("StagedFiles.materialize"))
|
|
76613
78200
|
});
|
|
@@ -76622,6 +78209,7 @@ var StagedFiles = class StagedFiles extends Service()("react-doctor/StagedFiles"
|
|
|
76622
78209
|
materialize: ({ tempDirectory }) => succeed$2({
|
|
76623
78210
|
tempDirectory,
|
|
76624
78211
|
stagedFiles: snapshot.materializedFiles ?? snapshot.sourceFiles ?? [],
|
|
78212
|
+
unmaterializedFiles: [],
|
|
76625
78213
|
cleanup: () => {}
|
|
76626
78214
|
})
|
|
76627
78215
|
}));
|
|
@@ -76990,6 +78578,11 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
76990
78578
|
}
|
|
76991
78579
|
return crypto.createHash("sha1").update(parts.join("|")).digest("hex");
|
|
76992
78580
|
};
|
|
78581
|
+
const createLintPhaseAbortError = () => new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) });
|
|
78582
|
+
const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
|
|
78583
|
+
slotCount: resolveScanConcurrency(concurrency),
|
|
78584
|
+
createAbortError: createLintPhaseAbortError
|
|
78585
|
+
});
|
|
76993
78586
|
const AI_TRAINING_ENV_VARS = [
|
|
76994
78587
|
["HF_DATASETS_CACHE", "huggingface"],
|
|
76995
78588
|
["HF_HOME", "huggingface"],
|
|
@@ -77069,7 +78662,7 @@ const groupBy = (items, keyFn) => {
|
|
|
77069
78662
|
* recipe, so advertising "fetch the fix recipe" for them sends agents to
|
|
77070
78663
|
* a 404. Gate the directive on this predicate.
|
|
77071
78664
|
*/
|
|
77072
|
-
const hasPublishedFixRecipe = (diagnostic) => diagnostic.plugin === "react-doctor" && Object.hasOwn(
|
|
78665
|
+
const hasPublishedFixRecipe = (diagnostic) => diagnostic.plugin === "react-doctor" && Object.hasOwn(REACT_DOCTOR_RULE_REGISTRY, diagnostic.rule);
|
|
77073
78666
|
const unionValues = (baseValues, overrideValues) => [...new Set([...baseValues, ...overrideValues])];
|
|
77074
78667
|
const mergeIgnores = (baseIgnore, overrideIgnore) => {
|
|
77075
78668
|
const mergedIgnore = {
|
|
@@ -77318,6 +78911,7 @@ const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
|
|
|
77318
78911
|
const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
|
|
77319
78912
|
const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
77320
78913
|
const GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS = 5e3;
|
|
78914
|
+
const TUI_REPORT_COMPACT_MAX_ROWS = 29;
|
|
77321
78915
|
const TUI_REPORT_DETAIL_WIDTH_FRACTION = .6;
|
|
77322
78916
|
const CI_TRUST_COMPANIES = "PayPal, Rippling, and Alibaba";
|
|
77323
78917
|
const WELCOME_EXPLANATION_HOLD_MS = 1e3;
|
|
@@ -77330,11 +78924,13 @@ const METRIC = {
|
|
|
77330
78924
|
cliError: "cli.error",
|
|
77331
78925
|
cliEnvironmentError: "cli.env_error",
|
|
77332
78926
|
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
78927
|
+
stagedPerProject: "staged.per_project",
|
|
77333
78928
|
projectDetected: "project.detected",
|
|
77334
78929
|
projectPathSelected: "project.path_selected",
|
|
77335
78930
|
projectConfigSelected: "project.config_selected",
|
|
77336
78931
|
scanCompleted: "scan.completed",
|
|
77337
78932
|
scanDuration: "scan.duration",
|
|
78933
|
+
scanFeedbackDelay: "scan.feedback_delay",
|
|
77338
78934
|
scanPhaseDuration: "scan.phase_duration",
|
|
77339
78935
|
scanFiles: "scan.files",
|
|
77340
78936
|
scanScore: "scan.score",
|
|
@@ -77366,6 +78962,10 @@ const METRIC = {
|
|
|
77366
78962
|
lspScanCompleted: "lsp.scan.completed",
|
|
77367
78963
|
lspScanDuration: "lsp.scan.duration",
|
|
77368
78964
|
lspScanDiagnostics: "lsp.scan.diagnostics",
|
|
78965
|
+
tuiActionMenuOpened: "tui.action_menu_opened",
|
|
78966
|
+
tuiCompactReportShown: "tui.compact_report_shown",
|
|
78967
|
+
tuiFindingNavigated: "tui.finding_navigated",
|
|
78968
|
+
tuiStackedReportCapped: "tui.stacked_report_capped",
|
|
77369
78969
|
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
77370
78970
|
jsonOutUsed: "json.out_used"
|
|
77371
78971
|
};
|
|
@@ -77410,7 +79010,7 @@ const makeNoopConsole = () => ({
|
|
|
77410
79010
|
});
|
|
77411
79011
|
//#endregion
|
|
77412
79012
|
//#region src/cli/utils/version.ts
|
|
77413
|
-
const VERSION = "0.9.
|
|
79013
|
+
const VERSION = "0.9.2-dev.075865f";
|
|
77414
79014
|
//#endregion
|
|
77415
79015
|
//#region src/cli/utils/json-mode.ts
|
|
77416
79016
|
let context = null;
|
|
@@ -77768,13 +79368,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
77768
79368
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
77769
79369
|
* standard `SENTRY_RELEASE` override.
|
|
77770
79370
|
*/
|
|
77771
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.
|
|
79371
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.9.2-dev.075865f`;
|
|
77772
79372
|
/**
|
|
77773
79373
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
77774
79374
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
77775
79375
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
77776
79376
|
*/
|
|
77777
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.
|
|
79377
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.9.2-dev.075865f") ? "development" : "production");
|
|
77778
79378
|
/**
|
|
77779
79379
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
77780
79380
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -89628,7 +91228,8 @@ const buildRuntimeLayers = (input) => {
|
|
|
89628
91228
|
resolvedDirectory: input.directory,
|
|
89629
91229
|
configSourceDirectory: input.configSourceDirectory
|
|
89630
91230
|
}) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive, deadCodeLayer, progressLayer, reporterLayer, scoreLayer, supplyChainLayer);
|
|
89631
|
-
|
|
91231
|
+
const layersWithConcurrency = input.oxlintConcurrency === void 0 ? baseLayers : mergeAll$1(baseLayers, succeed$3(OxlintConcurrency, input.oxlintConcurrency));
|
|
91232
|
+
return input.oxlintSpawnSlots === void 0 ? layersWithConcurrency : mergeAll$1(layersWithConcurrency, succeed$3(OxlintSpawnSlots, input.oxlintSpawnSlots));
|
|
89632
91233
|
};
|
|
89633
91234
|
//#endregion
|
|
89634
91235
|
//#region src/cli/utils/with-sentry-run-span.ts
|
|
@@ -90439,6 +92040,7 @@ const buildScanAttributes = (input) => {
|
|
|
90439
92040
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
90440
92041
|
fileCount: input.result?.scannedFileCount ?? null,
|
|
90441
92042
|
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null,
|
|
92043
|
+
htmlFileCount: input.result?.analyzedFiles?.filter((filePath) => HTML_FILE_PATTERN.test(filePath)).length ?? null,
|
|
90442
92044
|
multilineDiagnosticCount: input.result?.diagnostics.filter((diagnostic) => (diagnostic.endLine ?? diagnostic.line) > diagnostic.line).length ?? null
|
|
90443
92045
|
});
|
|
90444
92046
|
};
|
|
@@ -91230,16 +92832,19 @@ const formatClusterLocation = (cluster, resolveSourceRoot, hyperlinks) => {
|
|
|
91230
92832
|
if (!hyperlinks) return `${location}${contextTag}`;
|
|
91231
92833
|
return `${formatHyperlink(location, pathToFileURL(resolveAbsolutePath(lead.filePath, resolveSourceRoot(lead))).href)}${contextTag}`;
|
|
91232
92834
|
};
|
|
91233
|
-
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame, hyperlinks) => {
|
|
92835
|
+
const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, resolveFrameSourceRoot, renderCodeFrame, hyperlinks) => {
|
|
91234
92836
|
const lead = cluster.diagnostics[0];
|
|
91235
92837
|
const isMultiSite = cluster.diagnostics.length > 1;
|
|
92838
|
+
const sourceRoot = resolveSourceRoot(lead);
|
|
92839
|
+
const frameSourceRoot = resolveFrameSourceRoot(lead);
|
|
92840
|
+
const frameFilePath = Path.isAbsolute(lead.filePath) && sourceRoot !== frameSourceRoot ? Path.relative(sourceRoot, lead.filePath) : lead.filePath;
|
|
91236
92841
|
const lines = ["", highlighter.gray(`${TOP_ERROR_DETAIL_INDENT}${formatClusterLocation(cluster, resolveSourceRoot, hyperlinks)}`)];
|
|
91237
92842
|
const codeFrame = renderCodeFrame ? buildCodeFrame({
|
|
91238
|
-
filePath:
|
|
92843
|
+
filePath: frameFilePath,
|
|
91239
92844
|
line: cluster.startLine,
|
|
91240
92845
|
column: isMultiSite ? 0 : lead.column,
|
|
91241
92846
|
endLine: isMultiSite ? cluster.endLine : void 0,
|
|
91242
|
-
rootDirectory:
|
|
92847
|
+
rootDirectory: frameSourceRoot
|
|
91243
92848
|
}) : null;
|
|
91244
92849
|
if (codeFrame) {
|
|
91245
92850
|
const boxInnerWidth = resolveMeasureWidth(8);
|
|
@@ -91252,7 +92857,7 @@ const buildDiagnosticClusterLines = (cluster, resolveSourceRoot, renderCodeFrame
|
|
|
91252
92857
|
}
|
|
91253
92858
|
return lines;
|
|
91254
92859
|
};
|
|
91255
|
-
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, renderEverySite, isAgentEnvironment, hyperlinks) => {
|
|
92860
|
+
const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, renderEverySite, isAgentEnvironment, hyperlinks) => {
|
|
91256
92861
|
const representative = pickRepresentativeDiagnostic(ruleDiagnostics);
|
|
91257
92862
|
const { severity } = representative;
|
|
91258
92863
|
const trailingBadge = formatTrailingSiteBadge(ruleDiagnostics.length);
|
|
@@ -91274,7 +92879,7 @@ const buildRuleDetailBlock = (ruleKey, ruleDiagnostics, resolveSourceRoot, rende
|
|
|
91274
92879
|
}
|
|
91275
92880
|
const renderCodeFrame = severity === "error";
|
|
91276
92881
|
const sites = renderEverySite ? ruleDiagnostics : [representative];
|
|
91277
|
-
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, renderCodeFrame, hyperlinks));
|
|
92882
|
+
if (!(isCollapsedWarningGroup && representative.help.includes(representative.filePath))) for (const cluster of clusterNearbyDiagnostics(sites)) lines.push(...buildDiagnosticClusterLines(cluster, resolveSourceRoot, resolveFrameSourceRoot, renderCodeFrame, hyperlinks));
|
|
91278
92883
|
return lines;
|
|
91279
92884
|
};
|
|
91280
92885
|
const selectErrorRuleGroups = (diagnostics, rulePriority) => buildSortedRuleGroups(diagnostics.filter((diagnostic) => diagnostic.severity === "error"), rulePriority);
|
|
@@ -91300,7 +92905,7 @@ const buildMigrationScaleAdvisoryLines = (diagnostics) => {
|
|
|
91300
92905
|
return lines;
|
|
91301
92906
|
};
|
|
91302
92907
|
const getTopErrorRuleKeys = (diagnostics, limit, rulePriority) => new Set(selectTopErrorRuleGroups(diagnostics, limit, rulePriority).map(([ruleKey]) => ruleKey));
|
|
91303
|
-
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, hyperlinks, rulePriority) => {
|
|
92908
|
+
const buildTopErrorsSection = (diagnostics, resolveSourceRoot, resolveFrameSourceRoot, hyperlinks, rulePriority) => {
|
|
91304
92909
|
const topRuleGroups = selectErrorRuleGroups(diagnostics, rulePriority).slice(0, 3);
|
|
91305
92910
|
if (topRuleGroups.length === 0) return {
|
|
91306
92911
|
lines: [],
|
|
@@ -91310,7 +92915,7 @@ const buildTopErrorsSection = (diagnostics, resolveSourceRoot, hyperlinks, ruleP
|
|
|
91310
92915
|
const blockOffsets = [];
|
|
91311
92916
|
for (const [ruleKey, ruleDiagnostics] of topRuleGroups) {
|
|
91312
92917
|
blockOffsets.push(lines.length);
|
|
91313
|
-
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, false, false, hyperlinks));
|
|
92918
|
+
lines.push(...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, false, false, hyperlinks));
|
|
91314
92919
|
lines.push("");
|
|
91315
92920
|
}
|
|
91316
92921
|
return {
|
|
@@ -91348,18 +92953,19 @@ const buildOverviewHeaderLines = (diagnostics) => {
|
|
|
91348
92953
|
* single Effect.forEach over Console.log so failures or fiber
|
|
91349
92954
|
* interruption produce predictable partial output.
|
|
91350
92955
|
*/
|
|
91351
|
-
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}, hyperlinks = false) => gen(function* () {
|
|
92956
|
+
const printDiagnostics = (diagnostics, isVerbose, sourceRoot, rulePriority, isAgentEnvironment = false, onboarding = {}, hyperlinks = false, frameSourceRoot = sourceRoot) => gen(function* () {
|
|
91352
92957
|
const sectionPause = onboarding.sectionPause ?? void_;
|
|
91353
92958
|
const animateCountUp = onboarding.animateCountUp ?? false;
|
|
91354
92959
|
const resolveSourceRoot = typeof sourceRoot === "function" ? sourceRoot : () => sourceRoot;
|
|
92960
|
+
const resolveFrameSourceRoot = typeof frameSourceRoot === "function" ? frameSourceRoot : () => frameSourceRoot;
|
|
91355
92961
|
let detailLines;
|
|
91356
92962
|
let topErrorBlockOffsets = [];
|
|
91357
92963
|
if (!isVerbose) {
|
|
91358
|
-
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, hyperlinks, rulePriority);
|
|
92964
|
+
const topErrors = buildTopErrorsSection(diagnostics, resolveSourceRoot, resolveFrameSourceRoot, hyperlinks, rulePriority);
|
|
91359
92965
|
detailLines = topErrors.lines;
|
|
91360
92966
|
topErrorBlockOffsets = topErrors.blockOffsets;
|
|
91361
92967
|
} else detailLines = buildSortedRuleGroups(diagnostics, rulePriority).flatMap(([ruleKey, ruleDiagnostics]) => {
|
|
91362
|
-
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, true, isAgentEnvironment, hyperlinks), ""];
|
|
92968
|
+
return [...buildRuleDetailBlock(ruleKey, ruleDiagnostics, resolveSourceRoot, resolveFrameSourceRoot, true, isAgentEnvironment, hyperlinks), ""];
|
|
91363
92969
|
});
|
|
91364
92970
|
const overflowLine = isVerbose ? void 0 : buildOverflowSummaryLine(diagnostics, rulePriority);
|
|
91365
92971
|
const categoryTallies = buildCategoryDiagnosticGroups(diagnostics, rulePriority).map(buildCategoryTally);
|
|
@@ -92127,7 +93733,7 @@ const buildRunEventConfig = (options, userConfig, hasCustomConfig, resolvedWorke
|
|
|
92127
93733
|
userConfig
|
|
92128
93734
|
};
|
|
92129
93735
|
};
|
|
92130
|
-
const
|
|
93736
|
+
const inspectWithOxlintRuntime = async (directory, inputOptions, oxlintRuntime) => {
|
|
92131
93737
|
const startTime = performance$1.now();
|
|
92132
93738
|
const deadlineEpochMs = inputOptions.deadlineEpochMs ?? (inputOptions.maxDurationMs != null ? Date.now() + inputOptions.maxDurationMs : null);
|
|
92133
93739
|
const isConcurrentScan = inputOptions.concurrentScan === true;
|
|
@@ -92153,7 +93759,7 @@ const inspect = async (directory, inputOptions = {}) => {
|
|
|
92153
93759
|
try {
|
|
92154
93760
|
const result = await withSentryRunSpan(async (rootSentrySpan) => {
|
|
92155
93761
|
try {
|
|
92156
|
-
return await runInspectWithRuntime(scanDirectory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan);
|
|
93762
|
+
return await runInspectWithRuntime(scanDirectory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan, oxlintRuntime);
|
|
92157
93763
|
} catch (error) {
|
|
92158
93764
|
recordRunEvent(rootSentrySpan, {
|
|
92159
93765
|
...buildRunEventConfig(options, userConfig, userConfig !== null),
|
|
@@ -92169,6 +93775,15 @@ const inspect = async (directory, inputOptions = {}) => {
|
|
|
92169
93775
|
if (ownsSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
92170
93776
|
}
|
|
92171
93777
|
};
|
|
93778
|
+
const createInvocationInspect = (requestedOxlintConcurrency) => {
|
|
93779
|
+
const concurrency = resolveScanConcurrency(requestedOxlintConcurrency ?? runSync(OxlintConcurrency));
|
|
93780
|
+
const oxlintRuntime = {
|
|
93781
|
+
concurrency,
|
|
93782
|
+
spawnSlots: createOxlintSpawnSlots(concurrency)
|
|
93783
|
+
};
|
|
93784
|
+
return (directory, inputOptions = {}) => inspectWithOxlintRuntime(directory, inputOptions, oxlintRuntime);
|
|
93785
|
+
};
|
|
93786
|
+
const inspect = async (directory, inputOptions = {}) => createInvocationInspect(inputOptions.concurrency)(directory, inputOptions);
|
|
92172
93787
|
const countIncompleteLintFiles = (lintPartialFailures) => countDroppedLintFiles(lintPartialFailures) + countDeadlineSkippedFiles(lintPartialFailures);
|
|
92173
93788
|
/**
|
|
92174
93789
|
* Runs a second, lint-only scan over the changed files as they existed at the
|
|
@@ -92222,7 +93837,8 @@ const runBaselineComparison = async (params) => {
|
|
|
92222
93837
|
shouldRunSupplyChain: params.options.supplyChain,
|
|
92223
93838
|
shouldComputeScore: false,
|
|
92224
93839
|
shouldShowProgressSpinners: false,
|
|
92225
|
-
oxlintConcurrency: params.
|
|
93840
|
+
oxlintConcurrency: params.oxlintRuntime.concurrency,
|
|
93841
|
+
oxlintSpawnSlots: params.oxlintRuntime.spawnSlots
|
|
92226
93842
|
});
|
|
92227
93843
|
const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
|
|
92228
93844
|
directory: snapshot.tempDirectory,
|
|
@@ -92267,7 +93883,7 @@ const runBaselineComparison = async (params) => {
|
|
|
92267
93883
|
snapshot.cleanup();
|
|
92268
93884
|
}
|
|
92269
93885
|
};
|
|
92270
|
-
const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan) => {
|
|
93886
|
+
const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOverride, configSourceDirectory, startTime, deadlineEpochMs, rootSentrySpan, oxlintRuntime) => {
|
|
92271
93887
|
const isDiffMode = options.includePaths.length > 0;
|
|
92272
93888
|
const resolvedNodeBinaryPath = await resolveOxlintNode(options.lint, options.scoreOnly || options.silent);
|
|
92273
93889
|
const lintBindingMissing = options.lint && !resolvedNodeBinaryPath;
|
|
@@ -92317,7 +93933,8 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
92317
93933
|
shouldRunSupplyChain: options.supplyChain,
|
|
92318
93934
|
shouldComputeScore: !options.noScore,
|
|
92319
93935
|
shouldShowProgressSpinners,
|
|
92320
|
-
oxlintConcurrency:
|
|
93936
|
+
oxlintConcurrency: oxlintRuntime.concurrency,
|
|
93937
|
+
oxlintSpawnSlots: oxlintRuntime.spawnSlots,
|
|
92321
93938
|
reporterLayer: options.uiLayers?.reporter,
|
|
92322
93939
|
progressLayer: options.uiLayers?.progress
|
|
92323
93940
|
});
|
|
@@ -92374,7 +93991,8 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
92374
93991
|
baseFiles: options.baseline.baseFiles,
|
|
92375
93992
|
headFiles: options.baseline.headFiles,
|
|
92376
93993
|
headAnalyzedFiles: output.analyzedFiles,
|
|
92377
|
-
deadlineEpochMs
|
|
93994
|
+
deadlineEpochMs,
|
|
93995
|
+
oxlintRuntime
|
|
92378
93996
|
});
|
|
92379
93997
|
if (comparison) {
|
|
92380
93998
|
inspectDiagnostics = comparison.displayDiagnostics;
|
|
@@ -92623,26 +94241,26 @@ const finalizeAndRender = (input) => gen(function* () {
|
|
|
92623
94241
|
//#region src/cli/utils/get-staged-files.ts
|
|
92624
94242
|
const stagedFilesLayer = StagedFiles.layerNode.pipe(provide$2(Git.layerNode));
|
|
92625
94243
|
const getStagedSourceFiles = async (directory) => {
|
|
94244
|
+
let stagedSourceFiles;
|
|
92626
94245
|
try {
|
|
92627
|
-
|
|
94246
|
+
stagedSourceFiles = await runPromise(gen(function* () {
|
|
92628
94247
|
return yield* (yield* StagedFiles).discoverSourceFiles(directory);
|
|
92629
|
-
}).pipe(provide(stagedFilesLayer)))
|
|
94248
|
+
}).pipe(provide(stagedFilesLayer)));
|
|
92630
94249
|
} catch (error) {
|
|
92631
94250
|
cliLogger.warn(`Failed to discover staged files: ${messageFromUnknown(error)}`);
|
|
92632
94251
|
return [];
|
|
92633
94252
|
}
|
|
94253
|
+
if (stagedSourceFiles === null) throw new CliInputError("Could not read the git index to list staged files. Check that git can read the index in this directory.");
|
|
94254
|
+
return [...stagedSourceFiles];
|
|
92634
94255
|
};
|
|
92635
|
-
const materializeStagedFiles = async (
|
|
94256
|
+
const materializeStagedFiles = async (input) => {
|
|
92636
94257
|
const snapshot = await runPromise(gen(function* () {
|
|
92637
|
-
return yield* (yield* StagedFiles).materialize(
|
|
92638
|
-
directory,
|
|
92639
|
-
stagedFiles,
|
|
92640
|
-
tempDirectory
|
|
92641
|
-
});
|
|
94258
|
+
return yield* (yield* StagedFiles).materialize(input);
|
|
92642
94259
|
}).pipe(provide(stagedFilesLayer)));
|
|
92643
94260
|
return {
|
|
92644
94261
|
tempDirectory: snapshot.tempDirectory,
|
|
92645
94262
|
stagedFiles: [...snapshot.stagedFiles],
|
|
94263
|
+
unmaterializedFiles: [...snapshot.unmaterializedFiles],
|
|
92646
94264
|
cleanup: snapshot.cleanup
|
|
92647
94265
|
};
|
|
92648
94266
|
};
|
|
@@ -94516,13 +96134,18 @@ const printMultiProjectSummary = (input) => gen(function* () {
|
|
|
94516
96134
|
const scoreDiagnostics = new Set(filterScansForSurface(completedScans, "score"));
|
|
94517
96135
|
const displayedScoreDiagnostics = displayDiagnostics.filter((diagnostic) => scoreDiagnostics.has(diagnostic));
|
|
94518
96136
|
const projectRootByDiagnostic = /* @__PURE__ */ new WeakMap();
|
|
94519
|
-
|
|
96137
|
+
const frameSourceRootByDiagnostic = /* @__PURE__ */ new WeakMap();
|
|
96138
|
+
for (const scan of completedScans) for (const diagnostic of scan.result.diagnostics) {
|
|
96139
|
+
projectRootByDiagnostic.set(diagnostic, scan.result.project.rootDirectory);
|
|
96140
|
+
frameSourceRootByDiagnostic.set(diagnostic, scan.frameSourceRoot ?? scan.result.project.rootDirectory);
|
|
96141
|
+
}
|
|
94520
96142
|
const resolveDiagnosticSourceRoot = (diagnostic) => projectRootByDiagnostic.get(diagnostic) ?? "";
|
|
96143
|
+
const resolveDiagnosticFrameSourceRoot = (diagnostic) => frameSourceRootByDiagnostic.get(diagnostic) ?? resolveDiagnosticSourceRoot(diagnostic);
|
|
94521
96144
|
const totalScannedFileCount = countUniqueScannedFiles(completedScans.map((scan) => scan.result));
|
|
94522
96145
|
yield* log(`${highlighter.success("✔")} Scanned ${totalScannedFileCount} ${totalScannedFileCount === 1 ? "file" : "files"} in ${formatElapsedTime(totalElapsedMilliseconds)}`);
|
|
94523
96146
|
if (displayDiagnostics.length > 0) {
|
|
94524
96147
|
yield* log("");
|
|
94525
|
-
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender }, shouldRenderHyperlinks(process.stdout));
|
|
96148
|
+
yield* printDiagnostics(displayDiagnostics, verbose, resolveDiagnosticSourceRoot, buildRulePriorityMap(completedScans.map((scan) => scan.result.score)), isCodingAgentEnvironment(), { animateCountUp: animateRender }, shouldRenderHyperlinks(process.stdout), resolveDiagnosticFrameSourceRoot);
|
|
94526
96149
|
}
|
|
94527
96150
|
const lowestScoredScan = findLowestScoredScan(completedScans);
|
|
94528
96151
|
const aggregateScore = lowestScoredScan?.result.score ?? null;
|
|
@@ -94910,6 +96533,45 @@ const runExplain = async (fileLineArgument, context) => {
|
|
|
94910
96533
|
}
|
|
94911
96534
|
};
|
|
94912
96535
|
//#endregion
|
|
96536
|
+
//#region src/cli/utils/run-project-scan-batch.ts
|
|
96537
|
+
/**
|
|
96538
|
+
* Run one scan per project through the same bounded pool as
|
|
96539
|
+
* `diagnose({ projects })`, with the batch spinner and its progress counter.
|
|
96540
|
+
*
|
|
96541
|
+
* Pool members must not toggle the module-level spinner-silent flag themselves —
|
|
96542
|
+
* overlapping save/restore pairs would race — so the batch owns that toggle once
|
|
96543
|
+
* around the whole run.
|
|
96544
|
+
*
|
|
96545
|
+
* A `scanProject` that returns `null` drops the project from the results: diff
|
|
96546
|
+
* mode skips projects with no changed source.
|
|
96547
|
+
*/
|
|
96548
|
+
const runProjectScanBatch = async (input) => {
|
|
96549
|
+
const startTime = performance$1.now();
|
|
96550
|
+
const projectCount = input.projects.length;
|
|
96551
|
+
const isMultiProject = projectCount > 1;
|
|
96552
|
+
const batchSpinner = isMultiProject && !input.isQuiet ? spinner(`Scanning ${projectCount} projects…`).start() : null;
|
|
96553
|
+
const ownsBatchSpinnerSilence = isMultiProject && input.isSilent;
|
|
96554
|
+
const wasSpinnerSilent = isSpinnerSilent();
|
|
96555
|
+
if (ownsBatchSpinnerSilence) setSpinnerSilent(true);
|
|
96556
|
+
let finishedProjectCount = 0;
|
|
96557
|
+
let scanOutcomes;
|
|
96558
|
+
try {
|
|
96559
|
+
scanOutcomes = await mapWithConcurrency(input.projects, isMultiProject ? 4 : 1, async (project) => {
|
|
96560
|
+
const scanOutcome = await input.scanProject(project);
|
|
96561
|
+
finishedProjectCount += 1;
|
|
96562
|
+
batchSpinner?.update(`Scanning ${projectCount} projects… (${finishedProjectCount}/${projectCount})`);
|
|
96563
|
+
return scanOutcome;
|
|
96564
|
+
});
|
|
96565
|
+
} finally {
|
|
96566
|
+
if (ownsBatchSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
96567
|
+
batchSpinner?.stop();
|
|
96568
|
+
}
|
|
96569
|
+
return {
|
|
96570
|
+
completedScans: scanOutcomes.filter((scanOutcome) => scanOutcome !== null),
|
|
96571
|
+
elapsedMilliseconds: performance$1.now() - startTime
|
|
96572
|
+
};
|
|
96573
|
+
};
|
|
96574
|
+
//#endregion
|
|
94913
96575
|
//#region src/cli/utils/project-manifest-changed.ts
|
|
94914
96576
|
const PACKAGE_JSON = "package.json";
|
|
94915
96577
|
/**
|
|
@@ -94926,6 +96588,29 @@ const projectManifestChanged = (rootDirectory, projectDirectory, diffInfo) => {
|
|
|
94926
96588
|
return diffInfo.changedFiles.some((filePath) => toForwardSlashes(filePath) === manifestPath);
|
|
94927
96589
|
};
|
|
94928
96590
|
//#endregion
|
|
96591
|
+
//#region src/cli/utils/select-staged-projects.ts
|
|
96592
|
+
/**
|
|
96593
|
+
* Appended to the reason a `--staged` run could not scan per package. Shared so
|
|
96594
|
+
* both fallback sites word it identically.
|
|
96595
|
+
*/
|
|
96596
|
+
const STAGED_PROJECT_FALLBACK_HINT = "Scanning the staged files at the scan root instead — fix the `projects` entries in your config to scan per package.";
|
|
96597
|
+
/**
|
|
96598
|
+
* Resolve the project directories a `--staged` scan owns. The interactive picker
|
|
96599
|
+
* is always skipped: a commit hook has nobody to answer it.
|
|
96600
|
+
*/
|
|
96601
|
+
const selectStagedProjects = async (input) => {
|
|
96602
|
+
if (input.projectFlag) return selectProjects(input.rootDirectory, input.projectFlag, true, void 0);
|
|
96603
|
+
if (input.configProjects === void 0) return [input.rootDirectory];
|
|
96604
|
+
try {
|
|
96605
|
+
return await selectProjects(input.rootDirectory, void 0, true, input.configProjects);
|
|
96606
|
+
} catch (error) {
|
|
96607
|
+
if (!(error instanceof CliInputError)) throw error;
|
|
96608
|
+
cliLogger.warn(`${error.message} ${STAGED_PROJECT_FALLBACK_HINT}`);
|
|
96609
|
+
cliLogger.break();
|
|
96610
|
+
return [input.rootDirectory];
|
|
96611
|
+
}
|
|
96612
|
+
};
|
|
96613
|
+
//#endregion
|
|
94929
96614
|
//#region src/cli/utils/should-fail-scan-gate.ts
|
|
94930
96615
|
const shouldFailScanGate = (input) => {
|
|
94931
96616
|
if (input.blockingLevel === "none") return false;
|
|
@@ -95091,6 +96776,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95091
96776
|
const isQuiet = isScoreOnly || isJsonMode;
|
|
95092
96777
|
const requestedDirectory = Path.resolve(directory);
|
|
95093
96778
|
const startTime = performance$1.now();
|
|
96779
|
+
let scanStartupSpinner = null;
|
|
95094
96780
|
if (isJsonMode) {
|
|
95095
96781
|
enableJsonMode({
|
|
95096
96782
|
compact: Boolean(flags.jsonCompact),
|
|
@@ -95139,6 +96825,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95139
96825
|
if (!isQuiet) if (!flags.verbose && canAnimateOnboarding(process.stdout)) await runPromise(playWelcomeScene({ speedMultiplier: !isOnboardingForced() && hasCompletedOnboarding() ? 2 : 1 }));
|
|
95140
96826
|
else runSync(printBrandedHeader);
|
|
95141
96827
|
const scanOptions = resolveCliInspectOptions(flags, userConfig);
|
|
96828
|
+
const inspectProject = createInvocationInspect(scanOptions.concurrency);
|
|
95142
96829
|
const scanDeadlineEpochMs = scanOptions.maxDurationMs !== void 0 ? Date.now() + scanOptions.maxDurationMs : void 0;
|
|
95143
96830
|
const categoryFilters = new Set(scanOptions.categoryFilters ?? []);
|
|
95144
96831
|
const skipPrompts = shouldSkipPrompts({
|
|
@@ -95146,8 +96833,13 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95146
96833
|
json: flags.json
|
|
95147
96834
|
});
|
|
95148
96835
|
if (flags.staged) {
|
|
95149
|
-
const
|
|
95150
|
-
|
|
96836
|
+
const configProjectsApply = (userConfig?.projects ?? []).some((projectName) => projectName.trim().length > 0) && scanTarget.requestedDirectory === scanTarget.configSourceDirectory;
|
|
96837
|
+
const projectDirectories = await selectStagedProjects({
|
|
96838
|
+
rootDirectory: resolvedDirectory,
|
|
96839
|
+
projectFlag: flags.project,
|
|
96840
|
+
configProjects: configProjectsApply ? userConfig?.projects : void 0
|
|
96841
|
+
});
|
|
96842
|
+
const reportNothingToScan = (input) => {
|
|
95151
96843
|
if (isJsonMode) writeJsonReport(buildJsonReport({
|
|
95152
96844
|
version: VERSION,
|
|
95153
96845
|
directory: resolvedDirectory,
|
|
@@ -95156,75 +96848,214 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95156
96848
|
scans: [],
|
|
95157
96849
|
totalElapsedMilliseconds: performance$1.now() - startTime
|
|
95158
96850
|
}));
|
|
95159
|
-
else if (!isScoreOnly)
|
|
96851
|
+
else if (!isScoreOnly) if (input.severity === "warn") {
|
|
96852
|
+
cliLogger.warn(input.reason);
|
|
96853
|
+
cliLogger.break();
|
|
96854
|
+
} else cliLogger.dim(input.reason);
|
|
96855
|
+
};
|
|
96856
|
+
const rootStagedFiles = await getStagedSourceFiles(resolvedDirectory);
|
|
96857
|
+
if (rootStagedFiles.length === 0) {
|
|
96858
|
+
reportNothingToScan({ reason: "No staged source files found." });
|
|
95160
96859
|
return;
|
|
95161
96860
|
}
|
|
95162
|
-
|
|
95163
|
-
|
|
96861
|
+
const buildProjectScanContext = async (projectDirectory) => {
|
|
96862
|
+
const projectScanTarget = projectDirectory === resolvedDirectory ? scanTarget : await resolveScanTarget(projectDirectory, { allowAmbiguous: true });
|
|
96863
|
+
const scanDirectory = projectScanTarget.resolvedDirectory;
|
|
96864
|
+
const treeRelativeDirectory = resolveProjectRelativeDirectory(resolvedDirectory, scanDirectory);
|
|
96865
|
+
if (treeRelativeDirectory === null) return null;
|
|
96866
|
+
return {
|
|
96867
|
+
projectDirectory,
|
|
96868
|
+
scanDirectory,
|
|
96869
|
+
treeRelativeDirectory,
|
|
96870
|
+
projectConfig: projectDirectory === resolvedDirectory ? userConfig : mergeReactDoctorConfigs(userConfig, projectScanTarget.userConfig ?? void 0),
|
|
96871
|
+
projectConfigSourceDirectory: projectScanTarget.userConfig?.plugins === void 0 ? scanTarget.configSourceDirectory : projectScanTarget.configSourceDirectory
|
|
96872
|
+
};
|
|
96873
|
+
};
|
|
96874
|
+
const projectScanContexts = [];
|
|
96875
|
+
const seenScanDirectories = /* @__PURE__ */ new Set();
|
|
96876
|
+
for (const projectDirectory of projectDirectories) {
|
|
96877
|
+
const projectScanContext = await buildProjectScanContext(projectDirectory);
|
|
96878
|
+
if (projectScanContext === null) {
|
|
96879
|
+
if (flags.project) throw new CliInputError(`Project "${toRelativePath(projectDirectory, resolvedDirectory)}" is outside ${resolvedDirectory}, so it holds none of the staged files. Run --staged from a directory that contains the project.`);
|
|
96880
|
+
continue;
|
|
96881
|
+
}
|
|
96882
|
+
if (seenScanDirectories.has(projectScanContext.scanDirectory)) continue;
|
|
96883
|
+
seenScanDirectories.add(projectScanContext.scanDirectory);
|
|
96884
|
+
projectScanContexts.push(projectScanContext);
|
|
96885
|
+
}
|
|
96886
|
+
if (projectScanContexts.length === 0) {
|
|
96887
|
+
cliLogger.warn(`No configured project is inside ${resolvedDirectory}. ${STAGED_PROJECT_FALLBACK_HINT}`);
|
|
95164
96888
|
cliLogger.break();
|
|
96889
|
+
const rootScanContext = await buildProjectScanContext(resolvedDirectory);
|
|
96890
|
+
if (rootScanContext !== null) projectScanContexts.push(rootScanContext);
|
|
95165
96891
|
}
|
|
95166
|
-
const
|
|
95167
|
-
const
|
|
95168
|
-
|
|
95169
|
-
|
|
95170
|
-
|
|
96892
|
+
const contextsByLongestPathFirst = [...projectScanContexts].sort((left, right) => right.treeRelativeDirectory.length - left.treeRelativeDirectory.length);
|
|
96893
|
+
const ownedStagedFiles = /* @__PURE__ */ new Map();
|
|
96894
|
+
for (const stagedFile of rootStagedFiles) {
|
|
96895
|
+
const owner = contextsByLongestPathFirst.find((context) => context.treeRelativeDirectory.length === 0 || stagedFile.startsWith(`${context.treeRelativeDirectory}/`));
|
|
96896
|
+
if (owner === void 0) continue;
|
|
96897
|
+
const ownedFiles = ownedStagedFiles.get(owner.scanDirectory);
|
|
96898
|
+
if (ownedFiles === void 0) ownedStagedFiles.set(owner.scanDirectory, [stagedFile]);
|
|
96899
|
+
else ownedFiles.push(stagedFile);
|
|
96900
|
+
}
|
|
96901
|
+
const stagedProjectScans = [];
|
|
96902
|
+
for (const projectScanContext of projectScanContexts) {
|
|
96903
|
+
const projectStagedFiles = ownedStagedFiles.get(projectScanContext.scanDirectory);
|
|
96904
|
+
if (projectStagedFiles === void 0) continue;
|
|
96905
|
+
stagedProjectScans.push({
|
|
96906
|
+
...projectScanContext,
|
|
96907
|
+
stagedFiles: projectStagedFiles
|
|
95171
96908
|
});
|
|
95172
|
-
|
|
95173
|
-
|
|
96909
|
+
}
|
|
96910
|
+
if (stagedProjectScans.length === 0) {
|
|
96911
|
+
reportNothingToScan({ reason: "No staged source files in the selected projects." });
|
|
96912
|
+
return;
|
|
96913
|
+
}
|
|
96914
|
+
const selectedStagedFiles = stagedProjectScans.flatMap((projectScan) => projectScan.stagedFiles);
|
|
96915
|
+
const stagedFileCount = selectedStagedFiles.length;
|
|
96916
|
+
const unselectedStagedFileCount = rootStagedFiles.length - stagedFileCount;
|
|
96917
|
+
if (!isQuiet) {
|
|
96918
|
+
cliLogger.log(`Scanning ${highlighter.info(`${stagedFileCount}`)} staged files...`);
|
|
96919
|
+
if (unselectedStagedFileCount > 0) cliLogger.dim(`${unselectedStagedFileCount} more staged file${unselectedStagedFileCount === 1 ? "" : "s"} outside the selected projects.`);
|
|
96920
|
+
cliLogger.break();
|
|
96921
|
+
}
|
|
95174
96922
|
const stagedWantsLines = resolveScope(flags, userConfig).scope === "lines";
|
|
95175
96923
|
const stagedLineRanges = stagedWantsLines ? await getChangedLineRanges({
|
|
95176
96924
|
directory: resolvedDirectory,
|
|
95177
96925
|
cached: true,
|
|
95178
|
-
files:
|
|
96926
|
+
files: selectedStagedFiles
|
|
95179
96927
|
}) : null;
|
|
95180
96928
|
if (stagedWantsLines && stagedLineRanges === null && !isQuiet) {
|
|
95181
96929
|
cliLogger.warn("Could not determine staged changed lines; reporting all issues in staged files.");
|
|
95182
96930
|
cliLogger.break();
|
|
95183
96931
|
}
|
|
95184
|
-
|
|
95185
|
-
|
|
96932
|
+
if (stagedProjectScans.some((projectScan) => projectScan.treeRelativeDirectory.length > 0)) recordCount(METRIC.stagedPerProject, 1, { projectCount: stagedProjectScans.length });
|
|
96933
|
+
const tempDirectory = NFS.mkdtempSync(Path.join(tmpdir(), STAGED_FILES_TEMP_DIR_PREFIX));
|
|
96934
|
+
const configSubdirectories = /* @__PURE__ */ new Set();
|
|
96935
|
+
for (const projectScan of stagedProjectScans) {
|
|
96936
|
+
configSubdirectories.add(projectScan.treeRelativeDirectory);
|
|
96937
|
+
const projectRelativeDirectory = resolveProjectRelativeDirectory(resolvedDirectory, projectScan.projectDirectory);
|
|
96938
|
+
if (projectRelativeDirectory !== null) configSubdirectories.add(projectRelativeDirectory);
|
|
96939
|
+
}
|
|
96940
|
+
const snapshot = await materializeStagedFiles({
|
|
96941
|
+
directory: resolvedDirectory,
|
|
96942
|
+
stagedFiles: selectedStagedFiles,
|
|
96943
|
+
tempDirectory,
|
|
96944
|
+
configSubdirectories: [...configSubdirectories]
|
|
96945
|
+
}).catch((error) => {
|
|
96946
|
+
NFS.rmSync(tempDirectory, {
|
|
96947
|
+
recursive: true,
|
|
96948
|
+
force: true
|
|
96949
|
+
});
|
|
96950
|
+
throw error;
|
|
96951
|
+
});
|
|
96952
|
+
const materializedStagedFiles = new Set(snapshot.stagedFiles);
|
|
96953
|
+
const stagedProjectRuns = stagedProjectScans.map((projectScan) => ({
|
|
96954
|
+
projectScan,
|
|
96955
|
+
includePaths: resolveProjectSourceFilePaths(resolvedDirectory, projectScan.scanDirectory, projectScan.stagedFiles.filter((stagedFile) => materializedStagedFiles.has(stagedFile)))
|
|
96956
|
+
})).filter((projectRun) => projectRun.includePaths.length > 0);
|
|
96957
|
+
const isMultiProject = stagedProjectRuns.length > 1;
|
|
96958
|
+
if (stagedProjectRuns.length === 0) {
|
|
96959
|
+
snapshot.cleanup();
|
|
96960
|
+
reportNothingToScan({
|
|
96961
|
+
reason: `Could not read any of the ${stagedFileCount} staged file${stagedFileCount === 1 ? "" : "s"} out of the index, so nothing was scanned. An unusually large staged file is the usual cause.`,
|
|
96962
|
+
severity: "warn"
|
|
96963
|
+
});
|
|
96964
|
+
return;
|
|
96965
|
+
}
|
|
96966
|
+
if (snapshot.unmaterializedFiles.length > 0 && !isQuiet) {
|
|
96967
|
+
const stagedFileLabel = `staged file${stagedFileCount === 1 ? "" : "s"}`;
|
|
96968
|
+
cliLogger.warn(`Skipped ${snapshot.unmaterializedFiles.length} of ${stagedFileCount} ${stagedFileLabel}; they could not be snapshotted from the index.`);
|
|
96969
|
+
cliLogger.break();
|
|
96970
|
+
}
|
|
96971
|
+
const scanStagedProject = async (projectRun) => {
|
|
96972
|
+
const { projectScan, includePaths } = projectRun;
|
|
96973
|
+
const projectTempDirectory = Path.join(snapshot.tempDirectory, projectScan.treeRelativeDirectory);
|
|
96974
|
+
const scanResult = await inspectProject(projectTempDirectory, {
|
|
95186
96975
|
...scanOptions,
|
|
95187
96976
|
deadlineEpochMs: scanDeadlineEpochMs,
|
|
95188
|
-
includePaths:
|
|
95189
|
-
configOverride:
|
|
95190
|
-
configSourceDirectory:
|
|
95191
|
-
changedLineRanges: stagedLineRanges
|
|
96977
|
+
includePaths: [...includePaths],
|
|
96978
|
+
configOverride: projectScan.projectConfig,
|
|
96979
|
+
configSourceDirectory: projectScan.projectConfigSourceDirectory ?? void 0,
|
|
96980
|
+
changedLineRanges: stagedLineRanges === null ? void 0 : resolveProjectChangedLineRanges(resolvedDirectory, projectScan.scanDirectory, stagedLineRanges),
|
|
96981
|
+
suppressRendering: isMultiProject,
|
|
96982
|
+
concurrentScan: isMultiProject
|
|
95192
96983
|
});
|
|
95193
96984
|
const remappedDiagnostics = scanResult.diagnostics.map((diagnostic) => ({
|
|
95194
96985
|
...diagnostic,
|
|
95195
|
-
filePath: Path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(
|
|
96986
|
+
filePath: Path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(projectTempDirectory, () => projectScan.scanDirectory) : diagnostic.filePath
|
|
95196
96987
|
}));
|
|
95197
|
-
|
|
95198
|
-
|
|
95199
|
-
|
|
95200
|
-
|
|
95201
|
-
|
|
95202
|
-
|
|
95203
|
-
project
|
|
95204
|
-
|
|
95205
|
-
|
|
95206
|
-
|
|
95207
|
-
|
|
95208
|
-
|
|
95209
|
-
|
|
95210
|
-
|
|
95211
|
-
|
|
95212
|
-
|
|
95213
|
-
|
|
95214
|
-
|
|
95215
|
-
|
|
95216
|
-
|
|
95217
|
-
|
|
95218
|
-
|
|
95219
|
-
|
|
95220
|
-
|
|
96988
|
+
return {
|
|
96989
|
+
directory: projectScan.scanDirectory,
|
|
96990
|
+
result: {
|
|
96991
|
+
...scanResult,
|
|
96992
|
+
diagnostics: remappedDiagnostics,
|
|
96993
|
+
project: {
|
|
96994
|
+
...scanResult.project,
|
|
96995
|
+
rootDirectory: projectScan.scanDirectory
|
|
96996
|
+
}
|
|
96997
|
+
},
|
|
96998
|
+
config: projectScan.projectConfig,
|
|
96999
|
+
frameSourceRoot: projectTempDirectory
|
|
97000
|
+
};
|
|
97001
|
+
};
|
|
97002
|
+
const stagedBatch = await runProjectScanBatch({
|
|
97003
|
+
projects: stagedProjectRuns,
|
|
97004
|
+
isQuiet,
|
|
97005
|
+
isSilent: scanOptions.silent === true,
|
|
97006
|
+
scanProject: scanStagedProject
|
|
97007
|
+
}).catch((error) => {
|
|
97008
|
+
snapshot.cleanup();
|
|
97009
|
+
throw error;
|
|
97010
|
+
});
|
|
97011
|
+
const completedScans = stagedBatch.completedScans;
|
|
97012
|
+
try {
|
|
97013
|
+
if (!isQuiet && isMultiProject) {
|
|
97014
|
+
const showShareLink = !isShareOptedOut(completedScans, scanOptions.noScore) && !scanOptions.isCi;
|
|
97015
|
+
await runPromise(printMultiProjectSummary({
|
|
97016
|
+
completedScans,
|
|
97017
|
+
categoryFilters,
|
|
97018
|
+
verbose: Boolean(flags.verbose),
|
|
97019
|
+
outputDirectory: flags.outputDir,
|
|
97020
|
+
isOffline: !showShareLink,
|
|
97021
|
+
projectName: Path.basename(resolvedDirectory),
|
|
97022
|
+
totalElapsedMilliseconds: stagedBatch.elapsedMilliseconds
|
|
97023
|
+
}));
|
|
97024
|
+
}
|
|
97025
|
+
if (flags.outputDir && isMultiProject && isQuiet) await runPromise(printDiagnosticsDump(filterDiagnosticsByCategories(filterScansForSurface(completedScans, scanOptions.outputSurface ?? "cli"), categoryFilters), flags.outputDir, false, "stderr"));
|
|
95221
97026
|
} finally {
|
|
95222
97027
|
snapshot.cleanup();
|
|
95223
97028
|
}
|
|
97029
|
+
finalizeScans({
|
|
97030
|
+
completedScans,
|
|
97031
|
+
mode: "staged",
|
|
97032
|
+
diff: null,
|
|
97033
|
+
baselineIntended: false,
|
|
97034
|
+
isJsonMode,
|
|
97035
|
+
isScoreOnly,
|
|
97036
|
+
flags,
|
|
97037
|
+
categoryFilters,
|
|
97038
|
+
userConfig,
|
|
97039
|
+
resolvedDirectory,
|
|
97040
|
+
startTime
|
|
97041
|
+
});
|
|
95224
97042
|
return;
|
|
95225
97043
|
}
|
|
95226
97044
|
const projectDirectories = await selectProjects(resolvedDirectory, flags.project, skipPrompts, userConfig?.projects);
|
|
95227
|
-
const
|
|
97045
|
+
const projectSelectionCompletedTime = performance$1.now();
|
|
97046
|
+
let changedFilesDiffInfo = flags.changedFilesFrom ? buildChangedFilesDiffInfo(readChangedFilesFrom(Path.resolve(flags.changedFilesFrom))) : null;
|
|
97047
|
+
if (changedFilesDiffInfo !== null && scanTarget.didRedirectViaRootDir) {
|
|
97048
|
+
const relativeProjectDirectory = resolveProjectRelativeDirectory(requestedDirectory, resolvedDirectory);
|
|
97049
|
+
if (relativeProjectDirectory) {
|
|
97050
|
+
const projectPrefix = `${relativeProjectDirectory}/`;
|
|
97051
|
+
changedFilesDiffInfo = {
|
|
97052
|
+
...changedFilesDiffInfo,
|
|
97053
|
+
changedFiles: changedFilesDiffInfo.changedFiles.flatMap((filePath) => {
|
|
97054
|
+
return filePath.startsWith(projectPrefix) ? [filePath.slice(projectPrefix.length)] : [];
|
|
97055
|
+
})
|
|
97056
|
+
};
|
|
97057
|
+
}
|
|
97058
|
+
}
|
|
95228
97059
|
const requestedScope = resolveScope(flags, userConfig);
|
|
95229
97060
|
const includeUntracked = flags.includeUntracked ?? false;
|
|
95230
97061
|
const scopeRequest = requestedScope.scope === void 0 && changedFilesDiffInfo !== null ? {
|
|
@@ -95232,15 +97063,20 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95232
97063
|
scope: "changed"
|
|
95233
97064
|
} : requestedScope;
|
|
95234
97065
|
validateIncludeUntrackedScope(includeUntracked, scopeRequest.scope);
|
|
97066
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
97067
|
+
if (scanStartupSpinner !== null) recordDistribution(METRIC.scanFeedbackDelay, performance$1.now() - projectSelectionCompletedTime, { unit: "millisecond" });
|
|
95235
97068
|
const wantsDiffMode = scopeRequest.scope !== void 0 && scopeRequest.scope !== "full";
|
|
95236
97069
|
const shouldDetectDiff = changedFilesDiffInfo === null && (wantsDiffMode || scopeRequest.scope === void 0 && !skipPrompts && !isQuiet);
|
|
95237
97070
|
const diffInfo = changedFilesDiffInfo ?? (shouldDetectDiff ? await getDiffInfo(resolvedDirectory, scopeRequest.base, includeUntracked) : null);
|
|
97071
|
+
scanStartupSpinner?.stop();
|
|
97072
|
+
scanStartupSpinner = null;
|
|
95238
97073
|
const scope = await finalizeScope({
|
|
95239
97074
|
requested: scopeRequest,
|
|
95240
97075
|
diffInfo,
|
|
95241
97076
|
skipPrompts,
|
|
95242
97077
|
isQuiet
|
|
95243
97078
|
});
|
|
97079
|
+
scanStartupSpinner = !isQuiet ? spinner("Scanning...").start() : null;
|
|
95244
97080
|
const isDiffMode = scope !== "full";
|
|
95245
97081
|
const comparisonBaseRef = isDiffMode && diffInfo && !diffInfo.isCurrentChanges ? diffInfo.baseSha ? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseSha) : diffInfo.diffBaseRef ?? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseBranch) : null;
|
|
95246
97082
|
const baselineRef = scope === "changed" ? comparisonBaseRef : null;
|
|
@@ -95252,6 +97088,8 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95252
97088
|
files: [...diffInfo.changedFiles],
|
|
95253
97089
|
includeUntracked
|
|
95254
97090
|
}) : null;
|
|
97091
|
+
scanStartupSpinner?.stop();
|
|
97092
|
+
scanStartupSpinner = null;
|
|
95255
97093
|
if (scope === "lines" && changedLineRanges === null && !isQuiet) {
|
|
95256
97094
|
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
95257
97095
|
cliLogger.break();
|
|
@@ -95265,7 +97103,6 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95265
97103
|
}
|
|
95266
97104
|
cliLogger.break();
|
|
95267
97105
|
}
|
|
95268
|
-
const completedScans = [];
|
|
95269
97106
|
const isMultiProject = projectDirectories.length > 1;
|
|
95270
97107
|
const scanProject = async (projectDirectory) => {
|
|
95271
97108
|
const projectScanTarget = projectDirectory === resolvedDirectory ? scanTarget : await resolveScanTarget(projectDirectory, { allowAmbiguous: true });
|
|
@@ -95293,7 +97130,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95293
97130
|
if (supplyChainManifestChanged) includePaths.push("package.json");
|
|
95294
97131
|
}
|
|
95295
97132
|
if (!isQuiet && !isMultiProject) cliLogger.dim(" ");
|
|
95296
|
-
const scanResult = await
|
|
97133
|
+
const scanResult = await inspectProject(scanDirectory, {
|
|
95297
97134
|
...scanOptions,
|
|
95298
97135
|
deadlineEpochMs: scanDeadlineEpochMs,
|
|
95299
97136
|
includePaths,
|
|
@@ -95316,29 +97153,13 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95316
97153
|
config: projectConfig
|
|
95317
97154
|
};
|
|
95318
97155
|
};
|
|
95319
|
-
const
|
|
95320
|
-
|
|
95321
|
-
|
|
95322
|
-
|
|
95323
|
-
|
|
95324
|
-
|
|
95325
|
-
|
|
95326
|
-
let scanOutcomes;
|
|
95327
|
-
try {
|
|
95328
|
-
scanOutcomes = await mapWithConcurrency(projectDirectories, isMultiProject ? 4 : 1, async (projectDirectory) => {
|
|
95329
|
-
const scanOutcome = await scanProject(projectDirectory);
|
|
95330
|
-
finishedProjectCount += 1;
|
|
95331
|
-
batchSpinner?.update(`Scanning ${projectCount} projects… (${finishedProjectCount}/${projectCount})`);
|
|
95332
|
-
return scanOutcome;
|
|
95333
|
-
});
|
|
95334
|
-
} finally {
|
|
95335
|
-
if (ownsBatchSpinnerSilence) setSpinnerSilent(wasSpinnerSilent);
|
|
95336
|
-
batchSpinner?.stop();
|
|
95337
|
-
}
|
|
95338
|
-
for (const scanOutcome of scanOutcomes) {
|
|
95339
|
-
if (scanOutcome === null) continue;
|
|
95340
|
-
completedScans.push(scanOutcome);
|
|
95341
|
-
}
|
|
97156
|
+
const projectBatch = await runProjectScanBatch({
|
|
97157
|
+
projects: projectDirectories,
|
|
97158
|
+
isQuiet,
|
|
97159
|
+
isSilent: scanOptions.silent === true,
|
|
97160
|
+
scanProject
|
|
97161
|
+
});
|
|
97162
|
+
const completedScans = projectBatch.completedScans;
|
|
95342
97163
|
if (!isQuiet && isMultiProject && completedScans.length > 0) {
|
|
95343
97164
|
const showShareLink = !isShareOptedOut(completedScans, scanOptions.noScore) && !scanOptions.isCi;
|
|
95344
97165
|
await runPromise(printMultiProjectSummary({
|
|
@@ -95348,7 +97169,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95348
97169
|
outputDirectory: flags.outputDir,
|
|
95349
97170
|
isOffline: !showShareLink,
|
|
95350
97171
|
projectName: Path.basename(resolvedDirectory),
|
|
95351
|
-
totalElapsedMilliseconds:
|
|
97172
|
+
totalElapsedMilliseconds: projectBatch.elapsedMilliseconds
|
|
95352
97173
|
}));
|
|
95353
97174
|
}
|
|
95354
97175
|
const selectedSurfaceDiagnostics = filterDiagnosticsByCategories(filterScansForSurface(completedScans, scanOptions.outputSurface ?? "cli"), categoryFilters);
|
|
@@ -95395,6 +97216,7 @@ const inspectAction = async (directory, flags, invocationCommand = "inspect") =>
|
|
|
95395
97216
|
}
|
|
95396
97217
|
}
|
|
95397
97218
|
} catch (error) {
|
|
97219
|
+
scanStartupSpinner?.stop();
|
|
95398
97220
|
const isUserError = isExpectedUserError(error);
|
|
95399
97221
|
const sentryEventId = isUserError ? void 0 : await reportErrorToSentry(error);
|
|
95400
97222
|
if (isDebugFlagEnabled()) await flushSentry();
|
|
@@ -96329,6 +98151,7 @@ const COMMAND_FLAG_SPECS = new Map([
|
|
|
96329
98151
|
"--no-color",
|
|
96330
98152
|
"--no-dead-code",
|
|
96331
98153
|
"--no-score",
|
|
98154
|
+
"--no-supply-chain",
|
|
96332
98155
|
"--yes"
|
|
96333
98156
|
]),
|
|
96334
98157
|
longOptionsWithRequiredValues: new Set(["--blocking", "--project"]),
|
|
@@ -96492,7 +98315,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
96492
98315
|
${highlighter.info(CI_URL)}
|
|
96493
98316
|
`;
|
|
96494
98317
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
96495
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
98318
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS and inline HTML script source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").option("--include-untracked", "with --scope files/changed/lines, also scan ordinary untracked files (respects .gitignore)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks (honors --project and config `projects`; exits 0 when nothing is staged)").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
96496
98319
|
program.action(inspectAction);
|
|
96497
98320
|
program.command("design [directory]").description("Run only the focused UI design diagnostics").addHelpText("after", renderDesignHelpEpilog).action((directory, _options, command) => designAction(directory ?? ".", command.optsWithGlobals()));
|
|
96498
98321
|
program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
|
|
@@ -96514,15 +98337,17 @@ rules.command("category <category> <severity>").description("Set the severity fo
|
|
|
96514
98337
|
rules.command("ignore-tag <tag>").description("Skip a whole rule family by tag before linting (e.g. design)").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesIgnoreTagAction(tag, command.optsWithGlobals()));
|
|
96515
98338
|
rules.command("unignore-tag <tag>").description("Stop ignoring a tag previously skipped via ignore-tag").option("-c, --cwd <cwd>", "working directory", process.cwd()).action((tag, _options, command) => rulesUnignoreTagAction(tag, command.optsWithGlobals()));
|
|
96516
98339
|
program.command("experimental-lsp", { hidden: false }).description("[experimental] run the React Doctor language server over stdio (for editors)").allowUnknownOption().action(() => {});
|
|
96517
|
-
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
98340
|
+
program.command("experimental-tui [directory]", { hidden: true }).description("[experimental] interactive, scrollable scan report").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").option("--no-dead-code", "skip dead-code analysis").option("--no-supply-chain", "skip the dependency supply-chain scan").option("--no-score", "skip the score API, the share URL, and crash reporting").option("-p, --project <names>", "scan specific workspace projects (comma-separated, or *)").option("-y, --yes", "skip the project prompt and scan every discovered project").action(async (directory = ".", _localOptions, command) => {
|
|
96518
98341
|
const options = command.optsWithGlobals();
|
|
96519
98342
|
const deadCode = options.deadCode === false ? false : void 0;
|
|
96520
98343
|
const noScore = options.score === false ? true : void 0;
|
|
98344
|
+
const supplyChain = options.supplyChain === false ? false : void 0;
|
|
96521
98345
|
const nodeMajorVersion = Number(process.versions.node.split(".")[0]);
|
|
96522
98346
|
if (process.stdout.isTTY !== true || process.stdin.isTTY !== true || isNonInteractiveEnvironment() || nodeMajorVersion < 22) {
|
|
96523
98347
|
await inspectAction(directory, {
|
|
96524
98348
|
deadCode,
|
|
96525
98349
|
score: options.score === false ? false : void 0,
|
|
98350
|
+
supplyChain,
|
|
96526
98351
|
project: options.project,
|
|
96527
98352
|
yes: options.yes,
|
|
96528
98353
|
blocking: options.blocking
|
|
@@ -96530,12 +98355,13 @@ program.command("experimental-tui [directory]", { hidden: true }).description("[
|
|
|
96530
98355
|
return;
|
|
96531
98356
|
}
|
|
96532
98357
|
recordCount(METRIC.cliInvoked, 1, { command: "experimental-tui" });
|
|
96533
|
-
const { runScanApp } = await import("./run-scan-app-
|
|
98358
|
+
const { runScanApp } = await import("./run-scan-app-DHRvqfkX.js");
|
|
96534
98359
|
const { shouldFail } = await runScanApp({
|
|
96535
98360
|
directory,
|
|
96536
98361
|
options: {
|
|
96537
98362
|
deadCode,
|
|
96538
|
-
noScore
|
|
98363
|
+
noScore,
|
|
98364
|
+
supplyChain
|
|
96539
98365
|
},
|
|
96540
98366
|
projectFlag: options.project,
|
|
96541
98367
|
skipPrompts: options.yes ?? false,
|
|
@@ -96569,7 +98395,7 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
96569
98395
|
handleError(error, { sentryEventId });
|
|
96570
98396
|
});
|
|
96571
98397
|
//#endregion
|
|
96572
|
-
export { toForwardSlashes as A,
|
|
98398
|
+
export { toForwardSlashes as A, getCategoryImpact as B, buildRulePriorityMap as C, resolveBlockingLevel as D, formatLearnMoreLine as E, TUI_REPORT_DETAIL_WIDTH_FRACTION as F, runPromise as G, mapWithConcurrency as H, isCiEnvironment as I, succeed$3 as J, sync as K, DIAGNOSTIC_CATEGORY_BUCKETS as L, isUnicodeSupported as M, METRIC as N, isReactDoctorWorkflowInstalled as O, TUI_REPORT_COMPACT_MAX_ROWS as P, Progress as R, hasLintHardFailure as S, formatFixRecipeLine as T, mergeReactDoctorConfigs as U, highlighter as V, resolveScanTarget as W, canAnimateOnboarding as _, resolveCliInspectOptions as a, buildCodeFrame as b, detectLaunchableAgents as c, launchCliAgent as d, isShareOptedOut as f, doctorFace as g, easeOutCubic as h, selectProjects as i, findNearestPackageDirectory as j, recordCount as k, CLI_AGENT_BINARIES as l, printFooter as m, shouldFailScanGate as n, countUniqueScannedFiles as o, createInvocationInspect as p, void_ as q, discoverWorkspacePackages as r, setUpGitHubActions as s, exitGracefully as t, copyToClipboard as u, computeProjectedScore as v, buildSortedRuleGroups as w, buildNoScoreMessage as x, formatElapsedTime as y, Reporter as z };
|
|
96573
98399
|
|
|
96574
98400
|
//# sourceMappingURL=cli.js.map
|
|
96575
|
-
//# debugId=
|
|
98401
|
+
//# debugId=3bff4f9b-31f8-5abe-b7a2-a0ab9f6a85b4
|