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/dist/index.js CHANGED
@@ -1,8 +1,8 @@
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]="eb93b210-c190-581c-8fe2-f1e1c70e0bab")}catch(e){}}();
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]="61d9689f-8ba5-5ca3-a0c2-09557d3f7028")}catch(e){}}();
3
3
  import { i as __toESM$1, r as __require, t as __commonJSMin$1 } from "./chunk-ChKA3wi6.js";
4
4
  import { createRequire } from "node:module";
5
- import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
5
+ 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";
6
6
  import * as Crypto from "node:crypto";
7
7
  import crypto, { createHash } from "node:crypto";
8
8
  import * as NFS from "node:fs";
@@ -11,14 +11,16 @@ import * as Path from "node:path";
11
11
  import path from "node:path";
12
12
  import * as NodeChildProcess from "node:child_process";
13
13
  import { execFileSync, spawn, spawnSync } from "node:child_process";
14
+ import { ResolverFactory } from "oxc-resolver";
14
15
  import ts from "typescript";
16
+ import * as NodeUrl from "node:url";
17
+ import { fileURLToPath } from "node:url";
15
18
  import * as OS from "node:os";
16
19
  import os from "node:os";
17
20
  import { parseJSON5 } from "confbox";
18
- import * as NodeUrl from "node:url";
19
- import { fileURLToPath } 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
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Pipeable.js
24
26
  /**
@@ -10261,7 +10263,7 @@ const Number$4 = globalThis.Number;
10261
10263
  * @category constructors
10262
10264
  * @since 2.0.0
10263
10265
  */
10264
- const parse = (s) => {
10266
+ const parse$1 = (s) => {
10265
10267
  if (s === "NaN") return some(NaN);
10266
10268
  if (s === "Infinity") return some(Infinity);
10267
10269
  if (s === "-Infinity") return some(-Infinity);
@@ -14303,12 +14305,12 @@ TaggedError("EncodingError");
14303
14305
  //#endregion
14304
14306
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/internal/schema/annotations.js
14305
14307
  /** @internal */
14306
- function resolve(ast) {
14308
+ function resolve$1(ast) {
14307
14309
  return ast.checks ? ast.checks[ast.checks.length - 1].annotations : ast.annotations;
14308
14310
  }
14309
14311
  /** @internal */
14310
14312
  function resolveAt(key) {
14311
- return (ast) => resolve(ast)?.[key];
14313
+ return (ast) => resolve$1(ast)?.[key];
14312
14314
  }
14313
14315
  /** @internal */
14314
14316
  const resolveIdentifier = /* @__PURE__ */ resolveAt("identifier");
@@ -18060,7 +18062,7 @@ function asSync(parser) {
18060
18062
  }
18061
18063
  const recur$1 = /* @__PURE__ */ memoize((ast) => {
18062
18064
  let parser;
18063
- const astOptions = resolve(ast)?.["parseOptions"];
18065
+ const astOptions = resolve$1(ast)?.["parseOptions"];
18064
18066
  if (!ast.context && !ast.encoding && !ast.checks) return (ou, options) => {
18065
18067
  parser ??= ast.getParser(recur$1);
18066
18068
  if (astOptions) options = {
@@ -57665,7 +57667,7 @@ var UrlParamsError = class extends TaggedError("UrlParamsError") {};
57665
57667
  * @category converting
57666
57668
  * @since 4.0.0
57667
57669
  */
57668
- const makeUrl = (url, params, hash) => {
57670
+ const makeUrl$1 = (url, params, hash) => {
57669
57671
  try {
57670
57672
  const urlInstance = new URL(url, baseUrl());
57671
57673
  for (let i = 0; i < params.params.length; i++) {
@@ -58299,7 +58301,7 @@ const Proto$2 = {
58299
58301
  const make$10 = (f) => makeWith$1((effect) => flatMap$2(effect, (request) => withFiber((fiber) => {
58300
58302
  const scopedController = scopedRequests.get(request);
58301
58303
  const controller = scopedController ?? new AbortController();
58302
- const urlResult = makeUrl(request.url, request.urlParams, getOrUndefined(request.hash));
58304
+ const urlResult = makeUrl$1(request.url, request.urlParams, getOrUndefined(request.hash));
58303
58305
  if (isFailure(urlResult)) return fail$4(new HttpClientError({ reason: new InvalidUrlError({
58304
58306
  request,
58305
58307
  cause: urlResult.failure
@@ -58738,7 +58740,7 @@ const layer$7 = (loggers, options) => effect(CurrentLoggers, withFiber$1(fnUntra
58738
58740
  * @since 4.0.0
58739
58741
  */
58740
58742
  const policy = /* @__PURE__ */ forever$1.pipe(passthrough$2, /* @__PURE__ */ addDelay((error) => {
58741
- 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))));
58743
+ 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))));
58742
58744
  return succeed$2(seconds(1));
58743
58745
  }));
58744
58746
  /**
@@ -61380,6 +61382,428 @@ const layer = /* @__PURE__ */ succeed$3(Path$1)({
61380
61382
  toFileUrl
61381
61383
  });
61382
61384
  //#endregion
61385
+ //#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
61386
+ var comma = ",".charCodeAt(0);
61387
+ ";".charCodeAt(0);
61388
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61389
+ var intToChar = new Uint8Array(64);
61390
+ var charToInt = new Uint8Array(128);
61391
+ for (let i = 0; i < chars.length; i++) {
61392
+ const c = chars.charCodeAt(i);
61393
+ intToChar[i] = c;
61394
+ charToInt[c] = i;
61395
+ }
61396
+ function decodeInteger(reader, relative) {
61397
+ let value = 0;
61398
+ let shift = 0;
61399
+ let integer = 0;
61400
+ do {
61401
+ integer = charToInt[reader.next()];
61402
+ value |= (integer & 31) << shift;
61403
+ shift += 5;
61404
+ } while (integer & 32);
61405
+ const shouldNegate = value & 1;
61406
+ value >>>= 1;
61407
+ if (shouldNegate) value = -2147483648 | -value;
61408
+ return relative + value;
61409
+ }
61410
+ function hasMoreVlq(reader, max) {
61411
+ if (reader.pos >= max) return false;
61412
+ return reader.peek() !== comma;
61413
+ }
61414
+ var StringReader = class {
61415
+ constructor(buffer) {
61416
+ this.pos = 0;
61417
+ this.buffer = buffer;
61418
+ }
61419
+ next() {
61420
+ return this.buffer.charCodeAt(this.pos++);
61421
+ }
61422
+ peek() {
61423
+ return this.buffer.charCodeAt(this.pos);
61424
+ }
61425
+ indexOf(char) {
61426
+ const { buffer, pos } = this;
61427
+ const idx = buffer.indexOf(char, pos);
61428
+ return idx === -1 ? buffer.length : idx;
61429
+ }
61430
+ };
61431
+ function decode(mappings) {
61432
+ const { length } = mappings;
61433
+ const reader = new StringReader(mappings);
61434
+ const decoded = [];
61435
+ let genColumn = 0;
61436
+ let sourcesIndex = 0;
61437
+ let sourceLine = 0;
61438
+ let sourceColumn = 0;
61439
+ let namesIndex = 0;
61440
+ do {
61441
+ const semi = reader.indexOf(";");
61442
+ const line = [];
61443
+ let sorted = true;
61444
+ let lastCol = 0;
61445
+ genColumn = 0;
61446
+ while (reader.pos < semi) {
61447
+ let seg;
61448
+ genColumn = decodeInteger(reader, genColumn);
61449
+ if (genColumn < lastCol) sorted = false;
61450
+ lastCol = genColumn;
61451
+ if (hasMoreVlq(reader, semi)) {
61452
+ sourcesIndex = decodeInteger(reader, sourcesIndex);
61453
+ sourceLine = decodeInteger(reader, sourceLine);
61454
+ sourceColumn = decodeInteger(reader, sourceColumn);
61455
+ if (hasMoreVlq(reader, semi)) {
61456
+ namesIndex = decodeInteger(reader, namesIndex);
61457
+ seg = [
61458
+ genColumn,
61459
+ sourcesIndex,
61460
+ sourceLine,
61461
+ sourceColumn,
61462
+ namesIndex
61463
+ ];
61464
+ } else seg = [
61465
+ genColumn,
61466
+ sourcesIndex,
61467
+ sourceLine,
61468
+ sourceColumn
61469
+ ];
61470
+ } else seg = [genColumn];
61471
+ line.push(seg);
61472
+ reader.pos++;
61473
+ }
61474
+ if (!sorted) sort(line);
61475
+ decoded.push(line);
61476
+ reader.pos = semi + 1;
61477
+ } while (reader.pos <= length);
61478
+ return decoded;
61479
+ }
61480
+ function sort(line) {
61481
+ line.sort(sortComparator$1);
61482
+ }
61483
+ function sortComparator$1(a, b) {
61484
+ return a[0] - b[0];
61485
+ }
61486
+ //#endregion
61487
+ //#region ../../node_modules/.pnpm/@jridgewell+resolve-uri@3.1.2/node_modules/@jridgewell/resolve-uri/dist/resolve-uri.mjs
61488
+ const schemeRegex = /^[\w+.-]+:\/\//;
61489
+ /**
61490
+ * Matches the parts of a URL:
61491
+ * 1. Scheme, including ":", guaranteed.
61492
+ * 2. User/password, including "@", optional.
61493
+ * 3. Host, guaranteed.
61494
+ * 4. Port, including ":", optional.
61495
+ * 5. Path, including "/", optional.
61496
+ * 6. Query, including "?", optional.
61497
+ * 7. Hash, including "#", optional.
61498
+ */
61499
+ const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/;
61500
+ /**
61501
+ * File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start
61502
+ * with a leading `/`, they can have a domain (but only if they don't start with a Windows drive).
61503
+ *
61504
+ * 1. Host, optional.
61505
+ * 2. Path, which may include "/", guaranteed.
61506
+ * 3. Query, including "?", optional.
61507
+ * 4. Hash, including "#", optional.
61508
+ */
61509
+ const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i;
61510
+ function isAbsoluteUrl(input) {
61511
+ return schemeRegex.test(input);
61512
+ }
61513
+ function isSchemeRelativeUrl(input) {
61514
+ return input.startsWith("//");
61515
+ }
61516
+ function isAbsolutePath(input) {
61517
+ return input.startsWith("/");
61518
+ }
61519
+ function isFileUrl(input) {
61520
+ return input.startsWith("file:");
61521
+ }
61522
+ function isRelative(input) {
61523
+ return /^[.?#]/.test(input);
61524
+ }
61525
+ function parseAbsoluteUrl(input) {
61526
+ const match = urlRegex.exec(input);
61527
+ return makeUrl(match[1], match[2] || "", match[3], match[4] || "", match[5] || "/", match[6] || "", match[7] || "");
61528
+ }
61529
+ function parseFileUrl(input) {
61530
+ const match = fileRegex.exec(input);
61531
+ const path = match[2];
61532
+ return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path) ? path : "/" + path, match[3] || "", match[4] || "");
61533
+ }
61534
+ function makeUrl(scheme, user, host, port, path, query, hash) {
61535
+ return {
61536
+ scheme,
61537
+ user,
61538
+ host,
61539
+ port,
61540
+ path,
61541
+ query,
61542
+ hash,
61543
+ type: 7
61544
+ };
61545
+ }
61546
+ function parseUrl(input) {
61547
+ if (isSchemeRelativeUrl(input)) {
61548
+ const url = parseAbsoluteUrl("http:" + input);
61549
+ url.scheme = "";
61550
+ url.type = 6;
61551
+ return url;
61552
+ }
61553
+ if (isAbsolutePath(input)) {
61554
+ const url = parseAbsoluteUrl("http://foo.com" + input);
61555
+ url.scheme = "";
61556
+ url.host = "";
61557
+ url.type = 5;
61558
+ return url;
61559
+ }
61560
+ if (isFileUrl(input)) return parseFileUrl(input);
61561
+ if (isAbsoluteUrl(input)) return parseAbsoluteUrl(input);
61562
+ const url = parseAbsoluteUrl("http://foo.com/" + input);
61563
+ url.scheme = "";
61564
+ url.host = "";
61565
+ url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
61566
+ return url;
61567
+ }
61568
+ function stripPathFilename(path) {
61569
+ if (path.endsWith("/..")) return path;
61570
+ const index = path.lastIndexOf("/");
61571
+ return path.slice(0, index + 1);
61572
+ }
61573
+ function mergePaths(url, base) {
61574
+ normalizePath(base, base.type);
61575
+ if (url.path === "/") url.path = base.path;
61576
+ else url.path = stripPathFilename(base.path) + url.path;
61577
+ }
61578
+ /**
61579
+ * The path can have empty directories "//", unneeded parents "foo/..", or current directory
61580
+ * "foo/.". We need to normalize to a standard representation.
61581
+ */
61582
+ function normalizePath(url, type) {
61583
+ const rel = type <= 4;
61584
+ const pieces = url.path.split("/");
61585
+ let pointer = 1;
61586
+ let positive = 0;
61587
+ let addTrailingSlash = false;
61588
+ for (let i = 1; i < pieces.length; i++) {
61589
+ const piece = pieces[i];
61590
+ if (!piece) {
61591
+ addTrailingSlash = true;
61592
+ continue;
61593
+ }
61594
+ addTrailingSlash = false;
61595
+ if (piece === ".") continue;
61596
+ if (piece === "..") {
61597
+ if (positive) {
61598
+ addTrailingSlash = true;
61599
+ positive--;
61600
+ pointer--;
61601
+ } else if (rel) pieces[pointer++] = piece;
61602
+ continue;
61603
+ }
61604
+ pieces[pointer++] = piece;
61605
+ positive++;
61606
+ }
61607
+ let path = "";
61608
+ for (let i = 1; i < pointer; i++) path += "/" + pieces[i];
61609
+ if (!path || addTrailingSlash && !path.endsWith("/..")) path += "/";
61610
+ url.path = path;
61611
+ }
61612
+ /**
61613
+ * Attempts to resolve `input` URL/path relative to `base`.
61614
+ */
61615
+ function resolve(input, base) {
61616
+ if (!input && !base) return "";
61617
+ const url = parseUrl(input);
61618
+ let inputType = url.type;
61619
+ if (base && inputType !== 7) {
61620
+ const baseUrl = parseUrl(base);
61621
+ const baseType = baseUrl.type;
61622
+ switch (inputType) {
61623
+ case 1: url.hash = baseUrl.hash;
61624
+ case 2: url.query = baseUrl.query;
61625
+ case 3:
61626
+ case 4: mergePaths(url, baseUrl);
61627
+ case 5:
61628
+ url.user = baseUrl.user;
61629
+ url.host = baseUrl.host;
61630
+ url.port = baseUrl.port;
61631
+ case 6: url.scheme = baseUrl.scheme;
61632
+ }
61633
+ if (baseType > inputType) inputType = baseType;
61634
+ }
61635
+ normalizePath(url, inputType);
61636
+ const queryHash = url.query + url.hash;
61637
+ switch (inputType) {
61638
+ case 2:
61639
+ case 3: return queryHash;
61640
+ case 4: {
61641
+ const path = url.path.slice(1);
61642
+ if (!path) return queryHash || ".";
61643
+ if (isRelative(base || input) && !isRelative(path)) return "./" + path + queryHash;
61644
+ return path + queryHash;
61645
+ }
61646
+ case 5: return url.path + queryHash;
61647
+ default: return url.scheme + "//" + url.user + url.host + url.port + url.path + queryHash;
61648
+ }
61649
+ }
61650
+ //#endregion
61651
+ //#region ../../node_modules/.pnpm/@jridgewell+trace-mapping@0.3.31/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.mjs
61652
+ function stripFilename(path) {
61653
+ if (!path) return "";
61654
+ const index = path.lastIndexOf("/");
61655
+ return path.slice(0, index + 1);
61656
+ }
61657
+ function resolver(mapUrl, sourceRoot) {
61658
+ const from = stripFilename(mapUrl);
61659
+ const prefix = sourceRoot ? sourceRoot + "/" : "";
61660
+ return (source) => resolve(prefix + (source || ""), from);
61661
+ }
61662
+ var COLUMN = 0;
61663
+ var SOURCES_INDEX = 1;
61664
+ var SOURCE_LINE = 2;
61665
+ var SOURCE_COLUMN = 3;
61666
+ var NAMES_INDEX = 4;
61667
+ function maybeSort(mappings, owned) {
61668
+ const unsortedIndex = nextUnsortedSegmentLine(mappings, 0);
61669
+ if (unsortedIndex === mappings.length) return mappings;
61670
+ if (!owned) mappings = mappings.slice();
61671
+ for (let i = unsortedIndex; i < mappings.length; i = nextUnsortedSegmentLine(mappings, i + 1)) mappings[i] = sortSegments(mappings[i], owned);
61672
+ return mappings;
61673
+ }
61674
+ function nextUnsortedSegmentLine(mappings, start) {
61675
+ for (let i = start; i < mappings.length; i++) if (!isSorted(mappings[i])) return i;
61676
+ return mappings.length;
61677
+ }
61678
+ function isSorted(line) {
61679
+ for (let j = 1; j < line.length; j++) if (line[j][COLUMN] < line[j - 1][COLUMN]) return false;
61680
+ return true;
61681
+ }
61682
+ function sortSegments(line, owned) {
61683
+ if (!owned) line = line.slice();
61684
+ return line.sort(sortComparator);
61685
+ }
61686
+ function sortComparator(a, b) {
61687
+ return a[COLUMN] - b[COLUMN];
61688
+ }
61689
+ var found = false;
61690
+ function binarySearch(haystack, needle, low, high) {
61691
+ while (low <= high) {
61692
+ const mid = low + (high - low >> 1);
61693
+ const cmp = haystack[mid][COLUMN] - needle;
61694
+ if (cmp === 0) {
61695
+ found = true;
61696
+ return mid;
61697
+ }
61698
+ if (cmp < 0) low = mid + 1;
61699
+ else high = mid - 1;
61700
+ }
61701
+ found = false;
61702
+ return low - 1;
61703
+ }
61704
+ function upperBound(haystack, needle, index) {
61705
+ for (let i = index + 1; i < haystack.length; index = i++) if (haystack[i][COLUMN] !== needle) break;
61706
+ return index;
61707
+ }
61708
+ function lowerBound(haystack, needle, index) {
61709
+ for (let i = index - 1; i >= 0; index = i--) if (haystack[i][COLUMN] !== needle) break;
61710
+ return index;
61711
+ }
61712
+ function memoizedState() {
61713
+ return {
61714
+ lastKey: -1,
61715
+ lastNeedle: -1,
61716
+ lastIndex: -1
61717
+ };
61718
+ }
61719
+ function memoizedBinarySearch(haystack, needle, state, key) {
61720
+ const { lastKey, lastNeedle, lastIndex } = state;
61721
+ let low = 0;
61722
+ let high = haystack.length - 1;
61723
+ if (key === lastKey) {
61724
+ if (needle === lastNeedle) {
61725
+ found = lastIndex !== -1 && haystack[lastIndex][COLUMN] === needle;
61726
+ return lastIndex;
61727
+ }
61728
+ if (needle >= lastNeedle) low = lastIndex === -1 ? 0 : lastIndex;
61729
+ else high = lastIndex;
61730
+ }
61731
+ state.lastKey = key;
61732
+ state.lastNeedle = needle;
61733
+ return state.lastIndex = binarySearch(haystack, needle, low, high);
61734
+ }
61735
+ function parse(map) {
61736
+ return typeof map === "string" ? JSON.parse(map) : map;
61737
+ }
61738
+ var LINE_GTR_ZERO = "`line` must be greater than 0 (lines start at line 1)";
61739
+ var COL_GTR_EQ_ZERO = "`column` must be greater than or equal to 0 (columns start at column 0)";
61740
+ var TraceMap = class {
61741
+ constructor(map, mapUrl) {
61742
+ const isString = typeof map === "string";
61743
+ if (!isString && map._decodedMemo) return map;
61744
+ const parsed = parse(map);
61745
+ const { version, file, names, sourceRoot, sources, sourcesContent } = parsed;
61746
+ this.version = version;
61747
+ this.file = file;
61748
+ this.names = names || [];
61749
+ this.sourceRoot = sourceRoot;
61750
+ this.sources = sources;
61751
+ this.sourcesContent = sourcesContent;
61752
+ this.ignoreList = parsed.ignoreList || parsed.x_google_ignoreList || void 0;
61753
+ const resolve = resolver(mapUrl, sourceRoot);
61754
+ this.resolvedSources = sources.map(resolve);
61755
+ const { mappings } = parsed;
61756
+ if (typeof mappings === "string") {
61757
+ this._encoded = mappings;
61758
+ this._decoded = void 0;
61759
+ } else if (Array.isArray(mappings)) {
61760
+ this._encoded = void 0;
61761
+ this._decoded = maybeSort(mappings, isString);
61762
+ } else if (parsed.sections) throw new Error(`TraceMap passed sectioned source map, please use FlattenMap export instead`);
61763
+ else throw new Error(`invalid source map: ${JSON.stringify(parsed)}`);
61764
+ this._decodedMemo = memoizedState();
61765
+ this._bySources = void 0;
61766
+ this._bySourceMemos = void 0;
61767
+ }
61768
+ };
61769
+ function cast(map) {
61770
+ return map;
61771
+ }
61772
+ function decodedMappings(map) {
61773
+ var _a;
61774
+ return (_a = cast(map))._decoded || (_a._decoded = decode(cast(map)._encoded));
61775
+ }
61776
+ function originalPositionFor(map, needle) {
61777
+ let { line, column, bias } = needle;
61778
+ line--;
61779
+ if (line < 0) throw new Error(LINE_GTR_ZERO);
61780
+ if (column < 0) throw new Error(COL_GTR_EQ_ZERO);
61781
+ const decoded = decodedMappings(map);
61782
+ if (line >= decoded.length) return OMapping(null, null, null, null);
61783
+ const segments = decoded[line];
61784
+ const index = traceSegmentInternal(segments, cast(map)._decodedMemo, line, column, bias || 1);
61785
+ if (index === -1) return OMapping(null, null, null, null);
61786
+ const segment = segments[index];
61787
+ if (segment.length === 1) return OMapping(null, null, null, null);
61788
+ const { names, resolvedSources } = map;
61789
+ return OMapping(resolvedSources[segment[SOURCES_INDEX]], segment[SOURCE_LINE] + 1, segment[SOURCE_COLUMN], segment.length === 5 ? names[segment[NAMES_INDEX]] : null);
61790
+ }
61791
+ function OMapping(source, line, column, name) {
61792
+ return {
61793
+ source,
61794
+ line,
61795
+ column,
61796
+ name
61797
+ };
61798
+ }
61799
+ function traceSegmentInternal(segments, memo, line, column, bias) {
61800
+ let index = memoizedBinarySearch(segments, column, memo, line);
61801
+ if (found) index = (bias === -1 ? upperBound : lowerBound)(segments, column, index);
61802
+ else if (bias === -1) index++;
61803
+ if (index === -1 || index === segments.length) return -1;
61804
+ return index;
61805
+ }
61806
+ //#endregion
61383
61807
  //#region ../core/dist/index.js
61384
61808
  var __create = Object.create;
61385
61809
  var __defProp = Object.defineProperty;
@@ -61448,7 +61872,8 @@ var AmbiguousProjectError = class extends Error {
61448
61872
  }
61449
61873
  };
61450
61874
  const isProjectDiscoveryError = (value) => value instanceof ProjectNotFoundError || value instanceof NoReactDependencyError || value instanceof PackageJsonNotFoundError || value instanceof NotADirectoryError || value instanceof AmbiguousProjectError;
61451
- const SOURCE_FILE_PATTERN = /\.(tsx?|jsx?|mts|mjs)$/;
61875
+ const HTML_FILE_PATTERN = /\.html$/i;
61876
+ const SOURCE_FILE_PATTERN = /\.(?:astro|tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/;
61452
61877
  const GENERATED_BUNDLE_FILE_PATTERN = /\.(iife|umd|global|min)\.m?js$/i;
61453
61878
  const GENERATED_SOURCE_DIRECTORY_PATTERN = /(?:^|\/)__generated__\//;
61454
61879
  const MINIFIED_SNIFF_BYTES = 65536;
@@ -61791,7 +62216,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
61791
62216
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
61792
62217
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
61793
62218
  const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
61794
- const CORE_PACKAGE_VERSION = "0.9.1";
62219
+ const CORE_PACKAGE_VERSION = "0.9.2";
61795
62220
  const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
61796
62221
  const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
61797
62222
  const SUPPLY_CHAIN_PLUGIN = "socket";
@@ -62041,8 +62466,13 @@ const findMonorepoRoot = (startDirectory) => {
62041
62466
  * byte-equivalent copy.
62042
62467
  */
62043
62468
  const isProjectBoundary = (directory) => NFS.existsSync(Path.join(directory, ".git")) || isMonorepoRoot(directory);
62469
+ const unwrapTypescriptExpression = (expression) => {
62470
+ let currentExpression = expression;
62471
+ while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
62472
+ return currentExpression;
62473
+ };
62044
62474
  const TSCONFIG_FILENAME = "tsconfig.json";
62045
- const isRelativeExtendsValue = (extendsValue) => extendsValue.startsWith("./") || extendsValue.startsWith("../") || Path.isAbsolute(extendsValue);
62475
+ const isLocalModuleSpecifier = (moduleSpecifier) => moduleSpecifier === "." || moduleSpecifier === ".." || moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../") || Path.isAbsolute(moduleSpecifier);
62046
62476
  const ensureJsonExtension = (filePath) => Path.extname(filePath) === "" ? `${filePath}.json` : filePath;
62047
62477
  const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
62048
62478
  const requireFromConfig = createRequire(Path.join(fromConfigDirectory, "tsconfig.json"));
@@ -62059,7 +62489,12 @@ const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
62059
62489
  return null;
62060
62490
  };
62061
62491
  const resolveExtendsPath = (extendsValue, fromConfigDirectory) => {
62062
- if (isRelativeExtendsValue(extendsValue)) return ensureJsonExtension(Path.resolve(fromConfigDirectory, extendsValue));
62492
+ if (isLocalModuleSpecifier(extendsValue)) {
62493
+ const resolvedPath = Path.resolve(fromConfigDirectory, extendsValue);
62494
+ if (isFile(resolvedPath)) return resolvedPath;
62495
+ const directoryConfigPath = Path.join(resolvedPath, TSCONFIG_FILENAME);
62496
+ return isFile(directoryConfigPath) ? directoryConfigPath : ensureJsonExtension(resolvedPath);
62497
+ }
62063
62498
  return resolvePackageExtendsPath(extendsValue, fromConfigDirectory);
62064
62499
  };
62065
62500
  const normalizeCompilerOptions = (compilerOptions) => {
@@ -62166,6 +62601,7 @@ const FRAMEWORK_PACKAGES = {
62166
62601
  "@tanstack/react-start": "tanstack-start",
62167
62602
  "@remix-run/react": "remix",
62168
62603
  gatsby: "gatsby",
62604
+ astro: "astro",
62169
62605
  vite: "vite",
62170
62606
  "react-scripts": "cra",
62171
62607
  expo: "expo",
@@ -62253,6 +62689,15 @@ const REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS = [
62253
62689
  ".cts",
62254
62690
  ".json"
62255
62691
  ];
62692
+ const REACT_COMPILER_CONFIG_RESOLVER = new ResolverFactory({
62693
+ conditionNames: [
62694
+ "import",
62695
+ "require",
62696
+ "node",
62697
+ "default"
62698
+ ],
62699
+ extensions: REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS
62700
+ });
62256
62701
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
62257
62702
  const hasCompilerPackage = (packageJson, compilerPackages) => {
62258
62703
  const allDependencies = {
@@ -62276,6 +62721,18 @@ const hasCompilerPackageInAncestors = (directory, compilerPackages) => {
62276
62721
  return false;
62277
62722
  };
62278
62723
  const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
62724
+ if (!isLocalModuleSpecifier(moduleSpecifier)) {
62725
+ try {
62726
+ const resolvedPath = REACT_COMPILER_CONFIG_RESOLVER.resolveFileSync(fromFilePath, moduleSpecifier).path;
62727
+ if (resolvedPath && isFile(resolvedPath)) return resolvedPath;
62728
+ } catch {}
62729
+ try {
62730
+ const resolvedPath = createRequire(fromFilePath).resolve(moduleSpecifier);
62731
+ return isFile(resolvedPath) ? resolvedPath : null;
62732
+ } catch {
62733
+ return null;
62734
+ }
62735
+ }
62279
62736
  const unresolvedPath = Path.resolve(Path.dirname(fromFilePath), moduleSpecifier);
62280
62737
  const extension = Path.extname(unresolvedPath);
62281
62738
  return (extension ? [unresolvedPath, ...REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS.map((sourceExtension) => `${unresolvedPath.slice(0, -extension.length)}${sourceExtension}`)] : [
@@ -62285,10 +62742,10 @@ const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
62285
62742
  ]).find(isFile) ?? null;
62286
62743
  };
62287
62744
  const parseConfigSourceFile = (filePath, content) => filePath.endsWith(".json") || Path.basename(filePath) === ".babelrc" ? ts.parseJsonText(filePath, content) : ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
62288
- const getStaticPropertyName$1 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
62745
+ const getStaticPropertyName$2 = (propertyName) => ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName) ? propertyName.text : ts.isComputedPropertyName(propertyName) && ts.isStringLiteralLike(propertyName.expression) ? propertyName.expression.text : null;
62289
62746
  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");
62290
62747
  const hasExportModifier = (node) => ts.canHaveModifiers(node) && Boolean(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
62291
- const getRequireModuleSpecifier = (expression) => {
62748
+ const getRequireModuleSpecifier$1 = (expression) => {
62292
62749
  if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== "require" || expression.arguments.length !== 1) return null;
62293
62750
  const moduleSpecifier = expression.arguments[0];
62294
62751
  return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
@@ -62301,7 +62758,7 @@ const hasTopLevelValueBinding = (sourceFile, bindingName) => sourceFile.statemen
62301
62758
  const namedBindings = importClause?.namedBindings;
62302
62759
  return namedBindings ? ts.isNamespaceImport(namedBindings) ? namedBindings.name.text === bindingName : namedBindings.elements.some((element) => element.name.text === bindingName) : false;
62303
62760
  }
62304
- if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => ts.isIdentifier(declaration.name) && declaration.name.text === bindingName);
62761
+ if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.some((declaration) => bindingNameContainsIdentifier(declaration.name, bindingName));
62305
62762
  return (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === bindingName;
62306
62763
  });
62307
62764
  const getImportBinding = (sourceFile, bindingName) => {
@@ -62332,24 +62789,24 @@ const getImportBinding = (sourceFile, bindingName) => {
62332
62789
  for (const declaration of statement.declarationList.declarations) {
62333
62790
  if (!declaration.initializer) continue;
62334
62791
  if (ts.isIdentifier(declaration.name) && declaration.name.text === bindingName) {
62335
- const directModuleSpecifier = getRequireModuleSpecifier(declaration.initializer);
62792
+ const directModuleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
62336
62793
  if (directModuleSpecifier) return {
62337
62794
  moduleSpecifier: directModuleSpecifier,
62338
62795
  exportName: "default",
62339
62796
  isNamespace: true
62340
62797
  };
62341
- if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier(declaration.initializer.expression) !== null) return {
62342
- moduleSpecifier: getRequireModuleSpecifier(declaration.initializer.expression) ?? "",
62798
+ if (ts.isPropertyAccessExpression(declaration.initializer) && getRequireModuleSpecifier$1(declaration.initializer.expression) !== null) return {
62799
+ moduleSpecifier: getRequireModuleSpecifier$1(declaration.initializer.expression) ?? "",
62343
62800
  exportName: declaration.initializer.name.text,
62344
62801
  isNamespace: false
62345
62802
  };
62346
62803
  }
62347
62804
  if (!ts.isObjectBindingPattern(declaration.name)) continue;
62348
62805
  const bindingElement = declaration.name.elements.find((element) => ts.isIdentifier(element.name) && element.name.text === bindingName);
62349
- const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
62806
+ const moduleSpecifier = getRequireModuleSpecifier$1(declaration.initializer);
62350
62807
  if (bindingElement && moduleSpecifier) return {
62351
62808
  moduleSpecifier,
62352
- exportName: bindingElement.propertyName ? getStaticPropertyName$1(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
62809
+ exportName: bindingElement.propertyName ? getStaticPropertyName$2(bindingElement.propertyName) ?? bindingElement.propertyName.getText(sourceFile) : bindingElement.name.getText(sourceFile),
62353
62810
  isNamespace: false
62354
62811
  };
62355
62812
  }
@@ -62366,10 +62823,16 @@ const getTopLevelBinding = (sourceFile, bindingName) => {
62366
62823
  }
62367
62824
  return null;
62368
62825
  };
62369
- const getFunctionLocalBindings = (functionNode, argumentsList) => {
62826
+ const getFunctionLocalBindings = (functionNode, argumentsList, argumentAnalysis, functionAnalysis) => {
62370
62827
  const localBindings = /* @__PURE__ */ new Map();
62371
62828
  functionNode.parameters.forEach((parameter, parameterIndex) => {
62372
- if (ts.isIdentifier(parameter.name)) localBindings.set(parameter.name.text, argumentsList[parameterIndex] ?? parameter.initializer ?? null);
62829
+ if (ts.isIdentifier(parameter.name)) {
62830
+ const argument = argumentsList[parameterIndex];
62831
+ localBindings.set(parameter.name.text, {
62832
+ expression: argument ?? parameter.initializer ?? null,
62833
+ analysis: argument ? argumentAnalysis : functionAnalysis
62834
+ });
62835
+ }
62373
62836
  });
62374
62837
  return localBindings;
62375
62838
  };
@@ -62402,6 +62865,48 @@ const getScopedConfigBinding = (identifier) => {
62402
62865
  };
62403
62866
  };
62404
62867
  const isCompilerTransformModule = (moduleSpecifier, exportName) => moduleSpecifier === "babel-plugin-react-compiler" && exportName === "default" || moduleSpecifier === "@vitejs/plugin-react" && exportName === "reactCompilerPreset";
62868
+ const NODE_MODULE_SPECIFIERS = new Set(["module", "node:module"]);
62869
+ const isConstantVariableInitializer = (node) => ts.isExpression(node) && ts.isVariableDeclaration(node.parent) && ts.isVariableDeclarationList(node.parent.parent) && Boolean(node.parent.parent.flags & ts.NodeFlags.Const);
62870
+ const isNodeCreateRequireCall = (node, analysis) => {
62871
+ if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isTypeAssertionExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node) || ts.isAwaitExpression(node)) return isNodeCreateRequireCall(node.expression, analysis);
62872
+ if (!ts.isCallExpression(node)) return false;
62873
+ const target = node.expression;
62874
+ if (ts.isIdentifier(target)) {
62875
+ if (analysis.localBindings.has(target.text) || getScopedConfigBinding(target).wasFound) return false;
62876
+ const importBinding = getImportBinding(analysis.sourceFile, target.text);
62877
+ return Boolean(importBinding && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier) && importBinding.exportName === "createRequire");
62878
+ }
62879
+ if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return false;
62880
+ if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "createRequire") return false;
62881
+ const createRequireReceiver = target.expression;
62882
+ if (ts.isCallExpression(createRequireReceiver)) {
62883
+ const requiredModuleSpecifier = getRequireModuleSpecifier$1(createRequireReceiver);
62884
+ if (requiredModuleSpecifier === null || !NODE_MODULE_SPECIFIERS.has(requiredModuleSpecifier) || !ts.isIdentifier(createRequireReceiver.expression)) return false;
62885
+ const requireIdentifier = createRequireReceiver.expression;
62886
+ return !analysis.localBindings.has(requireIdentifier.text) && !getScopedConfigBinding(requireIdentifier).wasFound && !hasTopLevelValueBinding(analysis.sourceFile, requireIdentifier.text);
62887
+ }
62888
+ if (!ts.isIdentifier(createRequireReceiver)) return false;
62889
+ if (analysis.localBindings.has(createRequireReceiver.text) || getScopedConfigBinding(createRequireReceiver).wasFound) return false;
62890
+ const importBinding = getImportBinding(analysis.sourceFile, createRequireReceiver.text);
62891
+ return Boolean(importBinding?.isNamespace && NODE_MODULE_SPECIFIERS.has(importBinding.moduleSpecifier));
62892
+ };
62893
+ const getNodeRequireResolveModuleSpecifier = (callExpression, analysis) => {
62894
+ const [moduleSpecifierNode] = callExpression.arguments;
62895
+ if (!moduleSpecifierNode || !ts.isStringLiteralLike(moduleSpecifierNode)) return null;
62896
+ const target = callExpression.expression;
62897
+ if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
62898
+ if ((ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null) !== "resolve") return null;
62899
+ if (isNodeCreateRequireCall(target.expression, analysis)) return moduleSpecifierNode.text;
62900
+ if (!ts.isIdentifier(target.expression)) return null;
62901
+ const resolverIdentifier = target.expression;
62902
+ if (analysis.localBindings.has(resolverIdentifier.text)) return null;
62903
+ const scopedBinding = getScopedConfigBinding(resolverIdentifier);
62904
+ const topLevelBinding = scopedBinding.wasFound ? null : getTopLevelBinding(analysis.sourceFile, resolverIdentifier.text);
62905
+ const resolverInitializer = scopedBinding.wasFound ? scopedBinding.initializer : topLevelBinding;
62906
+ if (resolverInitializer === null && !scopedBinding.wasFound && resolverIdentifier.text === "require" && !hasTopLevelValueBinding(analysis.sourceFile, resolverIdentifier.text) && getImportBinding(analysis.sourceFile, resolverIdentifier.text) === null) return moduleSpecifierNode.text;
62907
+ if (!resolverInitializer || !isConstantVariableInitializer(resolverInitializer) || !isNodeCreateRequireCall(resolverInitializer, analysis)) return null;
62908
+ return moduleSpecifierNode.text;
62909
+ };
62405
62910
  const getAssignedPropertyInitializer = (identifier, propertyName) => {
62406
62911
  let bindingScope = null;
62407
62912
  let currentNode = identifier;
@@ -62444,9 +62949,11 @@ const getAssignedPropertyInitializer = (identifier, propertyName) => {
62444
62949
  initializer: assignedInitializer
62445
62950
  };
62446
62951
  };
62447
- const getStaticConfigValueState = (expression, analysis) => {
62448
- let unwrappedExpression = expression;
62449
- while (ts.isParenthesizedExpression(unwrappedExpression) || ts.isAsExpression(unwrappedExpression) || ts.isTypeAssertionExpression(unwrappedExpression) || ts.isSatisfiesExpression(unwrappedExpression) || ts.isNonNullExpression(unwrappedExpression)) unwrappedExpression = unwrappedExpression.expression;
62952
+ const getStaticConfigValueState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
62953
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
62954
+ if (visitedExpressions.has(unwrappedExpression)) return null;
62955
+ const nextVisitedExpressions = new Set(visitedExpressions);
62956
+ nextVisitedExpressions.add(unwrappedExpression);
62450
62957
  if (unwrappedExpression.kind === ts.SyntaxKind.NullKeyword || ts.isIdentifier(unwrappedExpression) && unwrappedExpression.text === "undefined") return {
62451
62958
  isNullish: true,
62452
62959
  isTruthy: false
@@ -62461,32 +62968,32 @@ const getStaticConfigValueState = (expression, analysis) => {
62461
62968
  };
62462
62969
  if (ts.isIdentifier(unwrappedExpression)) {
62463
62970
  if (analysis.localBindings.has(unwrappedExpression.text)) {
62464
- const localInitializer = analysis.localBindings.get(unwrappedExpression.text);
62465
- return localInitializer ? getStaticConfigValueState(localInitializer, analysis) : null;
62971
+ const localReference = analysis.localBindings.get(unwrappedExpression.text);
62972
+ return localReference?.expression ? getStaticConfigValueState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
62466
62973
  }
62467
62974
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
62468
- return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis) : null;
62975
+ return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis, nextVisitedExpressions) : null;
62469
62976
  }
62470
62977
  if (ts.isConditionalExpression(unwrappedExpression)) {
62471
- const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis);
62472
- if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis);
62473
- const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis);
62474
- const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis);
62978
+ const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis, nextVisitedExpressions);
62979
+ if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
62980
+ const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis, nextVisitedExpressions);
62981
+ const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
62475
62982
  return whenTrueState !== null && whenFalseState !== null && whenTrueState.isNullish === whenFalseState.isNullish && whenTrueState.isTruthy === whenFalseState.isTruthy ? whenTrueState : null;
62476
62983
  }
62477
62984
  if (ts.isBinaryExpression(unwrappedExpression)) {
62478
- const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis);
62985
+ const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis, nextVisitedExpressions);
62479
62986
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
62480
62987
  if (leftState === null) return null;
62481
- return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
62988
+ return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
62482
62989
  }
62483
62990
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
62484
62991
  if (leftState === null) return null;
62485
- return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis);
62992
+ return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions);
62486
62993
  }
62487
62994
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) {
62488
62995
  if (leftState === null) return null;
62489
- return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
62996
+ return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
62490
62997
  }
62491
62998
  }
62492
62999
  return null;
@@ -62495,25 +63002,27 @@ const isStaticallyDisabledConfigExpression = (expression, analysis) => getStatic
62495
63002
  const isStaticallyTruthyConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isTruthy === true;
62496
63003
  const isStaticallyNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === true;
62497
63004
  const isStaticallyNonNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === false;
62498
- const getReactCompilerFlagState = (expression, analysis) => {
62499
- let unwrappedExpression = expression;
62500
- while (ts.isParenthesizedExpression(unwrappedExpression) || ts.isAsExpression(unwrappedExpression) || ts.isTypeAssertionExpression(unwrappedExpression) || ts.isSatisfiesExpression(unwrappedExpression) || ts.isNonNullExpression(unwrappedExpression)) unwrappedExpression = unwrappedExpression.expression;
63005
+ const getReactCompilerFlagState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
63006
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
63007
+ if (visitedExpressions.has(unwrappedExpression)) return null;
63008
+ const nextVisitedExpressions = new Set(visitedExpressions);
63009
+ nextVisitedExpressions.add(unwrappedExpression);
62501
63010
  if (ts.isIdentifier(unwrappedExpression)) {
62502
63011
  const assignedBinding = getAssignedPropertyInitializer(unwrappedExpression, "reactCompiler");
62503
63012
  if (assignedBinding.wasFound && assignedBinding.initializer) return { isEnabled: !isStaticallyDisabledConfigExpression(assignedBinding.initializer, analysis) };
62504
63013
  if (analysis.localBindings.has(unwrappedExpression.text)) {
62505
- const localInitializer = analysis.localBindings.get(unwrappedExpression.text);
62506
- return localInitializer ? getReactCompilerFlagState(localInitializer, analysis) : null;
63014
+ const localReference = analysis.localBindings.get(unwrappedExpression.text);
63015
+ return localReference?.expression ? getReactCompilerFlagState(localReference.expression, localReference.analysis, nextVisitedExpressions) : null;
62507
63016
  }
62508
63017
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
62509
- return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis) : null;
63018
+ return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis, nextVisitedExpressions) : null;
62510
63019
  }
62511
63020
  if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
62512
63021
  for (const property of [...unwrappedExpression.properties].reverse()) {
62513
- if (ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
63022
+ if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
62514
63023
  if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
62515
63024
  if (ts.isSpreadAssignment(property)) {
62516
- const spreadState = getReactCompilerFlagState(property.expression, analysis);
63025
+ const spreadState = getReactCompilerFlagState(property.expression, analysis, nextVisitedExpressions);
62517
63026
  if (spreadState) return spreadState;
62518
63027
  }
62519
63028
  }
@@ -62526,8 +63035,8 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
62526
63035
  visitedExpressions.add(resolvedExpression);
62527
63036
  if (ts.isIdentifier(resolvedExpression)) {
62528
63037
  if (analysis.localBindings.has(resolvedExpression.text)) {
62529
- const localInitializer = analysis.localBindings.get(resolvedExpression.text);
62530
- return localInitializer ? getSelectedObjectProperty(localInitializer, propertyName, analysis, visitedExpressions) : null;
63038
+ const localReference = analysis.localBindings.get(resolvedExpression.text);
63039
+ return localReference?.expression ? getSelectedObjectProperty(localReference.expression, propertyName, localReference.analysis, visitedExpressions) : null;
62531
63040
  }
62532
63041
  const scopedBinding = getScopedConfigBinding(resolvedExpression);
62533
63042
  if (scopedBinding.wasFound) return scopedBinding.initializer ? getSelectedObjectProperty(scopedBinding.initializer, propertyName, analysis, visitedExpressions) : null;
@@ -62536,9 +63045,18 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
62536
63045
  }
62537
63046
  if (!ts.isObjectLiteralExpression(resolvedExpression)) return null;
62538
63047
  for (const property of [...resolvedExpression.properties].reverse()) {
62539
- if (ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === propertyName) return property.initializer;
62540
- if (ts.isMethodDeclaration(property) && getStaticPropertyName$1(property.name) === propertyName) return property;
62541
- if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return property.name;
63048
+ if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === propertyName) return {
63049
+ node: property.initializer,
63050
+ analysis
63051
+ };
63052
+ if (ts.isMethodDeclaration(property) && getStaticPropertyName$2(property.name) === propertyName) return {
63053
+ node: property,
63054
+ analysis
63055
+ };
63056
+ if (ts.isShorthandPropertyAssignment(property) && property.name.text === propertyName) return {
63057
+ node: property.name,
63058
+ analysis
63059
+ };
62542
63060
  if (ts.isSpreadAssignment(property)) {
62543
63061
  const spreadProperty = getSelectedObjectProperty(property.expression, propertyName, analysis, visitedExpressions);
62544
63062
  if (spreadProperty) return spreadProperty;
@@ -62551,8 +63069,8 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
62551
63069
  while (ts.isParenthesizedExpression(resolvedExpression) || ts.isAsExpression(resolvedExpression) || ts.isTypeAssertionExpression(resolvedExpression) || ts.isSatisfiesExpression(resolvedExpression) || ts.isNonNullExpression(resolvedExpression)) resolvedExpression = resolvedExpression.expression;
62552
63070
  if (ts.isIdentifier(resolvedExpression)) {
62553
63071
  if (analysis.localBindings.has(resolvedExpression.text)) {
62554
- const localInitializer = analysis.localBindings.get(resolvedExpression.text);
62555
- return localInitializer ? configExpressionMayDefineProperty(localInitializer, propertyName, analysis) : true;
63072
+ const localReference = analysis.localBindings.get(resolvedExpression.text);
63073
+ return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis) : true;
62556
63074
  }
62557
63075
  const scopedBinding = getScopedConfigBinding(resolvedExpression);
62558
63076
  if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis) : true;
@@ -62568,7 +63086,7 @@ const configExpressionMayDefineProperty = (expression, propertyName, analysis) =
62568
63086
  return resolvedExpression.properties.some((property) => {
62569
63087
  if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
62570
63088
  if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
62571
- const staticPropertyName = getStaticPropertyName$1(property.name);
63089
+ const staticPropertyName = getStaticPropertyName$2(property.name);
62572
63090
  return staticPropertyName === null || staticPropertyName === propertyName;
62573
63091
  }
62574
63092
  return false;
@@ -62587,7 +63105,7 @@ const getExportedConfigNodes = (sourceFile, exportName) => {
62587
63105
  continue;
62588
63106
  }
62589
63107
  if (ts.isExpressionStatement(statement) && isCommonJsConfigExportAssignment(statement.expression, sourceFile) && exportName !== "default" && ts.isObjectLiteralExpression(statement.expression.right)) for (const property of [...statement.expression.right.properties].reverse()) {
62590
- if (ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === exportName) {
63108
+ if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === exportName) {
62591
63109
  exportedNodes.push(property.initializer);
62592
63110
  break;
62593
63111
  }
@@ -62636,15 +63154,15 @@ const getReExportedConfigModules = (sourceFile, exportName) => {
62636
63154
  }
62637
63155
  return bindings;
62638
63156
  };
62639
- const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
63157
+ const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
62640
63158
  if (!isFile(filePath) || importDepth > 4) return false;
62641
63159
  const moduleVisitKey = `${filePath}:${exportName}:${allowCompilerTransform}`;
62642
63160
  if (visitedModules.has(moduleVisitKey)) return false;
62643
63161
  const nextVisitedModules = new Set(visitedModules);
62644
63162
  nextVisitedModules.add(moduleVisitKey);
62645
- return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList);
63163
+ return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
62646
63164
  };
62647
- const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = []) => {
63165
+ const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
62648
63166
  const analysis = {
62649
63167
  filePath,
62650
63168
  sourceFile,
@@ -62654,14 +63172,27 @@ const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCo
62654
63172
  localBindings: /* @__PURE__ */ new Map(),
62655
63173
  activeFunctions: /* @__PURE__ */ new Set()
62656
63174
  };
63175
+ const resolvedArgumentAnalysis = argumentAnalysis ?? analysis;
62657
63176
  const exportedConfigNodes = getExportedConfigNodes(sourceFile, exportName);
62658
- return exportedConfigNodes.some((node) => ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) ? analyzeConfigFunction(node, analysis, allowCompilerTransform, argumentsList) : analyzeConfigNode(node, analysis, allowCompilerTransform)) || getReExportedConfigModules(sourceFile, exportName).some((binding) => {
63177
+ return exportedConfigNodes.some((node) => {
63178
+ if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) return analyzeConfigFunction(node, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
63179
+ if (argumentsList.length > 0 && ts.isIdentifier(node)) {
63180
+ const topLevelBinding = getTopLevelBinding(sourceFile, node.text);
63181
+ if (topLevelBinding && ts.isFunctionLike(topLevelBinding)) return analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, argumentsList, resolvedArgumentAnalysis);
63182
+ const importBinding = getImportBinding(sourceFile, node.text);
63183
+ if (importBinding) {
63184
+ const importedFilePath = resolveImportedConfigFile(filePath, importBinding.moduleSpecifier);
63185
+ return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
63186
+ }
63187
+ }
63188
+ return analyzeConfigNode(node, analysis, allowCompilerTransform);
63189
+ }) || getReExportedConfigModules(sourceFile, exportName).some((binding) => {
62659
63190
  if (exportedConfigNodes.length > 0 && binding.isNamespace) return false;
62660
63191
  const importedFilePath = resolveImportedConfigFile(filePath, binding.moduleSpecifier);
62661
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList));
63192
+ return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, binding.exportName, allowCompilerTransform, importDepth + 1, visitedModules, argumentsList, resolvedArgumentAnalysis));
62662
63193
  });
62663
63194
  };
62664
- const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = []) => {
63195
+ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, argumentsList = [], argumentAnalysis = analysis) => {
62665
63196
  if (!functionNode.body) return false;
62666
63197
  if (analysis.activeFunctions.has(functionNode.pos)) return false;
62667
63198
  const activeFunctions = new Set(analysis.activeFunctions);
@@ -62669,7 +63200,7 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
62669
63200
  const functionAnalysis = {
62670
63201
  ...analysis,
62671
63202
  visitedNodes: /* @__PURE__ */ new Set(),
62672
- localBindings: getFunctionLocalBindings(functionNode, argumentsList),
63203
+ localBindings: getFunctionLocalBindings(functionNode, argumentsList, argumentAnalysis, analysis),
62673
63204
  activeFunctions
62674
63205
  };
62675
63206
  if (!ts.isBlock(functionNode.body)) return analyzeConfigNode(functionNode.body, functionAnalysis, allowCompilerTransform);
@@ -62685,6 +63216,11 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
62685
63216
  visitReturns(functionNode.body);
62686
63217
  return hasCompiler;
62687
63218
  };
63219
+ const analyzeImportedConfig = ({ analysis, moduleSpecifier, exportName, allowCompilerTransform, argumentsList }) => {
63220
+ const importedFilePath = resolveImportedConfigFile(analysis.filePath, moduleSpecifier);
63221
+ if (!importedFilePath) return null;
63222
+ return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList, analysis);
63223
+ };
62688
63224
  const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, isCompilerTransformCollection, excludedPropertyNames) => {
62689
63225
  const assignedReactCompiler = getAssignedPropertyInitializer(identifier, "reactCompiler");
62690
63226
  if (assignedReactCompiler.initializer && !isStaticallyDisabledConfigExpression(assignedReactCompiler.initializer, analysis)) return true;
@@ -62697,42 +63233,74 @@ const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, i
62697
63233
  if (assignedPlugins.wasFound) overriddenPropertyNames.add("plugins");
62698
63234
  if (assignedPresets.wasFound) overriddenPropertyNames.add("presets");
62699
63235
  if (analysis.localBindings.has(identifier.text)) {
62700
- const localInitializer = analysis.localBindings.get(identifier.text);
62701
- return Boolean(localInitializer && analyzeConfigNode(localInitializer, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
63236
+ const localReference = analysis.localBindings.get(identifier.text);
63237
+ return Boolean(localReference?.expression && analyzeConfigNode(localReference.expression, localReference.analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
62702
63238
  }
62703
63239
  const scopedBinding = getScopedConfigBinding(identifier);
62704
63240
  if (scopedBinding.wasFound) return Boolean(scopedBinding.initializer && analyzeConfigNode(scopedBinding.initializer, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
62705
63241
  const importBinding = getImportBinding(analysis.sourceFile, identifier.text);
62706
63242
  if (importBinding) {
62707
63243
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
62708
- if (!importBinding.moduleSpecifier.startsWith(".")) return false;
62709
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62710
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
63244
+ return Boolean(analyzeImportedConfig({
63245
+ analysis,
63246
+ moduleSpecifier: importBinding.moduleSpecifier,
63247
+ exportName: importBinding.exportName,
63248
+ allowCompilerTransform
63249
+ }));
62711
63250
  }
62712
63251
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, identifier.text);
62713
63252
  return Boolean(topLevelBinding && analyzeConfigNode(topLevelBinding, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
62714
63253
  };
62715
63254
  const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransform) => {
62716
63255
  const target = callExpression.expression;
63256
+ const callableRequiredModuleSpecifier = getRequireModuleSpecifier$1(target);
63257
+ if (callableRequiredModuleSpecifier !== null) {
63258
+ if (ts.isCallExpression(target) && ts.isIdentifier(target.expression) && (analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
63259
+ if (allowCompilerTransform && isCompilerTransformModule(callableRequiredModuleSpecifier, "default")) return true;
63260
+ const hasCompilerTransform = analyzeImportedConfig({
63261
+ analysis,
63262
+ moduleSpecifier: callableRequiredModuleSpecifier,
63263
+ exportName: "default",
63264
+ allowCompilerTransform,
63265
+ argumentsList: callExpression.arguments
63266
+ });
63267
+ if (isLocalModuleSpecifier(callableRequiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
63268
+ return null;
63269
+ }
62717
63270
  if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
62718
63271
  const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
62719
63272
  if (propertyName === null) return null;
62720
- const requiredModuleSpecifier = getRequireModuleSpecifier(target.expression);
63273
+ const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
62721
63274
  if (requiredModuleSpecifier !== null) {
62722
- if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62723
- if (!requiredModuleSpecifier.startsWith(".")) return null;
62724
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, requiredModuleSpecifier);
62725
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, propertyName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, callExpression.arguments));
63275
+ 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;
63276
+ if (allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, propertyName)) return true;
63277
+ const hasCompilerTransform = analyzeImportedConfig({
63278
+ analysis,
63279
+ moduleSpecifier: requiredModuleSpecifier,
63280
+ exportName: propertyName,
63281
+ allowCompilerTransform,
63282
+ argumentsList: callExpression.arguments
63283
+ });
63284
+ if (isLocalModuleSpecifier(requiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
63285
+ return null;
62726
63286
  }
62727
63287
  if (!ts.isIdentifier(target.expression)) return null;
62728
- const importBinding = getImportBinding(analysis.sourceFile, target.expression.text);
62729
- if (importBinding?.isNamespace && importBinding.moduleSpecifier.startsWith(".")) {
62730
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62731
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, propertyName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, callExpression.arguments));
63288
+ const importBinding = analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound ? null : getImportBinding(analysis.sourceFile, target.expression.text);
63289
+ if (importBinding?.isNamespace) {
63290
+ if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, propertyName)) return true;
63291
+ const hasCompilerTransform = analyzeImportedConfig({
63292
+ analysis,
63293
+ moduleSpecifier: importBinding.moduleSpecifier,
63294
+ exportName: propertyName,
63295
+ allowCompilerTransform,
63296
+ argumentsList: callExpression.arguments
63297
+ });
63298
+ if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
63299
+ return null;
62732
63300
  }
62733
63301
  const selectedProperty = getSelectedObjectProperty(target.expression, propertyName, analysis);
62734
63302
  if (selectedProperty === null) return null;
62735
- return ts.isFunctionLike(selectedProperty) ? analyzeConfigFunction(selectedProperty, analysis, allowCompilerTransform, callExpression.arguments) : analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
63303
+ return ts.isFunctionLike(selectedProperty.node) ? analyzeConfigFunction(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform, callExpression.arguments, analysis) : analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
62736
63304
  };
62737
63305
  const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTransformCollection = false, excludedPropertyNames) => {
62738
63306
  const excludedPropertiesVisitKey = excludedPropertyNames ? [...excludedPropertyNames].sort().join(",") : "";
@@ -62746,25 +63314,29 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62746
63314
  const reactCompilerFlagState = excludedPropertyNames?.has("reactCompiler") ? null : getReactCompilerFlagState(node, analysis);
62747
63315
  if (reactCompilerFlagState?.isEnabled) return true;
62748
63316
  for (const [propertyIndex, property] of node.properties.entries()) if (ts.isPropertyAssignment(property)) {
62749
- const propertyName = getStaticPropertyName$1(property.name);
63317
+ const propertyName = getStaticPropertyName$2(property.name);
62750
63318
  if (propertyName && excludedPropertyNames?.has(propertyName)) continue;
62751
63319
  if (propertyName === "reactCompiler") continue;
62752
- 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$1(laterProperty.name) === propertyName)) continue;
63320
+ 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;
62753
63321
  const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
62754
- if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer) && property.initializer.text.startsWith(".")) {
62755
- const extendedFilePath = resolveImportedConfigFile(analysis.filePath, property.initializer.text);
62756
- if (extendedFilePath && analyzeConfigModuleExport(extendedFilePath, "default", false, analysis.importDepth + 1, analysis.visitedModules)) return true;
63322
+ if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)) {
63323
+ if (analyzeImportedConfig({
63324
+ analysis,
63325
+ moduleSpecifier: property.initializer.text,
63326
+ exportName: "default",
63327
+ allowCompilerTransform: false
63328
+ })) return true;
62757
63329
  }
62758
63330
  if (analyzeConfigNode(property.initializer, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
62759
63331
  } else if (ts.isShorthandPropertyAssignment(property)) {
62760
63332
  if (excludedPropertyNames?.has(property.name.text)) continue;
62761
63333
  if (property.name.text === "reactCompiler") continue;
62762
- 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$1(laterProperty.name) === property.name.text)) continue;
63334
+ 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;
62763
63335
  const propertyAllowsCompilerTransform = property.name.text === "plugins" || property.name.text === "presets";
62764
63336
  if (analyzeConfigNode(property.name, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
62765
63337
  } else if (ts.isSpreadAssignment(property)) {
62766
63338
  if (reactCompilerFlagState && getReactCompilerFlagState(property.expression, analysis) !== null) continue;
62767
- if (node.properties.slice(propertyIndex + 1).some((laterProperty) => (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && (getStaticPropertyName$1(laterProperty.name) === "plugins" || getStaticPropertyName$1(laterProperty.name) === "presets"))) continue;
63339
+ 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;
62768
63340
  if (analyzeConfigNode(property.expression, analysis, allowCompilerTransform, false, excludedPropertyNames)) return true;
62769
63341
  }
62770
63342
  return false;
@@ -62777,23 +63349,36 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62777
63349
  });
62778
63350
  }
62779
63351
  if (ts.isCallExpression(node)) {
63352
+ const resolvedModuleSpecifier = getNodeRequireResolveModuleSpecifier(node, analysis);
63353
+ if (resolvedModuleSpecifier !== null) return allowCompilerTransform && isCompilerTransformModule(resolvedModuleSpecifier, "default");
62780
63354
  const callTargetResult = analyzeConfigCallTarget(node, analysis, allowCompilerTransform);
62781
63355
  if (callTargetResult !== null) return callTargetResult;
62782
- const directModuleSpecifier = getRequireModuleSpecifier(node);
63356
+ const directModuleSpecifier = getRequireModuleSpecifier$1(node);
62783
63357
  const isRequireShadowed = analysis.localBindings.has("require") || ts.isIdentifier(node.expression) && getScopedConfigBinding(node.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require");
62784
63358
  if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
62785
63359
  if (directModuleSpecifier && !isRequireShadowed) {
62786
63360
  if (allowCompilerTransform && isCompilerTransformModule(directModuleSpecifier, "default")) return true;
62787
- if (directModuleSpecifier.startsWith(".")) {
62788
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, directModuleSpecifier);
62789
- if (importedFilePath && analyzeConfigModuleExport(importedFilePath, "default", allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules)) return true;
62790
- }
63361
+ if (analyzeImportedConfig({
63362
+ analysis,
63363
+ moduleSpecifier: directModuleSpecifier,
63364
+ exportName: "default",
63365
+ allowCompilerTransform
63366
+ })) return true;
62791
63367
  }
62792
63368
  if (ts.isIdentifier(node.expression)) {
62793
- const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62794
- if (importBinding?.moduleSpecifier.startsWith(".")) {
62795
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62796
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, node.arguments));
63369
+ if (!analysis.localBindings.has(node.expression.text) && !getScopedConfigBinding(node.expression).wasFound) {
63370
+ const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
63371
+ if (importBinding) {
63372
+ if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
63373
+ const hasCompilerTransform = analyzeImportedConfig({
63374
+ analysis,
63375
+ moduleSpecifier: importBinding.moduleSpecifier,
63376
+ exportName: importBinding.exportName,
63377
+ allowCompilerTransform,
63378
+ argumentsList: node.arguments
63379
+ });
63380
+ if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
63381
+ }
62797
63382
  }
62798
63383
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, node.expression.text);
62799
63384
  if (topLevelBinding && ts.isFunctionLike(topLevelBinding) && analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, node.arguments)) return true;
@@ -62801,47 +63386,57 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62801
63386
  return analyzeConfigNode(node.expression, analysis, allowCompilerTransform) || node.arguments.some((argument) => analyzeConfigNode(argument, analysis, false));
62802
63387
  }
62803
63388
  if (ts.isPropertyAccessExpression(node)) {
62804
- const requiredModuleSpecifier = getRequireModuleSpecifier(node.expression);
63389
+ const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
62805
63390
  if (requiredModuleSpecifier) {
62806
- if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62807
- if (requiredModuleSpecifier.startsWith(".")) {
62808
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, requiredModuleSpecifier);
62809
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, node.name.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
62810
- }
63391
+ 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;
63392
+ if (analyzeImportedConfig({
63393
+ analysis,
63394
+ moduleSpecifier: requiredModuleSpecifier,
63395
+ exportName: node.name.text,
63396
+ allowCompilerTransform
63397
+ })) return true;
62811
63398
  return allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, node.name.text);
62812
63399
  }
62813
63400
  if (ts.isIdentifier(node.expression)) {
62814
- if (analysis.localBindings.has(node.expression.text)) {
62815
- const localInitializer = analysis.localBindings.get(node.expression.text);
62816
- return Boolean(localInitializer && analyzeConfigNode(localInitializer, analysis, allowCompilerTransform));
63401
+ if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
63402
+ const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
63403
+ return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
62817
63404
  }
62818
63405
  const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62819
63406
  if (importBinding?.isNamespace) {
62820
63407
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.name.text)) return true;
62821
- if (importBinding.moduleSpecifier.startsWith(".")) {
62822
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62823
- if (importedFilePath && analyzeConfigModuleExport(importedFilePath, node.name.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules)) return true;
62824
- }
63408
+ if (analyzeImportedConfig({
63409
+ analysis,
63410
+ moduleSpecifier: importBinding.moduleSpecifier,
63411
+ exportName: node.name.text,
63412
+ allowCompilerTransform
63413
+ })) return true;
62825
63414
  return false;
62826
63415
  }
62827
63416
  const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
62828
- if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
63417
+ if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
62829
63418
  return false;
62830
63419
  }
62831
63420
  return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
62832
63421
  }
62833
63422
  if (ts.isElementAccessExpression(node) && node.argumentExpression && ts.isStringLiteralLike(node.argumentExpression)) {
62834
63423
  if (ts.isIdentifier(node.expression)) {
63424
+ if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
63425
+ const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
63426
+ return Boolean(selectedProperty && analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform));
63427
+ }
62835
63428
  const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62836
63429
  if (importBinding?.isNamespace) {
62837
63430
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.argumentExpression.text)) return true;
62838
- if (importBinding.moduleSpecifier.startsWith(".")) {
62839
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62840
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, node.argumentExpression.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
62841
- }
63431
+ return Boolean(analyzeImportedConfig({
63432
+ analysis,
63433
+ moduleSpecifier: importBinding.moduleSpecifier,
63434
+ exportName: node.argumentExpression.text,
63435
+ allowCompilerTransform
63436
+ }));
62842
63437
  }
62843
63438
  const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
62844
- if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
63439
+ if (selectedProperty) return analyzeConfigNode(selectedProperty.node, selectedProperty.analysis, allowCompilerTransform);
62845
63440
  return false;
62846
63441
  }
62847
63442
  return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
@@ -62876,14 +63471,19 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62876
63471
  };
62877
63472
  const hasCompilerInConfigFile = (filePath) => analyzeConfigModuleExport(filePath, "default", false, 0, /* @__PURE__ */ new Set());
62878
63473
  const hasCompilerInConfigFiles = (directory, filenames) => filenames.some((filename) => hasCompilerInConfigFile(Path.join(directory, filename)));
62879
- const hasCompilerInPackageJsonConfig = (packageJson) => isPlainObject(packageJson.babel) && analyzeConfigSourceFileExport(ts.parseJsonText("package.json", JSON.stringify(packageJson.babel)), "package.json#babel", "default", false, 0, /* @__PURE__ */ new Set());
62880
- const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
63474
+ const hasCompilerInPackageJsonConfig = (directory, packageJson) => {
63475
+ if (!isPlainObject(packageJson.babel)) return false;
63476
+ const packageJsonPath = Path.join(directory, "package.json");
63477
+ return analyzeConfigSourceFileExport(ts.parseJsonText(packageJsonPath, JSON.stringify(packageJson.babel)), packageJsonPath, "default", false, 0, /* @__PURE__ */ new Set());
63478
+ };
63479
+ const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(directory, packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
62881
63480
  const hasCompilerConfigurationInAncestors = (directory) => {
62882
63481
  if (isProjectBoundary(directory)) return false;
62883
63482
  let ancestorDirectory = Path.dirname(directory);
62884
63483
  while (ancestorDirectory !== Path.dirname(ancestorDirectory)) {
62885
63484
  const ancestorPackagePath = Path.join(ancestorDirectory, "package.json");
62886
- if (hasCompilerInPackageJsonConfig(isFile(ancestorPackagePath) ? readPackageJson(ancestorPackagePath) : {}) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
63485
+ const ancestorPackageJson = isFile(ancestorPackagePath) ? readPackageJson(ancestorPackagePath) : {};
63486
+ if (hasCompilerInPackageJsonConfig(ancestorDirectory, ancestorPackageJson) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
62887
63487
  if (isProjectBoundary(ancestorDirectory)) return false;
62888
63488
  ancestorDirectory = Path.dirname(ancestorDirectory);
62889
63489
  }
@@ -65073,7 +65673,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
65073
65673
  const getDiagnosticRuleIdentity = (diagnostic) => ({
65074
65674
  ruleKey: `${diagnostic.plugin}/${diagnostic.rule}`,
65075
65675
  category: diagnostic.category,
65076
- tags: diagnostic.plugin === "react-doctor" ? reactDoctorPlugin.rules[diagnostic.rule]?.tags ?? [] : []
65676
+ tags: diagnostic.plugin === "react-doctor" ? REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule]?.tags ?? [] : []
65077
65677
  });
65078
65678
  const compileIgnoredFilePatterns = (userConfig) => {
65079
65679
  const files = userConfig?.ignore?.files;
@@ -65213,6 +65813,7 @@ const classifyPackageRole = (filename) => {
65213
65813
  * Resolves the absolute path to read for a diagnostic's `filePath`,
65214
65814
  * accounting for the various shapes oxlint emits:
65215
65815
  *
65816
+ * - `file://` URL — decode to an absolute filesystem path.
65216
65817
  * - Absolute POSIX (`/abs/path/file.tsx`) — pass through.
65217
65818
  * - Absolute Windows (`C:/...` or `C:\...`) — pass through.
65218
65819
  * - `./relative` or bare relative — join against `rootDirectory`.
@@ -65222,6 +65823,7 @@ const classifyPackageRole = (filename) => {
65222
65823
  * use one canonical resolution path.
65223
65824
  */
65224
65825
  const resolveCandidateReadPath = (rootDirectory, filePath) => {
65826
+ if (filePath.startsWith("file://")) return fileURLToPath(filePath);
65225
65827
  const normalizedFile = filePath.replace(/\\/g, "/");
65226
65828
  if (normalizedFile.startsWith("/") || /^[a-zA-Z]:\//.test(normalizedFile) || /^[a-zA-Z]:\\/.test(filePath)) return filePath;
65227
65829
  return `${rootDirectory.replace(/\\/g, "/").replace(/\/$/, "")}/${normalizedFile.replace(/^\.\//, "")}`;
@@ -65423,7 +66025,7 @@ const buildDiagnosticPipeline = (input) => {
65423
66025
  };
65424
66026
  const shouldAutoSuppress = (diagnostic) => {
65425
66027
  if (diagnostic.plugin !== "react-doctor") return false;
65426
- const rule = reactDoctorPlugin.rules[diagnostic.rule];
66028
+ const rule = REACT_DOCTOR_RULE_REGISTRY[diagnostic.rule];
65427
66029
  if (!rule?.tags?.includes("test-noise")) return false;
65428
66030
  if (rule.tags.includes("migration-hint")) return false;
65429
66031
  return getFileContext(diagnostic.filePath) !== "production";
@@ -65855,6 +66457,7 @@ var OxlintConcurrency = class extends Reference("react-doctor/OxlintConcurrency"
65855
66457
  if (Number.isInteger(parsed) && parsed > 0) return resolveScanConcurrency(parsed);
65856
66458
  return resolveAutoScanConcurrency();
65857
66459
  } }) {};
66460
+ var OxlintSpawnSlots = class extends Reference("react-doctor/OxlintSpawnSlots", { defaultValue: () => null }) {};
65858
66461
  /**
65859
66462
  * Three-state control for overlapping the dead-code pass with the lint pass —
65860
66463
  * forking dead-code as a child fiber that runs DURING lint instead of strictly
@@ -66138,7 +66741,7 @@ const warn = (message) => {
66138
66741
  runSync(warn$1(message));
66139
66742
  };
66140
66743
  const CONFIG_BASENAME = "doctor.config";
66141
- const CONFIG_EXTENSIONS = [
66744
+ const CONFIG_EXTENSIONS$1 = [
66142
66745
  "ts",
66143
66746
  "mts",
66144
66747
  "cts",
@@ -66242,7 +66845,7 @@ const loadLegacyConfig = (directory) => {
66242
66845
  };
66243
66846
  const loadConfigFromDirectory = async (directory) => {
66244
66847
  let sawBrokenConfigFile = false;
66245
- for (const extension of CONFIG_EXTENSIONS) {
66848
+ for (const extension of CONFIG_EXTENSIONS$1) {
66246
66849
  const filePath = Path.join(directory, `${CONFIG_BASENAME}.${extension}`);
66247
66850
  if (!isFile(filePath)) continue;
66248
66851
  const isDataFile = DATA_CONFIG_EXTENSIONS.has(extension);
@@ -66977,6 +67580,316 @@ const buildReactNativeDiagnostic = (input) => ({
66977
67580
  column: input.column ?? 0,
66978
67581
  category: input.category ?? "Correctness"
66979
67582
  });
67583
+ const ANDROID_APP_BUILD_FILE_NAMES = ["build.gradle", "build.gradle.kts"];
67584
+ const BUILD_TYPES_BLOCK_PATTERN = /\bbuildTypes\s*\{/g;
67585
+ const RELEASE_STRING_MARKER = "__RD_RELEASE__";
67586
+ const RELEASE_BLOCK_PATTERNS = [/\brelease\s*\{/g, /\b(?:getByName|named)\s*\(\s*(?:["']release["']|__RD_RELEASE__)\s*\)\s*\{/g];
67587
+ const MINIFY_ASSIGNMENT_PATTERN = /\b(?:isMinifyEnabled|minifyEnabled)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
67588
+ const SHRINK_RESOURCES_ASSIGNMENT_PATTERN = /\b(?:isShrinkResources|shrinkResources)\b\s*(?:\(\s*|=\s*|\s+)([^;}\r\n]+)/g;
67589
+ const stripGradleComments = (contents) => {
67590
+ let result = "";
67591
+ let index = 0;
67592
+ let quote = null;
67593
+ while (index < contents.length) {
67594
+ const character = contents[index];
67595
+ const nextCharacter = contents[index + 1];
67596
+ if (quote !== null) {
67597
+ result += character;
67598
+ if (character === "\\") {
67599
+ result += nextCharacter ?? "";
67600
+ index += 2;
67601
+ continue;
67602
+ }
67603
+ if (character === quote) quote = null;
67604
+ index += 1;
67605
+ continue;
67606
+ }
67607
+ if (character === "\"" || character === "'") {
67608
+ quote = character;
67609
+ result += character;
67610
+ index += 1;
67611
+ continue;
67612
+ }
67613
+ if (character === "/" && nextCharacter === "/") {
67614
+ while (index < contents.length && contents[index] !== "\n") {
67615
+ result += " ";
67616
+ index += 1;
67617
+ }
67618
+ continue;
67619
+ }
67620
+ if (character === "/" && nextCharacter === "*") {
67621
+ result += " ";
67622
+ index += 2;
67623
+ while (index < contents.length && !(contents[index] === "*" && contents[index + 1] === "/")) {
67624
+ result += contents[index] === "\n" ? "\n" : " ";
67625
+ index += 1;
67626
+ }
67627
+ if (index < contents.length) {
67628
+ result += " ";
67629
+ index += 2;
67630
+ }
67631
+ continue;
67632
+ }
67633
+ result += character;
67634
+ index += 1;
67635
+ }
67636
+ return result;
67637
+ };
67638
+ const maskGradleStrings = (contents) => {
67639
+ let result = "";
67640
+ let index = 0;
67641
+ let quote = null;
67642
+ while (index < contents.length) {
67643
+ const character = contents[index];
67644
+ if (quote === null) {
67645
+ if (character === "\"" || character === "'") {
67646
+ quote = character;
67647
+ result += " ";
67648
+ } else result += character;
67649
+ index += 1;
67650
+ continue;
67651
+ }
67652
+ if (character === "\\") {
67653
+ result += " ";
67654
+ index += 2;
67655
+ continue;
67656
+ }
67657
+ if (character === quote) quote = null;
67658
+ result += character === "\n" ? "\n" : " ";
67659
+ index += 1;
67660
+ }
67661
+ return result;
67662
+ };
67663
+ const findBlockContents = (contents, pattern) => {
67664
+ const blocks = [];
67665
+ pattern.lastIndex = 0;
67666
+ let match = pattern.exec(contents);
67667
+ while (match !== null) {
67668
+ const openingBraceIndex = pattern.lastIndex - 1;
67669
+ let depth = 1;
67670
+ let index = openingBraceIndex + 1;
67671
+ let quote = null;
67672
+ while (index < contents.length && depth > 0) {
67673
+ const character = contents[index];
67674
+ if (quote !== null) {
67675
+ if (character === "\\") {
67676
+ index += 2;
67677
+ continue;
67678
+ }
67679
+ if (character === quote) quote = null;
67680
+ } else if (character === "\"" || character === "'") quote = character;
67681
+ else if (character === "{") depth += 1;
67682
+ else if (character === "}") depth -= 1;
67683
+ index += 1;
67684
+ }
67685
+ if (depth === 0) blocks.push(contents.slice(openingBraceIndex + 1, index - 1));
67686
+ match = pattern.exec(contents);
67687
+ }
67688
+ return blocks;
67689
+ };
67690
+ const getFinalStaticBoolean = (contents, pattern) => {
67691
+ pattern.lastIndex = 0;
67692
+ let finalValue = null;
67693
+ let match = pattern.exec(contents);
67694
+ while (match !== null) {
67695
+ const staticValue = match[1]?.trim().replace(/\)$/, "").trim();
67696
+ if (staticValue === "true") finalValue = true;
67697
+ else if (staticValue === "false") finalValue = false;
67698
+ else finalValue = null;
67699
+ match = pattern.exec(contents);
67700
+ }
67701
+ return finalValue;
67702
+ };
67703
+ const getReleaseBlocks = (contents) => findBlockContents(contents, BUILD_TYPES_BLOCK_PATTERN).flatMap((buildTypesBlock) => RELEASE_BLOCK_PATTERNS.flatMap((pattern) => findBlockContents(buildTypesBlock, pattern)));
67704
+ const readAndroidReleaseShrinking = (rootDirectory) => {
67705
+ for (const buildFileName of ANDROID_APP_BUILD_FILE_NAMES) {
67706
+ const filePath = Path.posix.join("android", "app", buildFileName);
67707
+ const absoluteFilePath = Path.join(rootDirectory, filePath);
67708
+ if (!isFile(absoluteFilePath)) continue;
67709
+ let contents;
67710
+ try {
67711
+ contents = stripGradleComments(NFS.readFileSync(absoluteFilePath, "utf-8"));
67712
+ } catch {
67713
+ return null;
67714
+ }
67715
+ const releaseBlocks = getReleaseBlocks(maskGradleStrings(contents.replace(/(["'])release\1/g, RELEASE_STRING_MARKER)));
67716
+ const [releaseBlock] = releaseBlocks;
67717
+ if (releaseBlock === void 0 || releaseBlocks.length !== 1) return null;
67718
+ const hasDisabledMinification = getFinalStaticBoolean(releaseBlock, MINIFY_ASSIGNMENT_PATTERN) === false;
67719
+ const hasDisabledResourceShrinking = getFinalStaticBoolean(releaseBlock, SHRINK_RESOURCES_ASSIGNMENT_PATTERN) === false;
67720
+ if (!hasDisabledMinification && !hasDisabledResourceShrinking) return null;
67721
+ return {
67722
+ filePath,
67723
+ hasDisabledMinification,
67724
+ hasDisabledResourceShrinking
67725
+ };
67726
+ }
67727
+ return null;
67728
+ };
67729
+ const checkReactNativeAndroidReleaseShrinking = (rootDirectory) => {
67730
+ const releaseShrinking = readAndroidReleaseShrinking(rootDirectory);
67731
+ if (releaseShrinking === null) return [];
67732
+ const disabledFeatures = [releaseShrinking.hasDisabledMinification ? "code minification" : null, releaseShrinking.hasDisabledResourceShrinking ? "resource shrinking" : null].filter((feature) => feature !== null);
67733
+ return [buildReactNativeDiagnostic({
67734
+ filePath: releaseShrinking.filePath,
67735
+ rule: "rn-android-release-shrinking-disabled",
67736
+ category: "Performance",
67737
+ message: `The Android release build explicitly disables ${disabledFeatures.join(" and ")}, leaving unreachable code or resources in the shipped app.`,
67738
+ help: "Enable release code minification and resource shrinking, then test the optimized build and add keep rules for libraries that require them."
67739
+ })];
67740
+ };
67741
+ const getTypescriptScriptKind = (fileName) => {
67742
+ if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
67743
+ if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
67744
+ if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
67745
+ return ts.ScriptKind.JS;
67746
+ };
67747
+ const BABEL_CONFIG_FILE_NAMES$1 = [
67748
+ "babel.config.js",
67749
+ "babel.config.cjs",
67750
+ "babel.config.mjs",
67751
+ "babel.config.ts",
67752
+ "babel.config.cts",
67753
+ "babel.config.json",
67754
+ ".babelrc",
67755
+ ".babelrc.js",
67756
+ ".babelrc.cjs",
67757
+ ".babelrc.mjs",
67758
+ ".babelrc.cts",
67759
+ ".babelrc.json"
67760
+ ];
67761
+ const readUnknownPluginNames = (value) => {
67762
+ if (!Array.isArray(value)) return null;
67763
+ const pluginNames = [];
67764
+ for (const entry of value) {
67765
+ if (typeof entry === "string") {
67766
+ pluginNames.push(entry);
67767
+ continue;
67768
+ }
67769
+ if (Array.isArray(entry) && typeof entry[0] === "string") {
67770
+ pluginNames.push(entry[0]);
67771
+ continue;
67772
+ }
67773
+ return null;
67774
+ }
67775
+ return pluginNames;
67776
+ };
67777
+ const getStaticPropertyName$1 = (propertyName) => {
67778
+ if (ts.isIdentifier(propertyName) || ts.isStringLiteralLike(propertyName)) return propertyName.text;
67779
+ return null;
67780
+ };
67781
+ const getStaticPluginName = (expression) => {
67782
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
67783
+ if (ts.isStringLiteralLike(unwrappedExpression)) return unwrappedExpression.text;
67784
+ if (!ts.isArrayLiteralExpression(unwrappedExpression)) return null;
67785
+ const pluginExpression = unwrappedExpression.elements[0];
67786
+ return pluginExpression && ts.isStringLiteralLike(pluginExpression) ? pluginExpression.text : null;
67787
+ };
67788
+ const getPluginNamesFromObject = (objectExpression) => {
67789
+ if (objectExpression.properties.some((property) => ts.isSpreadAssignment(property))) return null;
67790
+ const pluginProperties = objectExpression.properties.filter((property) => ts.isPropertyAssignment(property) && getStaticPropertyName$1(property.name) === "plugins");
67791
+ if (pluginProperties.length !== 1) return pluginProperties.length === 0 ? [] : null;
67792
+ const pluginListExpression = unwrapTypescriptExpression(pluginProperties[0].initializer);
67793
+ if (!ts.isArrayLiteralExpression(pluginListExpression)) return null;
67794
+ const pluginNames = [];
67795
+ for (const element of pluginListExpression.elements) {
67796
+ if (ts.isSpreadElement(element)) return null;
67797
+ const pluginName = getStaticPluginName(element);
67798
+ if (pluginName === null) return null;
67799
+ pluginNames.push(pluginName);
67800
+ }
67801
+ return pluginNames;
67802
+ };
67803
+ 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";
67804
+ const getDirectExportedObject = (sourceFile) => {
67805
+ const exportedExpressions = [];
67806
+ for (const statement of sourceFile.statements) {
67807
+ if (ts.isExportAssignment(statement)) {
67808
+ exportedExpressions.push(statement.expression);
67809
+ continue;
67810
+ }
67811
+ if (ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken && isModuleExports(statement.expression.left)) exportedExpressions.push(statement.expression.right);
67812
+ }
67813
+ if (exportedExpressions.length !== 1) return null;
67814
+ const exportedExpression = unwrapTypescriptExpression(exportedExpressions[0]);
67815
+ return ts.isObjectLiteralExpression(exportedExpression) ? exportedExpression : null;
67816
+ };
67817
+ const parseConfigPluginNames = (filePath, contents) => {
67818
+ try {
67819
+ const parsedJson = JSON.parse(contents);
67820
+ return isPlainObject(parsedJson) ? readUnknownPluginNames(parsedJson.plugins) : null;
67821
+ } catch {
67822
+ if (ts.transpileModule(contents, {
67823
+ fileName: filePath,
67824
+ reportDiagnostics: true,
67825
+ compilerOptions: { allowJs: true }
67826
+ }).diagnostics?.some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error)) return null;
67827
+ const exportedObject = getDirectExportedObject(ts.createSourceFile(filePath, contents, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filePath)));
67828
+ return exportedObject === null ? null : getPluginNamesFromObject(exportedObject);
67829
+ }
67830
+ };
67831
+ const readStaticBabelPluginNames = (rootDirectory) => {
67832
+ for (const fileName of BABEL_CONFIG_FILE_NAMES$1) {
67833
+ const absoluteFilePath = Path.join(rootDirectory, fileName);
67834
+ if (!isFile(absoluteFilePath)) continue;
67835
+ try {
67836
+ return {
67837
+ filePath: fileName,
67838
+ pluginNames: parseConfigPluginNames(fileName, NFS.readFileSync(absoluteFilePath, "utf-8"))
67839
+ };
67840
+ } catch {
67841
+ return {
67842
+ filePath: fileName,
67843
+ pluginNames: null
67844
+ };
67845
+ }
67846
+ }
67847
+ const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
67848
+ if (!isPlainObject(packageJson.babel)) return null;
67849
+ return {
67850
+ filePath: "package.json",
67851
+ pluginNames: readUnknownPluginNames(packageJson.babel.plugins)
67852
+ };
67853
+ };
67854
+ const REACT_COMPILER_PLUGIN_NAMES = new Set(["babel-plugin-react-compiler", "react-compiler"]);
67855
+ const REANIMATED_PLUGIN_NAME = "react-native-reanimated/plugin";
67856
+ const WORKLETS_PLUGIN_NAME = "react-native-worklets/plugin";
67857
+ const checkReactCompilerPluginOrder = (filePath, pluginNames) => {
67858
+ if (pluginNames.findIndex((pluginName) => REACT_COMPILER_PLUGIN_NAMES.has(pluginName)) <= 0) return [];
67859
+ return [buildReactNativeDiagnostic({
67860
+ filePath,
67861
+ rule: "rn-react-compiler-plugin-first",
67862
+ category: "Performance",
67863
+ message: "The React Compiler Babel plugin is not first, so an earlier transform can change component or hook code before the compiler analyzes it.",
67864
+ help: "Move `babel-plugin-react-compiler` to the first entry in the Babel `plugins` array."
67865
+ })];
67866
+ };
67867
+ const checkReanimatedPluginOrder = (project, filePath, pluginNames) => {
67868
+ const reanimatedMajorVersion = project.reanimatedVersion === null || project.reanimatedVersion === void 0 ? null : getLowestDependencyMajor(project.reanimatedVersion);
67869
+ if (reanimatedMajorVersion === null || reanimatedMajorVersion < 4) return [];
67870
+ const diagnostics = [];
67871
+ if (pluginNames.includes(REANIMATED_PLUGIN_NAME)) diagnostics.push(buildReactNativeDiagnostic({
67872
+ filePath,
67873
+ rule: "rn-reanimated-worklets-plugin-last",
67874
+ category: "Performance",
67875
+ message: "This Reanimated 4 project still uses `react-native-reanimated/plugin`, which was renamed to the Worklets Babel plugin.",
67876
+ help: "Replace it with `react-native-worklets/plugin` and keep that plugin last in the Babel `plugins` array."
67877
+ }));
67878
+ const workletsPluginIndex = pluginNames.lastIndexOf(WORKLETS_PLUGIN_NAME);
67879
+ if (workletsPluginIndex !== -1 && workletsPluginIndex !== pluginNames.length - 1) diagnostics.push(buildReactNativeDiagnostic({
67880
+ filePath,
67881
+ rule: "rn-reanimated-worklets-plugin-last",
67882
+ category: "Performance",
67883
+ message: "`react-native-worklets/plugin` is not last in the Babel `plugins` array, so later transforms can prevent worklets from being compiled correctly.",
67884
+ help: "Move `react-native-worklets/plugin` to the final entry in the Babel `plugins` array."
67885
+ }));
67886
+ return diagnostics;
67887
+ };
67888
+ const checkReactNativeBabelPluginOrder = (rootDirectory, project) => {
67889
+ const babelPlugins = readStaticBabelPluginNames(rootDirectory);
67890
+ if (babelPlugins === null || babelPlugins.pluginNames === null) return [];
67891
+ return [...checkReactCompilerPluginOrder(babelPlugins.filePath, babelPlugins.pluginNames), ...checkReanimatedPluginOrder(project, babelPlugins.filePath, babelPlugins.pluginNames)];
67892
+ };
66980
67893
  const BUILDER_BOB_PACKAGE = "react-native-builder-bob";
66981
67894
  const isBuilderBobLibrary = (packageJson) => {
66982
67895
  const bobConfig = packageJson[BUILDER_BOB_PACKAGE];
@@ -67053,7 +67966,12 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
67053
67966
  const isReactNativeProject = (project) => project.framework === "react-native" || project.framework === "expo" || project.hasReactNativeWorkspace || project.expoVersion !== null;
67054
67967
  const checkReactNativeProject = (rootDirectory, project) => {
67055
67968
  if (!isReactNativeProject(project)) return [];
67056
- return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
67969
+ return [
67970
+ ...checkReactNativeMetroBabelPreset(rootDirectory),
67971
+ ...checkReactNativeBabelPluginOrder(rootDirectory, project),
67972
+ ...checkReactNativeAndroidReleaseShrinking(rootDirectory),
67973
+ ...checkReactNativeLibraryDependencies(rootDirectory)
67974
+ ];
67057
67975
  };
67058
67976
  const RULE_KEY = "no-vulnerable-react-server-components";
67059
67977
  const REACT_RSC_ADVISORIES_BY_MINOR = {
@@ -67204,17 +68122,6 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
67204
68122
  }
67205
68123
  return diagnostics;
67206
68124
  };
67207
- const getTypescriptScriptKind = (fileName) => {
67208
- if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
67209
- if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
67210
- if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
67211
- return ts.ScriptKind.JS;
67212
- };
67213
- const unwrapTypescriptExpression = (expression) => {
67214
- let currentExpression = expression;
67215
- while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
67216
- return currentExpression;
67217
- };
67218
68125
  const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
67219
68126
  isAnimationFunction: false,
67220
68127
  isMotionComponent: false,
@@ -67770,7 +68677,11 @@ const buildCapabilities = (project) => {
67770
68677
  capabilities.add(project.framework);
67771
68678
  if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
67772
68679
  if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
67773
- if (project.expoVersion !== null) capabilities.add("expo");
68680
+ if (project.expoVersion !== null) {
68681
+ capabilities.add("expo");
68682
+ const expoSdkMajorVersion = getLowestDependencyMajor(project.expoVersion);
68683
+ if (expoSdkMajorVersion !== null && expoSdkMajorVersion >= 54) capabilities.add("expo:54");
68684
+ }
67774
68685
  if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
67775
68686
  if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
67776
68687
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
@@ -67834,6 +68745,11 @@ const buildCapabilities = (project) => {
67834
68745
  if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addVersionCapabilityLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
67835
68746
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
67836
68747
  if (project.hasReactCompiler) capabilities.add("react-compiler");
68748
+ if (project.reanimatedVersion !== void 0 && project.reanimatedVersion !== null) {
68749
+ capabilities.add("reanimated");
68750
+ const reanimatedMajorVersion = getLowestDependencyMajor(project.reanimatedVersion);
68751
+ if (reanimatedMajorVersion !== null && reanimatedMajorVersion >= 4) capabilities.add("reanimated:4");
68752
+ }
67837
68753
  if (Boolean(project.hasTanStackQuery) || Boolean(project.tanstackQueryVersion)) capabilities.add("tanstack-query");
67838
68754
  if (project.styledComponentsVersion) {
67839
68755
  capabilities.add("styled-components");
@@ -67864,8 +68780,8 @@ const getCapabilities = (project) => {
67864
68780
  const cached = capabilitiesByProject.get(project);
67865
68781
  if (cached !== void 0) return cached;
67866
68782
  const capabilities = new Set(buildCapabilities(project));
67867
- const packageJson = readPackageJson(Path.join(project.rootDirectory, "package.json"));
67868
- const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(project.rootDirectory, packageJson);
68783
+ const capabilityRootDirectory = isFile(Path.join(project.rootDirectory, "package.json")) ? project.rootDirectory : findNearestAncestorPackageJson(project.rootDirectory) ?? project.rootDirectory;
68784
+ const targetBlankOpenerProtection = detectTargetBlankOpenerProtection(capabilityRootDirectory, readPackageJson(Path.join(capabilityRootDirectory, "package.json")));
67869
68785
  if (targetBlankOpenerProtection !== void 0) capabilities.add("target-blank-needs-explicit-protection");
67870
68786
  if (targetBlankOpenerProtection === "noreferrer") capabilities.add("target-blank-needs-noreferrer");
67871
68787
  capabilitiesByProject.set(project, capabilities);
@@ -67895,7 +68811,7 @@ const createSecurityScanSession = (rootDirectory, options) => {
67895
68811
  const capabilities = options.project ? getCapabilities(options.project) : /* @__PURE__ */ new Set();
67896
68812
  const ignoredTags = options.ignoredTags ?? /* @__PURE__ */ new Set();
67897
68813
  const includedTags = options.includedTags ?? /* @__PURE__ */ new Set();
67898
- const enabledScanRules = REACT_DOCTOR_RULES.flatMap((entry) => {
68814
+ const enabledScanRules = REACT_DOCTOR_SCAN_RULES.flatMap((entry) => {
67899
68815
  const rule = entry.rule;
67900
68816
  const scan = rule.scan;
67901
68817
  if (typeof scan !== "function") return [];
@@ -68340,47 +69256,55 @@ const resolveDeadCodeConcurrency = (facts = readSystemFacts()) => {
68340
69256
  const memoryBoundedWorkers = Math.floor(availableMemoryBytes / DEAD_CODE_WORKER_MEM_BUDGET_BYTES);
68341
69257
  return Math.max(1, Math.min(facts.availableCores, memoryBoundedWorkers));
68342
69258
  };
68343
- let availableSlots = -1;
68344
- const waiters = [];
68345
- const releaseSlot = () => {
68346
- const nextWaiter = waiters.shift();
68347
- if (nextWaiter !== void 0) nextWaiter();
68348
- else availableSlots += 1;
69259
+ const createWorkerSlots = (input) => {
69260
+ let availableSlotCount = input.slotCount;
69261
+ const waiters = [];
69262
+ const releaseSlot = () => {
69263
+ const nextWaiter = waiters.shift();
69264
+ if (nextWaiter === void 0) {
69265
+ availableSlotCount += 1;
69266
+ return;
69267
+ }
69268
+ nextWaiter.abortSignal?.removeEventListener("abort", nextWaiter.onAbort);
69269
+ nextWaiter.resolve();
69270
+ };
69271
+ const acquireSlot = async (abortSignal) => {
69272
+ if (abortSignal?.aborted) throw input.createAbortError();
69273
+ if (availableSlotCount > 0) {
69274
+ availableSlotCount -= 1;
69275
+ return;
69276
+ }
69277
+ await new Promise((resolve, reject) => {
69278
+ const onAbort = () => {
69279
+ const waiterIndex = waiters.indexOf(waiter);
69280
+ if (waiterIndex !== -1) waiters.splice(waiterIndex, 1);
69281
+ reject(input.createAbortError());
69282
+ };
69283
+ const waiter = {
69284
+ resolve,
69285
+ abortSignal,
69286
+ onAbort
69287
+ };
69288
+ waiters.push(waiter);
69289
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
69290
+ });
69291
+ };
69292
+ return { run: async (task, abortSignal) => {
69293
+ await acquireSlot(abortSignal);
69294
+ try {
69295
+ return await task();
69296
+ } finally {
69297
+ releaseSlot();
69298
+ }
69299
+ } };
68349
69300
  };
68350
- /**
68351
- * Runs `task` once a dead-code worker slot is free, releasing the slot when the
68352
- * task settles (success or failure). With a high cap (roomy machine) every
68353
- * caller proceeds immediately; with a low cap (constrained runner) callers
68354
- * queue and run as slots free.
68355
- *
68356
- * `abortSignal` short-circuits the WAIT: if it's already aborted, or fires while
68357
- * this caller is queued, the call rejects without acquiring a slot or running
68358
- * `task` — so a cancelled scan (e.g. lint failed) doesn't sit in the queue and
68359
- * then spawn a child only to tear it down. A queued caller that aborts removes
68360
- * its own waiter so a later release never hands a slot to a dead request.
68361
- */
69301
+ let deadCodeWorkerSlots = null;
68362
69302
  const withDeadCodeWorkerSlot = async (task, abortSignal) => {
68363
- if (abortSignal?.aborted) throw new Error("Dead-code worker aborted.");
68364
- if (availableSlots < 0) availableSlots = resolveDeadCodeConcurrency();
68365
- if (availableSlots > 0) availableSlots -= 1;
68366
- else await new Promise((resolve, reject) => {
68367
- const waiter = () => {
68368
- abortSignal?.removeEventListener("abort", onAbort);
68369
- resolve();
68370
- };
68371
- const onAbort = () => {
68372
- const queuedIndex = waiters.indexOf(waiter);
68373
- if (queuedIndex !== -1) waiters.splice(queuedIndex, 1);
68374
- reject(/* @__PURE__ */ new Error("Dead-code worker aborted."));
68375
- };
68376
- waiters.push(waiter);
68377
- abortSignal?.addEventListener("abort", onAbort, { once: true });
69303
+ deadCodeWorkerSlots ??= createWorkerSlots({
69304
+ slotCount: resolveDeadCodeConcurrency(),
69305
+ createAbortError: () => /* @__PURE__ */ new Error("Dead-code worker aborted.")
68378
69306
  });
68379
- try {
68380
- return await task();
68381
- } finally {
68382
- releaseSlot();
68383
- }
69307
+ return deadCodeWorkerSlots.run(task, abortSignal);
68384
69308
  };
68385
69309
  const projectCacheSubdir = (projectDirectory) => crypto.createHash("sha256").update(projectDirectory).digest("hex").slice(0, 16);
68386
69310
  const resolveReactDoctorCacheDir = (projectDirectory) => {
@@ -69173,7 +70097,10 @@ var Git = class Git extends Service()("react-doctor/Git") {
69173
70097
  if (argvLengthChars > spawnArgsLengthCap) return yield* foldSpawnFailure(`spawn ENAMETOOLONG (${argvLengthChars} argv chars exceed ${spawnArgsLengthCap})`);
69174
70098
  const handle = yield* spawner.spawn(make$1(input.command, [...input.args], {
69175
70099
  cwd: input.directory,
69176
- env: input.env,
70100
+ env: input.command === "git" ? {
70101
+ ...input.env,
70102
+ GIT_DIR: void 0
70103
+ } : input.env,
69177
70104
  extendEnv: true
69178
70105
  }));
69179
70106
  const maxStdoutBytes = input.maxStdoutBytes;
@@ -69446,7 +70373,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
69446
70373
  "--diff-filter=ACMR",
69447
70374
  "--relative"
69448
70375
  ]).pipe(map$3((result) => {
69449
- if (result.status !== 0) return [];
70376
+ if (result.status !== 0) return null;
69450
70377
  return splitNullSeparated(result.stdout);
69451
70378
  })),
69452
70379
  showStagedContent: (directory, relativePath, options) => runCommand({
@@ -69731,7 +70658,11 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
69731
70658
  const ROOT_DIRECTORY_PLACEHOLDER = "<root>";
69732
70659
  const normalizeConfigForHash = (config) => {
69733
70660
  const clone = JSON.parse(JSON.stringify(config));
69734
- if (clone?.settings?.["react-doctor"]) clone.settings["react-doctor"].rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
70661
+ if (clone?.settings?.["react-doctor"]) {
70662
+ const reactDoctorSettings = clone.settings["react-doctor"];
70663
+ reactDoctorSettings.rootDirectory = ROOT_DIRECTORY_PLACEHOLDER;
70664
+ if (Array.isArray(reactDoctorSettings.unpluginAutoImportRootDirectories)) reactDoctorSettings.unpluginAutoImportRootDirectories = [ROOT_DIRECTORY_PLACEHOLDER];
70665
+ }
69735
70666
  if (Array.isArray(clone?.jsPlugins)) clone.jsPlugins = clone.jsPlugins.map((_, index) => `<plugin:${index}>`);
69736
70667
  return clone;
69737
70668
  };
@@ -69890,21 +70821,22 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
69890
70821
  }
69891
70822
  return enabled;
69892
70823
  };
69893
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), includedTags = /* @__PURE__ */ new Set(), includeTagDefaults = false, serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
70824
+ 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 }) => {
69894
70825
  const hasIncludedTags = includedTags.size > 0;
69895
70826
  const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" || hasIncludedTags ? null : resolveReactHooksJsPlugin(project.hasReactCompiler || project.hasReactCompilerLintPlugin === true, customRulesOnly);
69896
70827
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
69897
70828
  const jsPlugins = [];
69898
70829
  if (reactHooksJsPlugin) jsPlugins.push(reactHooksJsPlugin.entry);
69899
70830
  const capabilities = getCapabilities(project);
70831
+ const settingsRootDirectory = resolveSettingsRootDirectory(project.rootDirectory);
69900
70832
  const enabledReactDoctorRules = {};
69901
70833
  for (const registryEntry of REACT_DOCTOR_RULES) {
69902
- const rule = reactDoctorPlugin.rules[registryEntry.id];
70834
+ const rule = REACT_DOCTOR_RULE_REGISTRY[registryEntry.id];
69903
70835
  if (!rule) continue;
69904
70836
  if (ruleSelection === "cacheable" && CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
69905
70837
  if (ruleSelection === "sidecar" && !CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
69906
70838
  if (ruleSelection === "sidecar" && sidecarRuleIdFilter !== void 0 && !sidecarRuleIdFilter.has(registryEntry.id)) continue;
69907
- if (rule.scan !== void 0) continue;
70839
+ if (rule.isScanRule) continue;
69908
70840
  if (customRulesOnly && registryEntry.originallyExternal) continue;
69909
70841
  if (rule.framework !== "global" && !rule.requires) continue;
69910
70842
  if (!shouldEnableRule(rule.requires, rule.tags, capabilities, ignoredTags, rule.disabledWhen, includedTags)) continue;
@@ -69942,8 +70874,16 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
69942
70874
  jsPlugins: [...jsPlugins, pluginPath],
69943
70875
  settings: { "react-doctor": {
69944
70876
  framework: project.framework,
69945
- rootDirectory: resolveSettingsRootDirectory(project.rootDirectory),
70877
+ rootDirectory: settingsRootDirectory,
69946
70878
  capabilities: [...capabilities].sort(),
70879
+ ...runtimeGlobals && runtimeGlobals.length > 0 ? { runtimeGlobals: [...runtimeGlobals] } : {},
70880
+ ...unpluginAutoImportGlobalScopes && unpluginAutoImportGlobalScopes.length > 0 ? {
70881
+ unpluginAutoImportRootDirectories: [...new Set([settingsRootDirectory, project.rootDirectory])],
70882
+ unpluginAutoImportGlobalScopes: unpluginAutoImportGlobalScopes.map((scope) => ({
70883
+ directory: scope.directory,
70884
+ names: [...scope.names]
70885
+ }))
70886
+ } : {},
69947
70887
  ...project.shopifyFlashListMajorVersion !== null ? { shopifyFlashListMajorVersion: project.shopifyFlashListMajorVersion } : {},
69948
70888
  ...serverAuthFunctionNames && serverAuthFunctionNames.length > 0 ? { serverAuthFunctionNames: [...serverAuthFunctionNames] } : {}
69949
70889
  } },
@@ -69954,6 +70894,245 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
69954
70894
  }
69955
70895
  };
69956
70896
  };
70897
+ const AUTO_IMPORT_ADAPTER_PATTERN = /^unplugin-auto-import\/(?:astro|esbuild|rollup|rolldown|rspack|vite|webpack)$/;
70898
+ const CONFIG_BASENAMES = [
70899
+ "astro.config",
70900
+ "esbuild.config",
70901
+ "rollup.config",
70902
+ "rolldown.config",
70903
+ "rspack.config",
70904
+ "vite.config",
70905
+ "webpack.config"
70906
+ ];
70907
+ const CONFIG_EXTENSIONS = [
70908
+ ".cjs",
70909
+ ".cts",
70910
+ ".js",
70911
+ ".mjs",
70912
+ ".mts",
70913
+ ".ts"
70914
+ ];
70915
+ const CONFIG_FILENAMES = new Set(CONFIG_BASENAMES.flatMap((basename) => CONFIG_EXTENSIONS.map((extension) => `${basename}${extension}`)));
70916
+ const DEFAULT_ESLINT_GLOBALS_PATH = ".eslintrc-auto-import.json";
70917
+ const SUPPORTED_GLOBAL_VALUES = new Set([
70918
+ true,
70919
+ false,
70920
+ "readable",
70921
+ "readonly",
70922
+ "writable",
70923
+ "writeable"
70924
+ ]);
70925
+ const getStaticProperty = (objectExpression, propertyName) => objectExpression.properties.find((property) => {
70926
+ if (ts.isSpreadAssignment(property)) return false;
70927
+ const name = ts.isComputedPropertyName(property.name) ? unwrapTypescriptExpression(property.name.expression) : property.name;
70928
+ return (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) && name.text === propertyName;
70929
+ }) ?? null;
70930
+ const hasNonLiteralComputedProperty = (objectExpression) => objectExpression.properties.some((property) => !ts.isSpreadAssignment(property) && ts.isComputedPropertyName(property.name) && !ts.isStringLiteralLike(unwrapTypescriptExpression(property.name.expression)));
70931
+ const getStaticPropertyAssignment = (objectExpression, propertyName) => {
70932
+ const property = getStaticProperty(objectExpression, propertyName);
70933
+ return property && ts.isPropertyAssignment(property) ? property : null;
70934
+ };
70935
+ const getRequireModuleSpecifier = (expression) => {
70936
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
70937
+ if (ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === "default") return getRequireModuleSpecifier(unwrappedExpression.expression);
70938
+ if (!ts.isCallExpression(unwrappedExpression) || !ts.isIdentifier(unwrappedExpression.expression) || unwrappedExpression.expression.text !== "require" || unwrappedExpression.arguments.length !== 1) return null;
70939
+ const moduleSpecifier = unwrappedExpression.arguments[0];
70940
+ return moduleSpecifier && ts.isStringLiteralLike(moduleSpecifier) ? moduleSpecifier.text : null;
70941
+ };
70942
+ const getRequiredPropertyModuleSpecifier = (expression, propertyName) => {
70943
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
70944
+ return ts.isPropertyAccessExpression(unwrappedExpression) && unwrappedExpression.name.text === propertyName ? getRequireModuleSpecifier(unwrappedExpression.expression) : null;
70945
+ };
70946
+ 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");
70947
+ const isTopLevelExpression = (node) => {
70948
+ let ancestor = node.parent;
70949
+ while (ancestor && !ts.isSourceFile(ancestor)) {
70950
+ if (ts.isExpressionStatement(ancestor)) return ts.isSourceFile(ancestor.parent);
70951
+ if (!ts.isParenthesizedExpression(ancestor) && !ts.isAsExpression(ancestor) && !ts.isSatisfiesExpression(ancestor) && !ts.isNonNullExpression(ancestor) && !ts.isTypeAssertionExpression(ancestor) && !ts.isAwaitExpression(ancestor)) return false;
70952
+ ancestor = ancestor.parent;
70953
+ }
70954
+ return false;
70955
+ };
70956
+ const isInsideActiveConfigProperty = (node, propertyName, sourceFile, esbuildBindings, esbuildNamespaceBindings) => {
70957
+ let ancestor = node.parent;
70958
+ let didFindConfigProperty = false;
70959
+ while (ancestor && !ts.isSourceFile(ancestor)) {
70960
+ 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;
70961
+ if (ts.isPropertyAssignment(ancestor)) {
70962
+ const isConfigProperty = (ts.isIdentifier(ancestor.name) || ts.isStringLiteralLike(ancestor.name)) && ancestor.name.text === propertyName;
70963
+ if (didFindConfigProperty || !isConfigProperty) return false;
70964
+ if (!ts.isObjectLiteralExpression(ancestor.parent) || ancestor.parent.properties.some(ts.isSpreadAssignment)) return false;
70965
+ didFindConfigProperty = true;
70966
+ ancestor = ancestor.parent;
70967
+ continue;
70968
+ }
70969
+ if (didFindConfigProperty) {
70970
+ if (ts.isExportAssignment(ancestor)) return true;
70971
+ if (isCommonJsExportAssignment(ancestor, sourceFile)) return isTopLevelExpression(ancestor);
70972
+ 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);
70973
+ 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;
70974
+ }
70975
+ ancestor = ancestor.parent;
70976
+ }
70977
+ return false;
70978
+ };
70979
+ const getGlobalsPathFromActiveAutoImportCall = (callExpression, packageDirectory) => {
70980
+ const optionsExpression = callExpression.arguments[0];
70981
+ if (!optionsExpression) return null;
70982
+ const unwrappedOptions = unwrapTypescriptExpression(optionsExpression);
70983
+ if (!ts.isObjectLiteralExpression(unwrappedOptions)) return null;
70984
+ if (unwrappedOptions.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(unwrappedOptions)) return null;
70985
+ if (getStaticProperty(unwrappedOptions, "include") || getStaticProperty(unwrappedOptions, "exclude")) return null;
70986
+ const eslintrcProperty = getStaticPropertyAssignment(unwrappedOptions, "eslintrc");
70987
+ if (!eslintrcProperty) return null;
70988
+ const eslintrcExpression = unwrapTypescriptExpression(eslintrcProperty.initializer);
70989
+ if (!ts.isObjectLiteralExpression(eslintrcExpression)) return null;
70990
+ if (eslintrcExpression.properties.some(ts.isSpreadAssignment) || hasNonLiteralComputedProperty(eslintrcExpression)) return null;
70991
+ const enabledProperty = getStaticPropertyAssignment(eslintrcExpression, "enabled");
70992
+ if (!enabledProperty || unwrapTypescriptExpression(enabledProperty.initializer).kind !== ts.SyntaxKind.TrueKeyword) return null;
70993
+ const filepathProperty = getStaticProperty(eslintrcExpression, "filepath");
70994
+ if (!filepathProperty) return Path.join(packageDirectory, DEFAULT_ESLINT_GLOBALS_PATH);
70995
+ if (!ts.isPropertyAssignment(filepathProperty)) return null;
70996
+ const filepathExpression = unwrapTypescriptExpression(filepathProperty.initializer);
70997
+ return ts.isStringLiteralLike(filepathExpression) ? Path.resolve(packageDirectory, filepathExpression.text) : null;
70998
+ };
70999
+ const collectGlobalsPathsFromConfig = (configPath, packageDirectory) => {
71000
+ let sourceText;
71001
+ try {
71002
+ sourceText = NFS.readFileSync(configPath, "utf8");
71003
+ } catch {
71004
+ return {
71005
+ didFindActiveAutoImport: false,
71006
+ globalsPaths: []
71007
+ };
71008
+ }
71009
+ const sourceFile = ts.createSourceFile(configPath, sourceText, ts.ScriptTarget.Latest, true);
71010
+ const autoImportBindings = /* @__PURE__ */ new Map();
71011
+ const esbuildBindings = /* @__PURE__ */ new Set();
71012
+ const esbuildNamespaceBindings = /* @__PURE__ */ new Set();
71013
+ for (const statement of sourceFile.statements) {
71014
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteralLike(statement.moduleSpecifier)) {
71015
+ const moduleSpecifier = statement.moduleSpecifier.text;
71016
+ if (AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
71017
+ const defaultBinding = statement.importClause?.name;
71018
+ if (defaultBinding) autoImportBindings.set(defaultBinding.text, moduleSpecifier);
71019
+ }
71020
+ if (moduleSpecifier === "esbuild") {
71021
+ const defaultBinding = statement.importClause?.name;
71022
+ if (defaultBinding) esbuildNamespaceBindings.add(defaultBinding.text);
71023
+ const namedBindings = statement.importClause?.namedBindings;
71024
+ if (namedBindings && ts.isNamedImports(namedBindings)) {
71025
+ for (const importSpecifier of namedBindings.elements) if ((importSpecifier.propertyName ?? importSpecifier.name).text === "build") esbuildBindings.add(importSpecifier.name.text);
71026
+ }
71027
+ if (namedBindings && ts.isNamespaceImport(namedBindings)) esbuildNamespaceBindings.add(namedBindings.name.text);
71028
+ }
71029
+ }
71030
+ if (!ts.isVariableStatement(statement)) continue;
71031
+ for (const declaration of statement.declarationList.declarations) {
71032
+ if (!declaration.initializer) continue;
71033
+ const declarationName = ts.isIdentifier(declaration.name) ? declaration.name.text : null;
71034
+ const moduleSpecifier = getRequireModuleSpecifier(declaration.initializer);
71035
+ if (declarationName && moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) autoImportBindings.set(declarationName, moduleSpecifier);
71036
+ if (moduleSpecifier === "esbuild") {
71037
+ if (declarationName) esbuildNamespaceBindings.add(declarationName);
71038
+ if (ts.isObjectBindingPattern(declaration.name)) for (const bindingElement of declaration.name.elements) {
71039
+ const importedName = bindingElement.propertyName ?? bindingElement.name;
71040
+ if (ts.isIdentifier(importedName) && importedName.text === "build" && ts.isIdentifier(bindingElement.name)) esbuildBindings.add(bindingElement.name.text);
71041
+ }
71042
+ }
71043
+ if (declarationName && getRequiredPropertyModuleSpecifier(declaration.initializer, "build") === "esbuild") esbuildBindings.add(declarationName);
71044
+ }
71045
+ }
71046
+ const globalsPaths = /* @__PURE__ */ new Set();
71047
+ let didFindActiveAutoImport = false;
71048
+ let didFindUnsafeActiveAutoImport = false;
71049
+ const visit = (node) => {
71050
+ if (ts.isCallExpression(node)) {
71051
+ const moduleSpecifier = ts.isIdentifier(node.expression) ? autoImportBindings.get(node.expression.text) : getRequireModuleSpecifier(node.expression);
71052
+ if (moduleSpecifier && AUTO_IMPORT_ADAPTER_PATTERN.test(moduleSpecifier)) {
71053
+ if (isInsideActiveConfigProperty(node, moduleSpecifier.endsWith("/astro") ? "integrations" : "plugins", sourceFile, esbuildBindings, esbuildNamespaceBindings)) {
71054
+ didFindActiveAutoImport = true;
71055
+ const globalsPath = getGlobalsPathFromActiveAutoImportCall(node, packageDirectory);
71056
+ if (globalsPath) globalsPaths.add(globalsPath);
71057
+ else didFindUnsafeActiveAutoImport = true;
71058
+ }
71059
+ }
71060
+ }
71061
+ ts.forEachChild(node, visit);
71062
+ };
71063
+ visit(sourceFile);
71064
+ return {
71065
+ didFindActiveAutoImport,
71066
+ globalsPaths: didFindUnsafeActiveAutoImport ? [] : [...globalsPaths]
71067
+ };
71068
+ };
71069
+ const collectGeneratedGlobalNames = (globalsPath, rootDirectory) => {
71070
+ const relativePath = Path.relative(rootDirectory, globalsPath);
71071
+ if (relativePath.startsWith("..") || Path.isAbsolute(relativePath)) return [];
71072
+ const parsed = failOpenReadJson(globalsPath, null);
71073
+ if (!isPlainObject(parsed) || !isPlainObject(parsed.globals)) return [];
71074
+ 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();
71075
+ };
71076
+ const findOwningPackageDirectory = (absoluteFilePath, rootDirectory, cache) => {
71077
+ let currentDirectory = Path.dirname(absoluteFilePath);
71078
+ const visitedDirectories = [];
71079
+ while (true) {
71080
+ const cachedDirectory = cache.get(currentDirectory);
71081
+ if (cachedDirectory !== void 0) {
71082
+ for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, cachedDirectory);
71083
+ return cachedDirectory;
71084
+ }
71085
+ const relativeDirectory = Path.relative(rootDirectory, currentDirectory);
71086
+ if (relativeDirectory.startsWith("..") || Path.isAbsolute(relativeDirectory)) {
71087
+ for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
71088
+ return null;
71089
+ }
71090
+ visitedDirectories.push(currentDirectory);
71091
+ if (NFS.existsSync(Path.join(currentDirectory, "package.json"))) {
71092
+ for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, currentDirectory);
71093
+ return currentDirectory;
71094
+ }
71095
+ if (currentDirectory === rootDirectory) {
71096
+ for (const visitedDirectory of visitedDirectories) cache.set(visitedDirectory, null);
71097
+ return null;
71098
+ }
71099
+ currentDirectory = Path.dirname(currentDirectory);
71100
+ }
71101
+ };
71102
+ const collectPackageGlobalNames = (packageDirectory, rootDirectory) => {
71103
+ let directoryEntries;
71104
+ try {
71105
+ directoryEntries = NFS.readdirSync(packageDirectory, { withFileTypes: true });
71106
+ } catch {
71107
+ return [];
71108
+ }
71109
+ const configuredGlobalsPaths = [];
71110
+ for (const entry of directoryEntries) {
71111
+ if (!entry.isFile() && !entry.isSymbolicLink() || !CONFIG_FILENAMES.has(entry.name)) continue;
71112
+ const configGlobalsPaths = collectGlobalsPathsFromConfig(Path.join(packageDirectory, entry.name), packageDirectory);
71113
+ if (configGlobalsPaths.didFindActiveAutoImport) configuredGlobalsPaths.push(configGlobalsPaths.globalsPaths.toSorted());
71114
+ }
71115
+ if (configuredGlobalsPaths.length === 0) return [];
71116
+ const globalsPaths = configuredGlobalsPaths[0];
71117
+ if (configuredGlobalsPaths.some((candidatePaths) => candidatePaths.length !== globalsPaths.length || candidatePaths.some((candidatePath, index) => candidatePath !== globalsPaths[index]))) return [];
71118
+ const names = /* @__PURE__ */ new Set();
71119
+ for (const globalsPath of globalsPaths) for (const name of collectGeneratedGlobalNames(globalsPath, rootDirectory)) names.add(name);
71120
+ return [...names].sort();
71121
+ };
71122
+ const collectUnpluginAutoImportGlobalScopes = ({ rootDirectory, candidateFiles }) => {
71123
+ const absoluteRootDirectory = Path.resolve(rootDirectory);
71124
+ const packageDirectoryCache = /* @__PURE__ */ new Map();
71125
+ const packageDirectories = /* @__PURE__ */ new Set();
71126
+ for (const candidateFile of candidateFiles) {
71127
+ const packageDirectory = findOwningPackageDirectory(Path.resolve(absoluteRootDirectory, candidateFile), absoluteRootDirectory, packageDirectoryCache);
71128
+ if (packageDirectory) packageDirectories.add(packageDirectory);
71129
+ }
71130
+ const scopes = [...packageDirectories].map((packageDirectory) => ({
71131
+ directory: Path.relative(absoluteRootDirectory, packageDirectory).replaceAll("\\", "/"),
71132
+ names: collectPackageGlobalNames(packageDirectory, absoluteRootDirectory)
71133
+ })).sort((firstScope, secondScope) => firstScope.directory.localeCompare(secondScope.directory));
71134
+ return scopes.some((scope) => scope.names.length > 0) ? scopes : [];
71135
+ };
69957
71136
  const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
69958
71137
  const decodeFileDiagnostics = (raw) => {
69959
71138
  if (!Array.isArray(raw)) return null;
@@ -70276,6 +71455,56 @@ const appendReanimatedSharedValueHint = (help, rule, project) => {
70276
71455
  if (!help) return REANIMATED_SHARED_VALUE_HINT;
70277
71456
  return `${help}\n\n${REANIMATED_SHARED_VALUE_HINT}`;
70278
71457
  };
71458
+ const columnOfUtf8Offset = (sourceBuffer, utf8Offset) => {
71459
+ const boundedOffset = Math.min(Math.max(utf8Offset, 0), sourceBuffer.length);
71460
+ let lineStartOffset = boundedOffset;
71461
+ while (lineStartOffset > 0 && sourceBuffer[lineStartOffset - 1] !== 10) lineStartOffset--;
71462
+ return sourceBuffer.subarray(lineStartOffset, boundedOffset).toString("utf8").length + 1;
71463
+ };
71464
+ const utf8OffsetFromSourcePosition = (sourceBuffer, lineNumber, zeroBasedColumn) => {
71465
+ if (lineNumber < 1 || zeroBasedColumn < 0) return null;
71466
+ const sourceLines = sourceBuffer.toString("utf8").split("\n");
71467
+ const sourceLine = sourceLines[lineNumber - 1];
71468
+ if (sourceLine === void 0 || zeroBasedColumn > sourceLine.length) return null;
71469
+ const precedingLines = sourceLines.slice(0, lineNumber - 1).join("\n");
71470
+ return (lineNumber === 1 ? 0 : Buffer.byteLength(precedingLines) + Buffer.byteLength("\n")) + Buffer.byteLength(sourceLine.slice(0, zeroBasedColumn));
71471
+ };
71472
+ const mapPreparedSourceSpan = (span, preparedSourceMap) => {
71473
+ const generatedLine = lineOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset);
71474
+ const generatedColumn = columnOfUtf8Offset(preparedSourceMap.generatedBuffer, span.offset) - 1;
71475
+ const originalStart = originalPositionFor(preparedSourceMap.traceMap, {
71476
+ line: generatedLine,
71477
+ column: generatedColumn
71478
+ });
71479
+ if (originalStart.source === null || originalStart.line === null || originalStart.column === null) return null;
71480
+ const originalOffset = utf8OffsetFromSourcePosition(preparedSourceMap.sourceBuffer, originalStart.line, originalStart.column);
71481
+ if (originalOffset === null) return null;
71482
+ const generatedSpan = preparedSourceMap.generatedBuffer.subarray(span.offset, span.offset + span.length);
71483
+ return {
71484
+ offset: originalOffset,
71485
+ length: preparedSourceMap.sourceBuffer.subarray(originalOffset, originalOffset + generatedSpan.length).equals(generatedSpan) ? generatedSpan.length : 0,
71486
+ line: originalStart.line,
71487
+ column: originalStart.column + 1
71488
+ };
71489
+ };
71490
+ const mapPreparedSourceLabels = (labels, preparedSourceMap) => {
71491
+ const primaryLabel = labels[0];
71492
+ if (primaryLabel === void 0) return null;
71493
+ const primarySpan = mapPreparedSourceSpan(primaryLabel.span, preparedSourceMap);
71494
+ if (primarySpan === null) return null;
71495
+ const mappedLabels = [{
71496
+ ...primaryLabel,
71497
+ span: primarySpan
71498
+ }];
71499
+ for (const relatedLabel of labels.slice(1)) {
71500
+ const relatedSpan = mapPreparedSourceSpan(relatedLabel.span, preparedSourceMap);
71501
+ if (relatedSpan !== null) mappedLabels.push({
71502
+ ...relatedLabel,
71503
+ span: relatedSpan
71504
+ });
71505
+ }
71506
+ return mappedLabels;
71507
+ };
70279
71508
  const REDACTED_PLACEHOLDER = "<redacted>";
70280
71509
  const KEEP_PREFIX = `$1${REDACTED_PLACEHOLDER}`;
70281
71510
  const KNOWN_SECRET_RULES = [
@@ -70918,7 +72147,7 @@ const PLUGIN_CATEGORY_MAP = {
70918
72147
  };
70919
72148
  const lookupOwnString = (record, key) => Object.hasOwn(record, key) ? record[key] : void 0;
70920
72149
  const getRuleRecommendation = (ruleName, project) => {
70921
- const rule = reactDoctorPlugin.rules[ruleName];
72150
+ const rule = REACT_DOCTOR_RULE_REGISTRY[ruleName];
70922
72151
  if (!rule) return void 0;
70923
72152
  if (rule.recommendationFor) {
70924
72153
  const capabilities = getCapabilities(project);
@@ -70927,8 +72156,8 @@ const getRuleRecommendation = (ruleName, project) => {
70927
72156
  }
70928
72157
  return rule.recommendation;
70929
72158
  };
70930
- const getRuleCategory = (ruleName) => reactDoctorPlugin.rules[ruleName]?.category;
70931
- const getRuleTitle = (ruleName) => reactDoctorPlugin.rules[ruleName]?.title;
72159
+ const getRuleCategory = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.category;
72160
+ const getRuleTitle = (ruleName) => REACT_DOCTOR_RULE_REGISTRY[ruleName]?.title;
70932
72161
  const resolveDiagnosticTitle = (plugin, rule) => {
70933
72162
  if (plugin !== "react-hooks-js") return getRuleTitle(rule);
70934
72163
  if (rule === "error-boundaries") return REACT_ERROR_BOUNDARY_TITLE;
@@ -70983,7 +72212,7 @@ const resolveDiagnosticCategory = (plugin, rule) => {
70983
72212
  if (plugin === "react-hooks-js" && rule === "error-boundaries") return "Bugs";
70984
72213
  return getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
70985
72214
  };
70986
- const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(reactDoctorPlugin.rules[rule]?.matchByOccurrence);
72215
+ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(REACT_DOCTOR_RULE_REGISTRY[rule]?.matchByOccurrence);
70987
72216
  /**
70988
72217
  * Maps oxlint's non-primary labels (`labels[1..]`) into related source
70989
72218
  * locations. Editors surface these as a diagnostic's
@@ -70991,7 +72220,7 @@ const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORI
70991
72220
  * with empty text still carry a useful jump target, so they're kept
70992
72221
  * with a neutral message.
70993
72222
  */
70994
- const buildRelatedLocations = (labels, filePath) => {
72223
+ const buildRelatedLocations = (labels, filePath, sourceBuffer) => {
70995
72224
  if (labels.length <= 1) return [];
70996
72225
  const related = [];
70997
72226
  for (let labelIndex = 1; labelIndex < labels.length; labelIndex++) {
@@ -70999,8 +72228,8 @@ const buildRelatedLocations = (labels, filePath) => {
70999
72228
  if (!label?.span) continue;
71000
72229
  related.push({
71001
72230
  filePath,
71002
- line: label.span.line ?? 0,
71003
- column: label.span.column ?? 0,
72231
+ line: sourceBuffer === null ? label.span.line ?? 0 : lineOfUtf8Offset(sourceBuffer, label.span.offset),
72232
+ column: sourceBuffer === null ? label.span.column ?? 0 : columnOfUtf8Offset(sourceBuffer, label.span.offset),
71004
72233
  offset: label.span.offset,
71005
72234
  length: label.span.length,
71006
72235
  message: label.label ?? ""
@@ -71020,7 +72249,7 @@ const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnos
71020
72249
  * to the first `{`. Raises `OxlintOutputUnparseable` when the
71021
72250
  * stdout isn't valid JSON or doesn't carry a `diagnostics` array.
71022
72251
  */
71023
- const parseOxlintOutput = (stdout, project, rootDirectory) => {
72252
+ const parseOxlintOutput = (stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath) => {
71024
72253
  if (!stdout) return [];
71025
72254
  const jsonStart = stdout.indexOf("{");
71026
72255
  const sanitizedStdout = jsonStart > 0 ? stdout.slice(jsonStart) : stdout;
@@ -71037,8 +72266,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
71037
72266
  const sourceBufferCache = /* @__PURE__ */ new Map();
71038
72267
  const sourceLinesCache = /* @__PURE__ */ new Map();
71039
72268
  const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
72269
+ const resolveMappedSourceFilename = (filename) => sourcePathByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
72270
+ const resolvePreparedSourceMap = (filename) => sourceMapByLintPath?.get(Path.normalize(resolveAbsolutePath(filename)));
72271
+ const resolveSourceFilename = (filename) => resolveMappedSourceFilename(filename) ?? filename;
71040
72272
  const readSourceBuffer = (filename) => {
71041
- const absolutePath = resolveAbsolutePath(filename);
72273
+ const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
71042
72274
  const cached = sourceBufferCache.get(absolutePath);
71043
72275
  if (cached !== void 0) return cached;
71044
72276
  let sourceBuffer;
@@ -71051,7 +72283,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
71051
72283
  return sourceBuffer;
71052
72284
  };
71053
72285
  const readSourceLines = (filename) => {
71054
- const absolutePath = resolveAbsolutePath(filename);
72286
+ const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
71055
72287
  const cached = sourceLinesCache.get(absolutePath);
71056
72288
  if (cached !== void 0) return cached;
71057
72289
  const sourceBuffer = readSourceBuffer(filename);
@@ -71060,27 +72292,42 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
71060
72292
  return sourceLines;
71061
72293
  };
71062
72294
  const isMinifiedDiagnosticFile = (filename) => {
71063
- const absolutePath = resolveAbsolutePath(filename);
72295
+ const absolutePath = resolveAbsolutePath(resolveSourceFilename(filename));
71064
72296
  const cached = minifiedFileCache.get(absolutePath);
71065
72297
  if (cached !== void 0) return cached;
71066
72298
  const minified = isMinifiedSource(absolutePath);
71067
72299
  minifiedFileCache.set(absolutePath, minified);
71068
72300
  return minified;
71069
72301
  };
71070
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !(TYPESCRIPT_DECLARATION_FILE_PATTERN.test(diagnostic.filename) && OXLINT_IGNORED_DECLARATION_DIAGNOSTIC_CODES.has(diagnostic.code)) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
72302
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.flatMap((diagnostic) => {
72303
+ const preparedSourceMap = resolvePreparedSourceMap(diagnostic.filename);
72304
+ if (preparedSourceMap === void 0) return [diagnostic];
72305
+ const { plugin, rule } = parseRuleCode(diagnostic.code);
72306
+ if (plugin !== "react-doctor" || !REACT_DOCTOR_RULE_REGISTRY[rule]?.tags?.includes("design")) return [];
72307
+ const labels = mapPreparedSourceLabels(diagnostic.labels, preparedSourceMap);
72308
+ const sourceFilename = resolveMappedSourceFilename(diagnostic.filename);
72309
+ return labels === null || sourceFilename === void 0 ? [] : [{
72310
+ ...diagnostic,
72311
+ filename: sourceFilename,
72312
+ labels
72313
+ }];
72314
+ }).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) => {
71071
72315
  const { plugin, rule } = parseRuleCode(diagnostic.code);
71072
72316
  const primaryLabel = diagnostic.labels[0];
71073
72317
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
71074
- const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
72318
+ const mappedSourceFilename = resolveMappedSourceFilename(diagnostic.filename);
72319
+ const normalizedFilePath = (mappedSourceFilename ?? diagnostic.filename).replaceAll("\\", "/");
71075
72320
  const primarySpan = primaryLabel?.span;
71076
72321
  const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
71077
- const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
72322
+ const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath, mappedSourceFilename === void 0 ? null : sourceBuffer);
71078
72323
  const category = resolveDiagnosticCategory(plugin, rule);
71079
72324
  const matchByOccurrence = resolveMatchByOccurrence(rule, category);
71080
72325
  const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
71081
- const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
72326
+ const primaryLineNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.line ?? 0;
72327
+ const primaryColumnNumber = primarySpan && mappedSourceFilename !== void 0 && sourceBuffer !== null ? columnOfUtf8Offset(sourceBuffer, primarySpan.offset) : primarySpan?.column ?? 0;
72328
+ const primaryLineIndex = primarySpan ? primaryLineNumber - 1 : -1;
71082
72329
  const primaryLine = sourceLines?.[primaryLineIndex];
71083
- const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
72330
+ const primaryColumnIndex = primarySpan ? primaryColumnNumber - 1 : -1;
71084
72331
  const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
71085
72332
  const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
71086
72333
  const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
@@ -71093,8 +72340,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
71093
72340
  message: cleaned.message,
71094
72341
  help: cleaned.help,
71095
72342
  url: diagnostic.url,
71096
- line: primarySpan?.line ?? 0,
71097
- column: primarySpan?.column ?? 0,
72343
+ line: primaryLineNumber,
72344
+ column: primaryColumnNumber,
71098
72345
  ...primarySpan ? {
71099
72346
  offset: primarySpan.offset,
71100
72347
  length: primarySpan.length,
@@ -71142,11 +72389,12 @@ const SANITIZED_ENV = buildOxlintChildEnv(process.env);
71142
72389
  * The first three are splittable (the caller's binary-split retry
71143
72390
  * shrinks the batch and re-spawns); the fourth isn't.
71144
72391
  */
71145
- const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal) => new Promise((resolve, reject) => {
72392
+ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES, abortSignal, onSpawn) => new Promise((resolve, reject) => {
71146
72393
  if (abortSignal?.aborted) {
71147
72394
  reject(new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) }));
71148
72395
  return;
71149
72396
  }
72397
+ onSpawn?.();
71150
72398
  const child = spawn(nodeBinaryPath, buildProfiledNodeArguments({
71151
72399
  argumentsList: args,
71152
72400
  cpuProfileDirectory: SANITIZED_ENV.REACT_DOCTOR_CPU_PROFILE_DIR,
@@ -71282,7 +72530,11 @@ const isParallelismRelatedSpawnError = (error) => {
71282
72530
  * loop with a slimmer config in that case.
71283
72531
  */
71284
72532
  const spawnLintBatches = async (input) => {
71285
- const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
72533
+ const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, sourcePathByLintPath, sourceMapByLintPath, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes, splitTotalBudgetMs = OXLINT_SPLIT_TOTAL_BUDGET_MS, splitMaxDepth = 8, signal, deadlineEpochMs } = input;
72534
+ const resolveSourcePath = (filePath) => {
72535
+ const absoluteFilePath = Path.isAbsolute(filePath) ? filePath : Path.resolve(rootDirectory, filePath);
72536
+ return sourcePathByLintPath?.get(Path.normalize(absoluteFilePath)) ?? filePath;
72537
+ };
71286
72538
  const requestedConcurrency = resolveScanConcurrency(input.concurrency ?? 1);
71287
72539
  let rescueDeadlineEpochMs;
71288
72540
  const isPastDeadline = () => deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(deadlineEpochMs) === 0 || rescueDeadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(rescueDeadlineEpochMs) === 0;
@@ -71302,7 +72554,21 @@ const spawnLintBatches = async (input) => {
71302
72554
  }
71303
72555
  const batchArgs = [...baseArgs, ...batch];
71304
72556
  try {
71305
- return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal), project, rootDirectory);
72557
+ const spawnBatch = () => {
72558
+ if (isPastDeadline()) {
72559
+ deadlineSkippedFiles.push(...batch);
72560
+ batchState.deadlineSkippedFileCount += batch.length;
72561
+ return Promise.resolve(null);
72562
+ }
72563
+ return spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes, signal, () => {
72564
+ if (batchState.didStart) return;
72565
+ batchState.didStart = true;
72566
+ startedFileCount += batchState.initialFileCount;
72567
+ });
72568
+ };
72569
+ const stdout = input.spawnSlots === void 0 ? await spawnBatch() : await input.spawnSlots.run(spawnBatch, signal);
72570
+ if (stdout === null) return [];
72571
+ return parseOxlintOutput(stdout, project, rootDirectory, sourcePathByLintPath, sourceMapByLintPath);
71306
72572
  } catch (error) {
71307
72573
  if (!isSplittableReactDoctorError(error)) throw error;
71308
72574
  if (isPastDeadline()) {
@@ -71346,14 +72612,15 @@ const spawnLintBatches = async (input) => {
71346
72612
  deadlineSkippedFiles.push(...batch);
71347
72613
  return [];
71348
72614
  }
71349
- startedFileCount += batch.length;
71350
72615
  const batchState = {
71351
72616
  deadlineMs: null,
71352
- deadlineSkippedFileCount: 0
72617
+ deadlineSkippedFileCount: 0,
72618
+ didStart: false,
72619
+ initialFileCount: batch.length
71353
72620
  };
71354
72621
  const batchDiagnostics = await spawnLintBatch(batch, 0, batchState);
71355
72622
  scannedFileCount += batch.length - batchState.deadlineSkippedFileCount;
71356
- if (passOnFileProgress) {
72623
+ if (passOnFileProgress && batchState.didStart) {
71357
72624
  displayedFileCount = Math.min(Math.max(displayedFileCount, scannedFileCount), totalFileCount);
71358
72625
  passOnFileProgress(displayedFileCount, totalFileCount);
71359
72626
  }
@@ -71408,10 +72675,12 @@ const spawnLintBatches = async (input) => {
71408
72675
  onPartialFailure(buildMessage(`${skippedFiles.slice(0, 3).join(", ")}${skippedFiles.length > 3 ? `, +${skippedFiles.length - 3} more` : ""}`));
71409
72676
  };
71410
72677
  const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
71411
- reportSkippedFiles(droppedFiles, (fileListPreview) => `${droppedFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
71412
- reportSkippedFiles(outcome.deadlineSkippedFiles, (fileListPreview) => `${outcome.deadlineSkippedFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
72678
+ const droppedSourceFiles = [...new Set(droppedFiles.map(resolveSourcePath))];
72679
+ const deadlineSkippedSourceFiles = [...new Set(outcome.deadlineSkippedFiles.map(resolveSourcePath))];
72680
+ reportSkippedFiles(droppedSourceFiles, (fileListPreview) => `${droppedSourceFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
72681
+ reportSkippedFiles(deadlineSkippedSourceFiles, (fileListPreview) => `${deadlineSkippedSourceFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
71413
72682
  const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
71414
- input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
72683
+ input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)).map(resolveSourcePath))].sort());
71415
72684
  return dedupeDiagnostics(diagnostics);
71416
72685
  };
71417
72686
  let didValidate = false;
@@ -71435,8 +72704,8 @@ const validateRuleRegistration = () => {
71435
72704
  for (const fullKey of ALL_REACT_DOCTOR_RULE_KEYS) {
71436
72705
  const ruleName = fullKey.replace(/^react-doctor\//, "");
71437
72706
  if (!getRuleCategory(ruleName)) missingCategory.push(fullKey);
71438
- if (!reactDoctorPlugin.rules[ruleName]?.recommendation) missingHelp.push(fullKey);
71439
- if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !reactDoctorPlugin.rules[ruleName]?.requires) missingMetadata.push(fullKey);
72707
+ if (!REACT_DOCTOR_RULE_REGISTRY[ruleName]?.recommendation) missingHelp.push(fullKey);
72708
+ if (FRAMEWORK_SPECIFIC_RULE_KEYS.has(fullKey) && !REACT_DOCTOR_RULE_REGISTRY[ruleName]?.requires) missingMetadata.push(fullKey);
71440
72709
  }
71441
72710
  if (missingCategory.length === 0 && missingHelp.length === 0 && missingMetadata.length === 0) return;
71442
72711
  const detail = [
@@ -71510,6 +72779,294 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
71510
72779
  }
71511
72780
  return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
71512
72781
  };
72782
+ const THREE_MODULE_IMPORT_PATTERN = /\b(?:from\s*|import\s*(?:\(\s*)?|require\s*\(\s*)["']three(?:\/[^"']*)?["']/;
72783
+ const containsThreeModuleImport = (sourceText) => THREE_MODULE_IMPORT_PATTERN.test(sourceText);
72784
+ const COMMENT_OPEN = "<!--";
72785
+ const COMMENT_CLOSE = "-->";
72786
+ const FRONTMATTER_FENCE = "---";
72787
+ const SCRIPT_TAG_NAME = "script";
72788
+ const SCRIPT_OPEN = `<${SCRIPT_TAG_NAME}`;
72789
+ const SCRIPT_CLOSE = `</${SCRIPT_TAG_NAME}`;
72790
+ const TEMPLATE_TAG_NAME = "template";
72791
+ const TEMPLATE_CLOSE = `</${TEMPLATE_TAG_NAME}`;
72792
+ const JAVASCRIPT_MIME_TYPES = new Set([
72793
+ "application/ecmascript",
72794
+ "application/javascript",
72795
+ "application/x-ecmascript",
72796
+ "application/x-javascript",
72797
+ "text/ecmascript",
72798
+ "text/javascript",
72799
+ "text/javascript1.0",
72800
+ "text/javascript1.1",
72801
+ "text/javascript1.2",
72802
+ "text/javascript1.3",
72803
+ "text/javascript1.4",
72804
+ "text/javascript1.5",
72805
+ "text/jscript",
72806
+ "text/livescript",
72807
+ "text/x-ecmascript",
72808
+ "text/x-javascript"
72809
+ ]);
72810
+ const RAW_TEXT_TAG_NAMES = new Set([
72811
+ "iframe",
72812
+ "noembed",
72813
+ "noframes",
72814
+ "noscript",
72815
+ "style",
72816
+ "textarea",
72817
+ "title",
72818
+ "xmp"
72819
+ ]);
72820
+ const PLAINTEXT_TAG_NAME = "plaintext";
72821
+ const TAG_OPEN_UTF8_BYTE = "<".charCodeAt(0);
72822
+ const TAG_CLOSE_UTF8_BYTE = ">".charCodeAt(0);
72823
+ const SINGLE_QUOTE_UTF8_BYTE = "'".charCodeAt(0);
72824
+ const DOUBLE_QUOTE_UTF8_BYTE = "\"".charCodeAt(0);
72825
+ const ATTRIBUTE_ASSIGNMENT_UTF8_BYTE = "=".charCodeAt(0);
72826
+ const TAG_SELF_CLOSE_UTF8_BYTE = "/".charCodeAt(0);
72827
+ const TAB_UTF8_BYTE = " ".charCodeAt(0);
72828
+ const FORM_FEED_UTF8_BYTE = "\f".charCodeAt(0);
72829
+ const isHtmlWhitespace = (byte) => byte === TAB_UTF8_BYTE || byte === 10 || byte === FORM_FEED_UTF8_BYTE || byte === 13 || byte === 32;
72830
+ const matchesAsciiCaseInsensitive = (sourceBuffer, startByte, expected) => {
72831
+ if (startByte + expected.length > sourceBuffer.length) return false;
72832
+ for (let expectedIndex = 0; expectedIndex < expected.length; expectedIndex++) {
72833
+ const sourceByte = sourceBuffer[startByte + expectedIndex];
72834
+ if (sourceByte === void 0 || String.fromCharCode(sourceByte).toLowerCase() !== expected[expectedIndex]) return false;
72835
+ }
72836
+ return true;
72837
+ };
72838
+ const isTagBoundary = (byte) => byte === TAG_CLOSE_UTF8_BYTE || byte === TAG_SELF_CLOSE_UTF8_BYTE || isHtmlWhitespace(byte);
72839
+ const isPotentialTagStart = (byte) => {
72840
+ if (byte === void 0) return false;
72841
+ return /[A-Za-z!/?]/.test(String.fromCharCode(byte));
72842
+ };
72843
+ const findLineEnd = (sourceBuffer, lineStartByte) => {
72844
+ let byteIndex = lineStartByte;
72845
+ while (byteIndex < sourceBuffer.length && sourceBuffer[byteIndex] !== 10 && sourceBuffer[byteIndex] !== 13) byteIndex++;
72846
+ return byteIndex;
72847
+ };
72848
+ const findNextLineStart = (sourceBuffer, lineStartByte) => {
72849
+ const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
72850
+ if (sourceBuffer[lineEndByte] === 13 && sourceBuffer[lineEndByte + 1] === 10) return lineEndByte + 2;
72851
+ return Math.min(lineEndByte + 1, sourceBuffer.length);
72852
+ };
72853
+ const isFrontmatterFenceLine = (sourceBuffer, lineStartByte) => {
72854
+ if (!matchesAsciiCaseInsensitive(sourceBuffer, lineStartByte, FRONTMATTER_FENCE)) return false;
72855
+ const lineEndByte = findLineEnd(sourceBuffer, lineStartByte);
72856
+ for (let byteIndex = lineStartByte + 3; byteIndex < lineEndByte; byteIndex++) if (!isHtmlWhitespace(sourceBuffer[byteIndex])) return false;
72857
+ return true;
72858
+ };
72859
+ const findFrontmatterEnd = (sourceBuffer) => {
72860
+ if (!isFrontmatterFenceLine(sourceBuffer, 0)) return 0;
72861
+ const openingFenceEndByte = findLineEnd(sourceBuffer, 0);
72862
+ let lineStartByte = findNextLineStart(sourceBuffer, 0);
72863
+ while (lineStartByte < sourceBuffer.length) {
72864
+ if (isFrontmatterFenceLine(sourceBuffer, lineStartByte)) return findLineEnd(sourceBuffer, lineStartByte);
72865
+ lineStartByte = findNextLineStart(sourceBuffer, lineStartByte);
72866
+ }
72867
+ return openingFenceEndByte;
72868
+ };
72869
+ const maskByteRange = (maskedBuffer, startByte, endByte) => {
72870
+ for (let byteIndex = startByte; byteIndex < endByte; byteIndex++) {
72871
+ const byte = maskedBuffer[byteIndex];
72872
+ if (byte !== 10 && byte !== 13) maskedBuffer[byteIndex] = 32;
72873
+ }
72874
+ };
72875
+ const readStartTagName = (sourceBuffer, tagStartByte) => {
72876
+ const firstNameByte = sourceBuffer[tagStartByte + 1];
72877
+ if (firstNameByte === void 0 || !/[A-Za-z]/.test(String.fromCharCode(firstNameByte))) return null;
72878
+ let nameEndByte = tagStartByte + 2;
72879
+ while (nameEndByte < sourceBuffer.length && /[A-Za-z0-9:-]/.test(String.fromCharCode(sourceBuffer[nameEndByte] ?? 32))) nameEndByte++;
72880
+ return sourceBuffer.subarray(tagStartByte + 1, nameEndByte).toString("ascii").toLowerCase();
72881
+ };
72882
+ const findTagEnd = (sourceBuffer, startByte) => {
72883
+ let quoteByte = null;
72884
+ for (let byteIndex = startByte; byteIndex < sourceBuffer.length; byteIndex++) {
72885
+ const byte = sourceBuffer[byteIndex];
72886
+ if (quoteByte !== null) {
72887
+ if (byte === quoteByte) quoteByte = null;
72888
+ continue;
72889
+ }
72890
+ if (byte === SINGLE_QUOTE_UTF8_BYTE || byte === DOUBLE_QUOTE_UTF8_BYTE) {
72891
+ quoteByte = byte;
72892
+ continue;
72893
+ }
72894
+ if (byte === TAG_CLOSE_UTF8_BYTE) return byteIndex;
72895
+ }
72896
+ return sourceBuffer.length;
72897
+ };
72898
+ const parseScriptAttributes = (sourceBuffer, attributesStartByte, tagEndByte) => {
72899
+ let byteIndex = attributesStartByte;
72900
+ let hasSource = false;
72901
+ let language = null;
72902
+ let scriptType = null;
72903
+ while (byteIndex < tagEndByte) {
72904
+ while (byteIndex < tagEndByte && (isHtmlWhitespace(sourceBuffer[byteIndex]) || sourceBuffer[byteIndex] === TAG_SELF_CLOSE_UTF8_BYTE)) byteIndex++;
72905
+ const attributeNameStartByte = byteIndex;
72906
+ while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== ATTRIBUTE_ASSIGNMENT_UTF8_BYTE && sourceBuffer[byteIndex] !== TAG_SELF_CLOSE_UTF8_BYTE) byteIndex++;
72907
+ const attributeName = sourceBuffer.subarray(attributeNameStartByte, byteIndex).toString("ascii").toLowerCase();
72908
+ while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
72909
+ let attributeValue = "";
72910
+ if (sourceBuffer[byteIndex] === ATTRIBUTE_ASSIGNMENT_UTF8_BYTE) {
72911
+ byteIndex++;
72912
+ while (byteIndex < tagEndByte && isHtmlWhitespace(sourceBuffer[byteIndex])) byteIndex++;
72913
+ const quoteByte = sourceBuffer[byteIndex];
72914
+ if (quoteByte === SINGLE_QUOTE_UTF8_BYTE || quoteByte === DOUBLE_QUOTE_UTF8_BYTE) {
72915
+ const valueStartByte = byteIndex + 1;
72916
+ byteIndex = valueStartByte;
72917
+ while (byteIndex < tagEndByte && sourceBuffer[byteIndex] !== quoteByte) byteIndex++;
72918
+ attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
72919
+ if (byteIndex < tagEndByte) byteIndex++;
72920
+ } else {
72921
+ const valueStartByte = byteIndex;
72922
+ while (byteIndex < tagEndByte && !isHtmlWhitespace(sourceBuffer[byteIndex]) && sourceBuffer[byteIndex] !== TAG_CLOSE_UTF8_BYTE) byteIndex++;
72923
+ attributeValue = sourceBuffer.subarray(valueStartByte, byteIndex).toString("utf8");
72924
+ }
72925
+ }
72926
+ if (attributeName === "src") hasSource = true;
72927
+ else if (attributeName === "type" && scriptType === null) scriptType = attributeValue;
72928
+ else if (attributeName === "language" && language === null) language = attributeValue;
72929
+ }
72930
+ return {
72931
+ hasSource,
72932
+ language,
72933
+ type: scriptType
72934
+ };
72935
+ };
72936
+ const isExecutableScript = (attributes) => {
72937
+ if (attributes.hasSource) return false;
72938
+ const type = attributes.type?.trim().toLowerCase() ?? "";
72939
+ if (type !== "") {
72940
+ const mimeType = type.split(";")[0]?.trim() ?? "";
72941
+ return mimeType === "module" || JAVASCRIPT_MIME_TYPES.has(mimeType);
72942
+ }
72943
+ const language = attributes.language?.trim().toLowerCase() ?? "";
72944
+ return language === "" || JAVASCRIPT_MIME_TYPES.has(`text/${language}`);
72945
+ };
72946
+ const findElementClose = (sourceBuffer, startByte, tagName) => {
72947
+ const closeTagStart = `</${tagName}`;
72948
+ 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;
72949
+ return sourceBuffer.length;
72950
+ };
72951
+ const prepareHtmlScriptSource = (sourceBuffer) => {
72952
+ const frontmatterEndByte = findFrontmatterEnd(sourceBuffer);
72953
+ let maskedBuffer = frontmatterEndByte > 0 ? Buffer.from(sourceBuffer) : null;
72954
+ if (maskedBuffer !== null) maskByteRange(maskedBuffer, 0, frontmatterEndByte);
72955
+ const executableScriptBodies = [];
72956
+ let byteIndex = frontmatterEndByte;
72957
+ let templateDepth = 0;
72958
+ while (byteIndex < sourceBuffer.length) {
72959
+ if (sourceBuffer[byteIndex] !== TAG_OPEN_UTF8_BYTE) {
72960
+ byteIndex++;
72961
+ continue;
72962
+ }
72963
+ if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, COMMENT_OPEN)) {
72964
+ const commentEndByte = sourceBuffer.indexOf(COMMENT_CLOSE, byteIndex + 4);
72965
+ byteIndex = commentEndByte === -1 ? sourceBuffer.length : commentEndByte + 3;
72966
+ continue;
72967
+ }
72968
+ if (matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, TEMPLATE_CLOSE) && isTagBoundary(sourceBuffer[byteIndex + TEMPLATE_CLOSE.length])) {
72969
+ const tagEndByte = findTagEnd(sourceBuffer, byteIndex + TEMPLATE_CLOSE.length);
72970
+ if (templateDepth > 0) templateDepth--;
72971
+ byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
72972
+ continue;
72973
+ }
72974
+ if (!matchesAsciiCaseInsensitive(sourceBuffer, byteIndex, SCRIPT_OPEN) || !isTagBoundary(sourceBuffer[byteIndex + SCRIPT_OPEN.length])) {
72975
+ if (!isPotentialTagStart(sourceBuffer[byteIndex + 1])) {
72976
+ byteIndex++;
72977
+ continue;
72978
+ }
72979
+ const tagEndByte = findTagEnd(sourceBuffer, byteIndex + 1);
72980
+ const tagName = readStartTagName(sourceBuffer, byteIndex);
72981
+ if (tagName === PLAINTEXT_TAG_NAME) break;
72982
+ if (tagName === TEMPLATE_TAG_NAME) templateDepth++;
72983
+ if (tagName !== null && RAW_TEXT_TAG_NAMES.has(tagName)) {
72984
+ const closeTagStartByte = findElementClose(sourceBuffer, tagEndByte + 1, tagName);
72985
+ if (closeTagStartByte === sourceBuffer.length) break;
72986
+ const closeTagEndByte = findTagEnd(sourceBuffer, closeTagStartByte + tagName.length + 2);
72987
+ byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
72988
+ continue;
72989
+ }
72990
+ byteIndex = Math.min(tagEndByte + 1, sourceBuffer.length);
72991
+ continue;
72992
+ }
72993
+ const tagEndByte = findTagEnd(sourceBuffer, byteIndex + SCRIPT_OPEN.length);
72994
+ if (tagEndByte === sourceBuffer.length) break;
72995
+ const bodyStartByte = tagEndByte + 1;
72996
+ const bodyEndByte = findElementClose(sourceBuffer, bodyStartByte, SCRIPT_TAG_NAME);
72997
+ const attributes = parseScriptAttributes(sourceBuffer, byteIndex + SCRIPT_OPEN.length, tagEndByte);
72998
+ if (attributes.hasSource || templateDepth > 0) {
72999
+ maskedBuffer ??= Buffer.from(sourceBuffer);
73000
+ maskByteRange(maskedBuffer, bodyStartByte, bodyEndByte);
73001
+ } else if (isExecutableScript(attributes)) executableScriptBodies.push(sourceBuffer.subarray(bodyStartByte, bodyEndByte));
73002
+ if (bodyEndByte === sourceBuffer.length) break;
73003
+ const closeTagEndByte = findTagEnd(sourceBuffer, bodyEndByte + SCRIPT_CLOSE.length);
73004
+ byteIndex = Math.min(closeTagEndByte + 1, sourceBuffer.length);
73005
+ }
73006
+ return {
73007
+ executableScriptBodies,
73008
+ lintBuffer: maskedBuffer ?? sourceBuffer
73009
+ };
73010
+ };
73011
+ const ASTRO_FILE_PATTERN = /\.astro$/;
73012
+ const prepareLintSources = (rootDirectory, temporaryDirectory, candidateFiles) => {
73013
+ const lintFiles = [];
73014
+ const sourcePathByLintPath = /* @__PURE__ */ new Map();
73015
+ const sourceMapByLintPath = /* @__PURE__ */ new Map();
73016
+ const sizeByLintPath = /* @__PURE__ */ new Map();
73017
+ const htmlSourcesDirectory = Path.join(temporaryDirectory, "html-sources");
73018
+ const astroSourcesDirectory = Path.join(temporaryDirectory, "astro-sources");
73019
+ let htmlFileIndex = 0;
73020
+ let astroFileIndex = 0;
73021
+ let hasThreeModuleImport = false;
73022
+ for (const candidateFile of candidateFiles) {
73023
+ if (!HTML_FILE_PATTERN.test(candidateFile) && !ASTRO_FILE_PATTERN.test(candidateFile)) {
73024
+ lintFiles.push(candidateFile);
73025
+ continue;
73026
+ }
73027
+ const absoluteSourcePath = Path.isAbsolute(candidateFile) ? candidateFile : Path.resolve(rootDirectory, candidateFile);
73028
+ const sourceBuffer = NFS.readFileSync(absoluteSourcePath);
73029
+ if (ASTRO_FILE_PATTERN.test(candidateFile)) {
73030
+ const compilerSourcePath = absoluteSourcePath.replaceAll("\\", "/");
73031
+ const convertedSource = convertToTSX(sourceBuffer.toString("utf8"), {
73032
+ filename: compilerSourcePath,
73033
+ sourcemap: "external",
73034
+ includeScripts: true
73035
+ });
73036
+ if (astroFileIndex === 0) NFS.mkdirSync(astroSourcesDirectory, { recursive: true });
73037
+ const lintPath = Path.join(astroSourcesDirectory, `${astroFileIndex}.tsx`);
73038
+ const generatedBuffer = Buffer.from(convertedSource.code);
73039
+ NFS.writeFileSync(lintPath, generatedBuffer);
73040
+ lintFiles.push(candidateFile);
73041
+ lintFiles.push(lintPath);
73042
+ sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
73043
+ sourceMapByLintPath.set(Path.resolve(lintPath), {
73044
+ traceMap: new TraceMap(JSON.stringify(convertedSource.map)),
73045
+ generatedBuffer,
73046
+ sourceBuffer
73047
+ });
73048
+ sizeByLintPath.set(lintPath, sourceBuffer.length);
73049
+ astroFileIndex++;
73050
+ continue;
73051
+ }
73052
+ const { executableScriptBodies, lintBuffer } = prepareHtmlScriptSource(sourceBuffer);
73053
+ if (htmlFileIndex === 0) NFS.mkdirSync(htmlSourcesDirectory, { recursive: true });
73054
+ const lintPath = Path.join(htmlSourcesDirectory, `${htmlFileIndex}.astro`);
73055
+ NFS.writeFileSync(lintPath, lintBuffer);
73056
+ lintFiles.push(lintPath);
73057
+ sourcePathByLintPath.set(Path.resolve(lintPath), candidateFile);
73058
+ sizeByLintPath.set(lintPath, sourceBuffer.length);
73059
+ hasThreeModuleImport ||= executableScriptBodies.some((scriptBody) => containsThreeModuleImport(scriptBody.toString("utf8")));
73060
+ htmlFileIndex++;
73061
+ }
73062
+ return {
73063
+ lintFiles,
73064
+ sourcePathByLintPath,
73065
+ sourceMapByLintPath,
73066
+ sizeByLintPath,
73067
+ hasThreeModuleImport
73068
+ };
73069
+ };
71513
73070
  /**
71514
73071
  * Atomically (re)writes the generated oxlintrc.json. Used twice in
71515
73072
  * the runner: once for the primary scan, once for the
@@ -71670,6 +73227,8 @@ const reactHooksJsPluginDropNote = (error) => {
71670
73227
  const runOxlint = async (options) => {
71671
73228
  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;
71672
73229
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
73230
+ const runtimeGlobals = Array.isArray(userConfig?.runtimeGlobals) ? userConfig.runtimeGlobals.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
73231
+ let unpluginAutoImportGlobalScopes = [];
71673
73232
  const severityControls = buildRuleSeverityControls(userConfig);
71674
73233
  validateRuleRegistration();
71675
73234
  resetManifestCaches();
@@ -71683,21 +73242,6 @@ const runOxlint = async (options) => {
71683
73242
  const pluginPath = resolvePluginPath();
71684
73243
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
71685
73244
  const userPlugins = includedTags.size > 0 ? [] : resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
71686
- const buildConfig = (overrides) => createOxlintConfig({
71687
- pluginPath,
71688
- project,
71689
- customRulesOnly,
71690
- extendsPaths: overrides.extendsPaths,
71691
- ignoredTags,
71692
- includedTags,
71693
- includeTagDefaults,
71694
- serverAuthFunctionNames,
71695
- severityControls,
71696
- userPlugins,
71697
- disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
71698
- ruleSelection: overrides.ruleSelection,
71699
- sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
71700
- });
71701
73245
  const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
71702
73246
  const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
71703
73247
  const configPath = Path.join(configDirectory, "oxlintrc.json");
@@ -71733,7 +73277,36 @@ const runOxlint = async (options) => {
71733
73277
  await yieldToEventLoop();
71734
73278
  const sizedScanFiles = includePaths === void 0 ? listSourceFilesWithSize(rootDirectory) : null;
71735
73279
  const candidateFiles = includePaths !== void 0 ? includePaths : (sizedScanFiles ?? []).map((entry) => entry.path);
73280
+ unpluginAutoImportGlobalScopes = collectUnpluginAutoImportGlobalScopes({
73281
+ rootDirectory,
73282
+ candidateFiles
73283
+ });
73284
+ const preparedLintSources = prepareLintSources(rootDirectory, configDirectory, candidateFiles);
73285
+ const lintFiles = preparedLintSources.lintFiles;
73286
+ const hasPreparedFiles = preparedLintSources.sourcePathByLintPath.size > 0;
73287
+ const lintProject = !project.hasThree && preparedLintSources.hasThreeModuleImport ? {
73288
+ ...project,
73289
+ hasThree: true
73290
+ } : project;
73291
+ const buildConfig = (overrides) => createOxlintConfig({
73292
+ pluginPath,
73293
+ project: lintProject,
73294
+ customRulesOnly,
73295
+ extendsPaths: overrides.extendsPaths,
73296
+ ignoredTags,
73297
+ includedTags,
73298
+ includeTagDefaults,
73299
+ runtimeGlobals,
73300
+ unpluginAutoImportGlobalScopes,
73301
+ serverAuthFunctionNames,
73302
+ severityControls,
73303
+ userPlugins,
73304
+ disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
73305
+ ruleSelection: overrides.ruleSelection,
73306
+ sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
73307
+ });
71736
73308
  const sizeByFile = sizedScanFiles !== null && lintBatchOrdering === "cost" ? new Map(sizedScanFiles.map((entry) => [entry.path, entry.sizeBytes])) : null;
73309
+ if (sizeByFile !== null) for (const [lintPath, sizeBytes] of preparedLintSources.sizeByLintPath) sizeByFile.set(lintPath, sizeBytes);
71737
73310
  const buildFileBatches = (passBaseArgs, passFiles) => sizeByFile !== null ? planLintBatches({
71738
73311
  baseArgs: passBaseArgs,
71739
73312
  files: passFiles,
@@ -71762,7 +73335,9 @@ const runOxlint = async (options) => {
71762
73335
  fileBatches: passFileBatches,
71763
73336
  rootDirectory,
71764
73337
  nodeBinaryPath,
71765
- project,
73338
+ project: lintProject,
73339
+ sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
73340
+ sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
71766
73341
  onPartialFailure: reportPartialFailure,
71767
73342
  onAnalyzedFiles: (filePaths) => {
71768
73343
  analyzedFiles = filePaths;
@@ -71771,6 +73346,7 @@ const runOxlint = async (options) => {
71771
73346
  spawnTimeoutMs,
71772
73347
  outputMaxBytes,
71773
73348
  concurrency: options.concurrency,
73349
+ spawnSlots: options.spawnSlots,
71774
73350
  signal: options.signal,
71775
73351
  deadlineEpochMs: options.deadlineEpochMs
71776
73352
  });
@@ -71797,7 +73373,7 @@ const runOxlint = async (options) => {
71797
73373
  };
71798
73374
  }
71799
73375
  };
71800
- if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0) {
73376
+ if (perFileLintCacheEnabled && !project.hasReactCompiler && project.hasReactCompilerLintPlugin !== true && extendsPaths.length === 0 && userPlugins.length === 0 && !hasPreparedFiles) {
71801
73377
  const rulesetHash = computeRulesetHash({
71802
73378
  config: buildConfig({
71803
73379
  extendsPaths: [],
@@ -71955,14 +73531,16 @@ const runOxlint = async (options) => {
71955
73531
  ]);
71956
73532
  }
71957
73533
  const baseArgs = makeBaseArgs(configPath);
71958
- const fileBatches = buildFileBatches(baseArgs, candidateFiles);
73534
+ const fileBatches = buildFileBatches(baseArgs, lintFiles);
71959
73535
  let analyzedFiles = [];
71960
73536
  const runBatches = () => spawnLintBatches({
71961
73537
  baseArgs,
71962
73538
  fileBatches,
71963
73539
  rootDirectory,
71964
73540
  nodeBinaryPath,
71965
- project,
73541
+ project: lintProject,
73542
+ sourcePathByLintPath: preparedLintSources.sourcePathByLintPath,
73543
+ sourceMapByLintPath: preparedLintSources.sourceMapByLintPath,
71966
73544
  onPartialFailure,
71967
73545
  onAnalyzedFiles: (filePaths) => {
71968
73546
  analyzedFiles = filePaths;
@@ -71971,6 +73549,7 @@ const runOxlint = async (options) => {
71971
73549
  spawnTimeoutMs,
71972
73550
  outputMaxBytes,
71973
73551
  concurrency: options.concurrency,
73552
+ spawnSlots: options.spawnSlots,
71974
73553
  signal: options.signal,
71975
73554
  deadlineEpochMs: options.deadlineEpochMs
71976
73555
  });
@@ -72065,6 +73644,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
72065
73644
  const spawnTimeoutMs = yield* OxlintSpawnTimeoutMs;
72066
73645
  const outputMaxBytes = yield* OxlintOutputMaxBytes;
72067
73646
  const concurrency = yield* OxlintConcurrency;
73647
+ const spawnSlots = yield* OxlintSpawnSlots;
72068
73648
  const lintBatchOrdering = yield* LintBatchOrdering;
72069
73649
  const perFileLintCacheEnabled = yield* PerFileLintCacheEnabled;
72070
73650
  const sidecarLintCacheEnabled = yield* SidecarLintCacheEnabled;
@@ -72094,6 +73674,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
72094
73674
  onSidecarStats: input.onSidecarStats,
72095
73675
  spawnTimeoutMs,
72096
73676
  outputMaxBytes,
73677
+ spawnSlots: spawnSlots ?? void 0,
72097
73678
  concurrency,
72098
73679
  signal,
72099
73680
  lintBatchOrdering,
@@ -73311,10 +74892,14 @@ const materializeSourceTree = (input) => gen(function* () {
73311
74892
  materializedFiles.push(relativePath);
73312
74893
  }
73313
74894
  yield* sync(() => {
73314
- for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
73315
- const sourcePath = path.join(input.directory, configFilename);
73316
- const targetPath = path.join(resolvedTempDirectory, configFilename);
73317
- if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) fs.cpSync(sourcePath, targetPath);
74895
+ for (const subdirectory of ["", ...input.configSubdirectories ?? []]) for (const configFilename of STAGED_FILES_PROJECT_CONFIG_FILENAMES) {
74896
+ const sourcePath = path.join(input.directory, subdirectory, configFilename);
74897
+ const targetPath = path.resolve(resolvedTempDirectory, subdirectory, configFilename);
74898
+ if (!isPathInsideDirectory(targetPath, resolvedTempDirectory)) continue;
74899
+ if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) {
74900
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
74901
+ fs.cpSync(sourcePath, targetPath);
74902
+ }
73318
74903
  }
73319
74904
  });
73320
74905
  return {
@@ -73335,15 +74920,17 @@ const materializeSourceTree = (input) => gen(function* () {
73335
74920
  static layerNode = effect(StagedFiles, gen(function* () {
73336
74921
  const git = yield* Git;
73337
74922
  return StagedFiles.of({
73338
- discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
73339
- materialize: ({ directory, stagedFiles, tempDirectory }) => materializeSourceTree({
74923
+ discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries === null ? null : entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
74924
+ materialize: ({ directory, stagedFiles, tempDirectory, configSubdirectories }) => materializeSourceTree({
73340
74925
  directory,
73341
74926
  files: stagedFiles,
73342
74927
  tempDirectory,
74928
+ configSubdirectories,
73343
74929
  readContent: (relativePath) => git.showStagedContent(directory, relativePath, { maxBufferBytes: GIT_SHOW_MAX_BUFFER_BYTES })
73344
74930
  }).pipe(map$3((tree) => ({
73345
74931
  tempDirectory: tree.tempDirectory,
73346
74932
  stagedFiles: tree.materializedFiles,
74933
+ unmaterializedFiles: tree.unmaterializedFiles,
73347
74934
  cleanup: tree.cleanup
73348
74935
  })), withSpan("StagedFiles.materialize"))
73349
74936
  });
@@ -73358,6 +74945,7 @@ const materializeSourceTree = (input) => gen(function* () {
73358
74945
  materialize: ({ tempDirectory }) => succeed$2({
73359
74946
  tempDirectory,
73360
74947
  stagedFiles: snapshot.materializedFiles ?? snapshot.sourceFiles ?? [],
74948
+ unmaterializedFiles: [],
73361
74949
  cleanup: () => {}
73362
74950
  })
73363
74951
  }));
@@ -73614,6 +75202,11 @@ const filterSourceFiles = (filePaths) => filePaths.filter(isLintableSourceFile);
73614
75202
  * other `clear*` helpers.
73615
75203
  */
73616
75204
  const clearAutoSuppressionCaches = () => {};
75205
+ const createLintPhaseAbortError = () => new ReactDoctorError({ reason: new OxlintSpawnFailed({ cause: "lint phase aborted" }) });
75206
+ const createOxlintSpawnSlots = (concurrency) => createWorkerSlots({
75207
+ slotCount: resolveScanConcurrency(concurrency),
75208
+ createAbortError: createLintPhaseAbortError
75209
+ });
73617
75210
  /**
73618
75211
  * Identity helper for authoring a typed `doctor.config.{ts,js,mjs,cjs}`.
73619
75212
  * Gives editor autocomplete and type-checking for the config object without
@@ -73734,7 +75327,7 @@ const buildDiagnoseLayer = (input) => {
73734
75327
  resolvedDirectory: input.configOverrideTarget.resolvedDirectory,
73735
75328
  configSourceDirectory: input.configOverrideTarget.configSourceDirectory
73736
75329
  });
73737
- return mergeAll$1(Project.layerNode, configLayer, input.shouldRunDeadCode ? DeadCode.layerNode : DeadCode.layerOf([]), Files.layerNode, Git.layerNode, input.shouldRunLint ? Linter.layerOxlint : Linter.layerOf([]), LintPartialFailures.layerLive, Progress.layerNoop, Reporter.layerNoop, Score.layerHttp, input.config?.supplyChain?.enabled !== false ? SupplyChain.layerNode : SupplyChain.layerOf([]));
75330
+ return mergeAll$1(Project.layerNode, configLayer, input.shouldRunDeadCode ? DeadCode.layerNode : DeadCode.layerOf([]), Files.layerNode, Git.layerNode, input.shouldRunLint ? Linter.layerOxlint : Linter.layerOf([]), LintPartialFailures.layerLive, succeed$3(OxlintConcurrency, input.oxlintConcurrency), succeed$3(OxlintSpawnSlots, input.oxlintSpawnSlots), Progress.layerNoop, Reporter.layerNoop, Score.layerHttp, input.config?.supplyChain?.enabled !== false ? SupplyChain.layerNode : SupplyChain.layerOf([]));
73738
75331
  };
73739
75332
  const buildInspectProgram = (scanTarget, options, configOverride) => {
73740
75333
  const effectiveConfig = configOverride ?? scanTarget.userConfig;
@@ -73775,10 +75368,14 @@ const diagnoseDirectory = async (directory, options) => {
73775
75368
  const program = buildInspectProgram(scanTarget, options);
73776
75369
  const shouldRunLint = resolveShouldRunLint(options, scanTarget.userConfig);
73777
75370
  const shouldRunDeadCode = resolveShouldRunDeadCode(options, scanTarget.userConfig);
75371
+ const oxlintConcurrency = runSync(OxlintConcurrency);
75372
+ const oxlintSpawnSlots = createOxlintSpawnSlots(oxlintConcurrency);
73778
75373
  return outputToDiagnoseResult(await runPromise(restoreLegacyThrow(program.pipe(provide(buildDiagnoseLayer({
73779
75374
  config: scanTarget.userConfig,
73780
75375
  shouldRunLint,
73781
- shouldRunDeadCode
75376
+ shouldRunDeadCode,
75377
+ oxlintConcurrency,
75378
+ oxlintSpawnSlots
73782
75379
  })), provide(layerOtlp)))), globalThis.performance.now() - startTime);
73783
75380
  };
73784
75381
  const findWorstScore = (projectResults) => {
@@ -73793,7 +75390,7 @@ const findWorstScore = (projectResults) => {
73793
75390
  }
73794
75391
  return worstResult;
73795
75392
  };
73796
- const diagnoseProject = async (projectDefinition, baseOptions, batchConfig) => {
75393
+ const diagnoseProject = async (projectDefinition, baseOptions, batchConfig, oxlintConcurrency, oxlintSpawnSlots) => {
73797
75394
  const startTime = globalThis.performance.now();
73798
75395
  try {
73799
75396
  const scanTarget = await resolveScanTarget(projectDefinition.directory);
@@ -73812,6 +75409,8 @@ const diagnoseProject = async (projectDefinition, baseOptions, batchConfig) => {
73812
75409
  config: effectiveConfig,
73813
75410
  shouldRunLint,
73814
75411
  shouldRunDeadCode,
75412
+ oxlintConcurrency,
75413
+ oxlintSpawnSlots,
73815
75414
  configOverrideTarget: {
73816
75415
  resolvedDirectory: scanTarget.resolvedDirectory,
73817
75416
  configSourceDirectory: didOverridePlugins ? null : scanTarget.configSourceDirectory
@@ -73819,7 +75418,9 @@ const diagnoseProject = async (projectDefinition, baseOptions, batchConfig) => {
73819
75418
  } : {
73820
75419
  config: effectiveConfig,
73821
75420
  shouldRunLint,
73822
- shouldRunDeadCode
75421
+ shouldRunDeadCode,
75422
+ oxlintConcurrency,
75423
+ oxlintSpawnSlots
73823
75424
  });
73824
75425
  return {
73825
75426
  ok: true,
@@ -73838,7 +75439,9 @@ const diagnoseProjectBatch = async (input) => {
73838
75439
  warnIfAiTrainingEnvironment();
73839
75440
  const startTime = globalThis.performance.now();
73840
75441
  const { projects, concurrency, config: batchConfig, ...baseOptions } = input;
73841
- const projectResults = await mapWithConcurrency(projects, concurrency ?? 4, (projectDefinition) => diagnoseProject(projectDefinition, baseOptions, batchConfig));
75442
+ const oxlintConcurrency = runSync(OxlintConcurrency);
75443
+ const oxlintSpawnSlots = createOxlintSpawnSlots(oxlintConcurrency);
75444
+ const projectResults = await mapWithConcurrency(projects, concurrency ?? 4, (projectDefinition) => diagnoseProject(projectDefinition, baseOptions, batchConfig, oxlintConcurrency, oxlintSpawnSlots));
73842
75445
  const succeededProjects = projectResults.filter((projectResult) => projectResult.ok);
73843
75446
  return {
73844
75447
  projects: projectResults,
@@ -73884,4 +75487,4 @@ const toJsonReport = (result, options) => buildJsonReport({
73884
75487
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
73885
75488
 
73886
75489
  //# sourceMappingURL=index.js.map
73887
- //# debugId=eb93b210-c190-581c-8fe2-f1e1c70e0bab
75490
+ //# debugId=61d9689f-8ba5-5ca3-a0c2-09557d3f7028