react-doctor 0.9.13-dev.ff7dd67 → 0.9.14-dev.260b448
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/_react-doctor_require-typescript-DXQDYeWK.js +16 -0
- package/dist/{active-run-trace-dlIZeEvb.js → active-run-trace-Dewycxda.js} +3 -3
- package/dist/{active-scan-abort-registry-DwG6tSPy.js → active-scan-abort-registry-CCTgal0O.js} +3 -3
- package/dist/build-section-divider-gekJe2aO.js +81 -0
- package/dist/{ci-ByM_SFTq.js → ci-S43tmiRM.js} +14 -13
- package/dist/cli.js +31 -30
- package/dist/constants-CgtYeXfx.js +1035 -0
- package/dist/constants-DNh19qg9.js +23 -0
- package/dist/{design-2hjOmtV1.js → design-D4ctp88p.js} +4 -4
- package/dist/{devtools-CC2PAZ85.js → devtools-D20sefkm.js} +3 -3
- package/dist/duplicate-jsx-worker.d.ts +1 -0
- package/dist/duplicate-jsx-worker.js +636 -0
- package/dist/{exit-gracefully-niPFXq9Y.js → exit-gracefully-D69nyRA4.js} +7 -7
- package/dist/fs-utils-C88IbqFa.js +45 -0
- package/dist/{get-east-asian-width-Bv2TD3Xj.js → get-east-asian-width-DRPy7dqz.js} +4 -4
- package/dist/{handle-error-D-4lexec.js → handle-error-BE3O3Ugs.js} +6 -5
- package/dist/index.d.ts +8511 -8509
- package/dist/index.js +61693 -60580
- package/dist/{inspect-BrctG7ql.js → inspect-CKjzI6gB.js} +38 -27
- package/dist/{install-CcFc56OK.js → install-PndnbaOs.js} +10 -9
- package/dist/{install-doctor-script-Coa2ErCg.js → install-doctor-script-BAGTNvoL.js} +17 -8
- package/dist/{install-github-workflow-DlfdrYkQ.js → install-github-workflow-u0qIsWNy.js} +10 -10
- package/dist/{install-react-doctor-BWxqZMX-.js → install-react-doctor-D4nc_F4X.js} +15 -11
- package/dist/is-cache-globally-disabled-Bi2D2qVm.js +10 -0
- package/dist/{jsx-runtime-Njm7vAoN.js → jsx-runtime-DT94xKcX.js} +11 -10
- package/dist/oxlint-worker.d.ts +1 -0
- package/dist/oxlint-worker.js +225 -0
- package/dist/{path-format-DnHpmJwG.js → path-format-By20mo8A.js} +3 -3
- package/dist/{print-branded-header-DFkeG4BS.js → print-branded-header-BwVcjvPZ.js} +4 -4
- package/dist/project-analysis-worker.js +461 -480
- package/dist/{prompt-runtime-scan-url-BenBNq25.js → prompt-runtime-scan-url-Bjsn6chf.js} +6 -6
- package/dist/react-compiler-detection-worker.d.ts +1 -0
- package/dist/react-compiler-detection-worker.js +1029 -0
- package/dist/{read-object-file-CqMtxcfF.js → read-object-file-lnRYcs-x.js} +4 -4
- package/dist/{record-metric-Bkorhx43.js → record-metric-CQTcuE_T.js} +12998 -12770
- package/dist/{report-error-DPjmfRi9.js → report-error-DbKdfCEt.js} +9 -8
- package/dist/{report-workflow-result-CBL6CrLY.js → report-workflow-result-w7YFI8kv.js} +24 -11
- package/dist/{resolve-scope-BFloAClV.js → resolve-scope-qNuGZ908.js} +7 -7
- package/dist/{rules-BKNy9YIl.js → rules-ByH9CzFb.js} +8 -7
- package/dist/{run-scan-app-Bc70ozp-.js → run-scan-app-5khIAxD-.js} +30 -23
- package/dist/{runtime-scan-ODrdp5mV.js → runtime-scan-BuSOAA46.js} +13 -12
- package/dist/{sanitize-runtime-url-BYOmPSdm.js → sanitize-runtime-url-5kypdWqI.js} +4 -4
- package/dist/{scan-BfcGHHkI.js → scan-Cv_Bwsqc.js} +10 -9
- package/dist/{semver-DFtnEmN-.js → semver-BZIuy1gP.js} +3 -3
- package/dist/{should-fail-scan-gate-CCPDoHaM.js → should-fail-scan-gate-fan2kMeu.js} +1339 -1283
- package/dist/{should-skip-prompts-D-ClPHHR.js → should-skip-prompts-BbpOXwiH.js} +4 -4
- package/dist/{should-use-tui-BaCVIPPN.js → should-use-tui-CI612w4M.js} +4 -4
- package/dist/start-scan-preamble-DVB7vlit.js +68 -0
- package/dist/start-scan-preamble-DVhXIPc0.d.ts +1 -0
- package/dist/start-scan-preamble.d.ts +1 -0
- package/dist/start-scan-preamble.js +4 -0
- package/dist/{telemetry-runtime-BGWa_GB9.js → telemetry-runtime-CbJQ0K-c.js} +154 -5
- package/dist/{unref-stdin-SK3WfwxS.js → unref-stdin-D-NZBFpg.js} +3 -3
- package/dist/unwrap-typescript-expression-CrEPQUWz.js +14 -0
- package/dist/{version-DN1N-oZy.js → version-0CrqwW3U.js} +5 -4
- package/dist/{why-CyioXUF2.js → why-Bm4JpSPS.js} +4 -4
- package/dist/{with-run-span-GsCWW2_X.js → with-run-span-DF9i7MAa.js} +7 -6
- package/package.json +9 -7
- package/dist/build-section-divider-BRuN44fL.js +0 -216
|
@@ -0,0 +1,636 @@
|
|
|
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]="3fb1e6c0-870e-54f2-9dd3-ef90f8a0c9bf")}catch(e){}}();
|
|
3
|
+
import { t as typescriptBinding } from "./_react-doctor_require-typescript-DXQDYeWK.js";
|
|
4
|
+
import { t as unwrapTypescriptExpression } from "./unwrap-typescript-expression-CrEPQUWz.js";
|
|
5
|
+
import { i as JSX_DUPLICATION_SOURCE_FILE_PATTERN } from "./constants-DNh19qg9.js";
|
|
6
|
+
import * as fs$2 from "node:fs";
|
|
7
|
+
import * as path$1 from "node:path";
|
|
8
|
+
import crypto from "node:crypto";
|
|
9
|
+
import { parentPort } from "node:worker_threads";
|
|
10
|
+
import * as fs$1 from "node:fs/promises";
|
|
11
|
+
//#region ../core/src/utils/resolve-bounded-source-read-bytes.ts
|
|
12
|
+
const resolveBoundedSourceReadBytes = (maximumLengthChars, sizeBytes) => Math.min(sizeBytes, maximumLengthChars * 3 + 1);
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region ../core/src/utils/read-text-file-up-to-character-limit-sync.ts
|
|
15
|
+
const readTextFileUpToCharacterLimitSync = (input) => {
|
|
16
|
+
const buffer = Buffer.allocUnsafe(resolveBoundedSourceReadBytes(input.maximumLengthChars, input.sizeBytes));
|
|
17
|
+
const fileDescriptor = fs$2.openSync(input.filePath, "r");
|
|
18
|
+
let readOffset = 0;
|
|
19
|
+
try {
|
|
20
|
+
while (readOffset < buffer.length) {
|
|
21
|
+
const bytesRead = fs$2.readSync(fileDescriptor, buffer, readOffset, buffer.length - readOffset, readOffset);
|
|
22
|
+
if (bytesRead === 0) break;
|
|
23
|
+
readOffset += bytesRead;
|
|
24
|
+
}
|
|
25
|
+
} finally {
|
|
26
|
+
fs$2.closeSync(fileDescriptor);
|
|
27
|
+
}
|
|
28
|
+
return buffer.subarray(0, readOffset).toString("utf-8");
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region ../core/src/utils/read-text-file-up-to-character-limit.ts
|
|
32
|
+
const readTextFileUpToCharacterLimit = async (input) => {
|
|
33
|
+
const buffer = Buffer.allocUnsafe(resolveBoundedSourceReadBytes(input.maximumLengthChars, input.sizeBytes));
|
|
34
|
+
const fileHandle = await fs$1.open(input.filePath, "r");
|
|
35
|
+
let readOffset = 0;
|
|
36
|
+
try {
|
|
37
|
+
while (readOffset < buffer.length) {
|
|
38
|
+
input.signal?.throwIfAborted();
|
|
39
|
+
const { bytesRead } = await fileHandle.read(buffer, readOffset, buffer.length - readOffset, readOffset);
|
|
40
|
+
if (bytesRead === 0) break;
|
|
41
|
+
readOffset += bytesRead;
|
|
42
|
+
}
|
|
43
|
+
} finally {
|
|
44
|
+
await fileHandle.close();
|
|
45
|
+
}
|
|
46
|
+
input.signal?.throwIfAborted();
|
|
47
|
+
return buffer.subarray(0, readOffset).toString("utf-8");
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region ../core/src/react-cleanup/create-jsx-source-reader.ts
|
|
51
|
+
const readBlocking = (absolutePath, maximumLengthChars, sizeBytes) => new Promise((resolve) => {
|
|
52
|
+
resolve(sizeBytes <= maximumLengthChars ? fs$2.readFileSync(absolutePath, "utf-8") : readTextFileUpToCharacterLimitSync({
|
|
53
|
+
filePath: absolutePath,
|
|
54
|
+
maximumLengthChars,
|
|
55
|
+
sizeBytes
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
const createJsxSourceReader = (input) => {
|
|
59
|
+
const sourceSizeByPath = new Map(input.sourceFiles.map((sourceFile) => [sourceFile.path, sourceFile.sizeBytes]));
|
|
60
|
+
return {
|
|
61
|
+
paths: [...sourceSizeByPath.keys()],
|
|
62
|
+
read: (filePath, maximumLengthChars) => {
|
|
63
|
+
const absolutePath = path$1.resolve(input.rootDirectory, filePath);
|
|
64
|
+
const sourceSizeBytes = sourceSizeByPath.get(filePath) ?? 0;
|
|
65
|
+
if (input.useBlockingReads === true) return readBlocking(absolutePath, maximumLengthChars, sourceSizeBytes);
|
|
66
|
+
return sourceSizeBytes <= maximumLengthChars ? fs$1.readFile(absolutePath, {
|
|
67
|
+
encoding: "utf-8",
|
|
68
|
+
signal: input.signal
|
|
69
|
+
}) : readTextFileUpToCharacterLimit({
|
|
70
|
+
filePath: absolutePath,
|
|
71
|
+
maximumLengthChars,
|
|
72
|
+
sizeBytes: sourceSizeBytes,
|
|
73
|
+
signal: input.signal
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region ../core/src/utils/get-typescript-script-kind.ts
|
|
80
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
81
|
+
if (fileName.endsWith(".tsx")) return typescriptBinding.ScriptKind.TSX;
|
|
82
|
+
if (fileName.endsWith(".jsx")) return typescriptBinding.ScriptKind.JSX;
|
|
83
|
+
if (fileName.endsWith(".ts")) return typescriptBinding.ScriptKind.TS;
|
|
84
|
+
return typescriptBinding.ScriptKind.JS;
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region ../core/src/utils/yield-to-event-loop.ts
|
|
88
|
+
const yieldToEventLoop = () => new Promise((resolve) => {
|
|
89
|
+
setImmediate(resolve);
|
|
90
|
+
});
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region ../core/src/react-cleanup/utils/is-non-react-jsx-source.ts
|
|
93
|
+
const NON_REACT_JSX_RUNTIME_PREFIXES = ["solid-js", "@builder.io/qwik"];
|
|
94
|
+
const NON_REACT_JSX_RUNTIME_PACKAGES = new Set(["voby", "vidode"]);
|
|
95
|
+
const REACT_JSX_RUNTIME_PREFIXES = [
|
|
96
|
+
"react",
|
|
97
|
+
"react-dom",
|
|
98
|
+
"preact"
|
|
99
|
+
];
|
|
100
|
+
const matchesPackagePrefix = (source, prefixes) => prefixes.some((prefix) => source === prefix || source.startsWith(`${prefix}/`));
|
|
101
|
+
const importDeclarationHasRuntimeValue = (declaration) => {
|
|
102
|
+
const importClause = declaration.importClause;
|
|
103
|
+
if (!importClause) return true;
|
|
104
|
+
if (importClause.isTypeOnly) return false;
|
|
105
|
+
if (importClause.name || !importClause.namedBindings) return true;
|
|
106
|
+
if (typescriptBinding.isNamespaceImport(importClause.namedBindings)) return true;
|
|
107
|
+
return importClause.namedBindings.elements.some((element) => !element.isTypeOnly);
|
|
108
|
+
};
|
|
109
|
+
const openingElementHasNonReactMarker = (openingElement) => openingElement.attributes.properties.some((attribute) => {
|
|
110
|
+
if (!typescriptBinding.isJsxAttribute(attribute)) return false;
|
|
111
|
+
if (typescriptBinding.isJsxNamespacedName(attribute.name)) return attribute.name.namespace.text === "class" || attribute.name.namespace.text === "bind";
|
|
112
|
+
if (attribute.name.text !== "classList" || !attribute.initializer) return false;
|
|
113
|
+
return typescriptBinding.isJsxExpression(attribute.initializer) && attribute.initializer.expression !== void 0 && typescriptBinding.isObjectLiteralExpression(attribute.initializer.expression);
|
|
114
|
+
});
|
|
115
|
+
const NON_REACT_RUNTIME_SOURCE_TEXT_MARKERS = [
|
|
116
|
+
...NON_REACT_JSX_RUNTIME_PREFIXES,
|
|
117
|
+
...NON_REACT_JSX_RUNTIME_PACKAGES,
|
|
118
|
+
"classList"
|
|
119
|
+
];
|
|
120
|
+
const NAMESPACED_ATTRIBUTE_MARKER_PATTERN = /\b(?:class|bind)\s*:/;
|
|
121
|
+
const ESCAPED_MODULE_SPECIFIER_PATTERN = /(?:import|from)\s*["'][^"'\n]*\\/;
|
|
122
|
+
const mayContainNonReactMarker = (sourceText) => NON_REACT_RUNTIME_SOURCE_TEXT_MARKERS.some((marker) => sourceText.includes(marker)) || NAMESPACED_ATTRIBUTE_MARKER_PATTERN.test(sourceText) || ESCAPED_MODULE_SPECIFIER_PATTERN.test(sourceText);
|
|
123
|
+
const isNonReactJsxSource = (sourceFile) => {
|
|
124
|
+
if (!mayContainNonReactMarker(sourceFile.text)) return false;
|
|
125
|
+
let hasNonReactRuntime = false;
|
|
126
|
+
let hasReactRuntime = false;
|
|
127
|
+
let hasNonReactMarker = false;
|
|
128
|
+
const visitNode = (node) => {
|
|
129
|
+
if (typescriptBinding.isImportDeclaration(node) && importDeclarationHasRuntimeValue(node)) {
|
|
130
|
+
const source = typescriptBinding.isStringLiteral(node.moduleSpecifier) ? node.moduleSpecifier.text : "";
|
|
131
|
+
if (NON_REACT_JSX_RUNTIME_PACKAGES.has(source) || matchesPackagePrefix(source, NON_REACT_JSX_RUNTIME_PREFIXES)) hasNonReactRuntime = true;
|
|
132
|
+
if (matchesPackagePrefix(source, REACT_JSX_RUNTIME_PREFIXES)) hasReactRuntime = true;
|
|
133
|
+
}
|
|
134
|
+
if ((typescriptBinding.isJsxOpeningElement(node) || typescriptBinding.isJsxSelfClosingElement(node)) && openingElementHasNonReactMarker(node)) hasNonReactMarker = true;
|
|
135
|
+
typescriptBinding.forEachChild(node, visitNode);
|
|
136
|
+
};
|
|
137
|
+
visitNode(sourceFile);
|
|
138
|
+
return !hasReactRuntime && (hasNonReactRuntime || hasNonReactMarker);
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region ../core/src/react-cleanup/detect-duplicate-jsx-subtrees.ts
|
|
142
|
+
const isJsxSubtreeNode = (node) => typescriptBinding.isJsxElement(node) || typescriptBinding.isJsxSelfClosingElement(node) || typescriptBinding.isJsxFragment(node);
|
|
143
|
+
const resolveOptions = (options) => ({
|
|
144
|
+
minimumNodeCount: options.minimumNodeCount ?? 6,
|
|
145
|
+
minimumDepth: options.minimumDepth ?? 3,
|
|
146
|
+
minimumOccurrences: options.minimumOccurrences ?? 2,
|
|
147
|
+
minimumDistinctFiles: options.minimumDistinctFiles ?? 1,
|
|
148
|
+
maxSourceFiles: options.budget?.maxSourceFiles ?? 5e3,
|
|
149
|
+
maxSourceLengthChars: options.budget?.maxSourceLengthChars ?? 1e6,
|
|
150
|
+
maxJsxNodes: options.budget?.maxJsxNodes ?? 5e4,
|
|
151
|
+
maxFamilies: options.budget?.maxFamilies ?? 20
|
|
152
|
+
});
|
|
153
|
+
const hashParts = (parts) => {
|
|
154
|
+
let framedParts = "";
|
|
155
|
+
for (const part of parts) framedParts += `${part.length}:${part}`;
|
|
156
|
+
return crypto.hash("sha256", framedParts, "hex");
|
|
157
|
+
};
|
|
158
|
+
const collectDirectJsxDescendants = (node) => {
|
|
159
|
+
const descendants = [];
|
|
160
|
+
const pendingNodes = [];
|
|
161
|
+
typescriptBinding.forEachChild(node, (child) => {
|
|
162
|
+
pendingNodes.push(child);
|
|
163
|
+
});
|
|
164
|
+
while (pendingNodes.length > 0) {
|
|
165
|
+
const currentNode = pendingNodes.pop();
|
|
166
|
+
if (currentNode === void 0) continue;
|
|
167
|
+
if (isJsxSubtreeNode(currentNode)) {
|
|
168
|
+
descendants.push(currentNode);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
typescriptBinding.forEachChild(currentNode, (child) => {
|
|
172
|
+
pendingNodes.push(child);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return descendants;
|
|
176
|
+
};
|
|
177
|
+
const buildStructuralHash = (node, metadataByNode) => {
|
|
178
|
+
if (isJsxSubtreeNode(node)) return buildJsxSubtreeMetadata(node, metadataByNode).fingerprint;
|
|
179
|
+
if (typescriptBinding.isJsxText(node)) return node.getText().trim().length === 0 ? "jsx-whitespace" : "jsx-text";
|
|
180
|
+
if (typescriptBinding.isPropertyAccessExpression(node)) return hashParts([
|
|
181
|
+
"property-access",
|
|
182
|
+
node.questionDotToken === void 0 ? "required" : "optional",
|
|
183
|
+
buildStructuralHash(node.expression, metadataByNode),
|
|
184
|
+
node.name.text
|
|
185
|
+
]);
|
|
186
|
+
if (typescriptBinding.isElementAccessExpression(node)) {
|
|
187
|
+
const argumentHash = typescriptBinding.isStringLiteral(node.argumentExpression) || typescriptBinding.isNumericLiteral(node.argumentExpression) ? `${typescriptBinding.SyntaxKind[node.argumentExpression.kind]}:${node.argumentExpression.text}` : buildStructuralHash(node.argumentExpression, metadataByNode);
|
|
188
|
+
return hashParts([
|
|
189
|
+
"element-access",
|
|
190
|
+
node.questionDotToken === void 0 ? "required" : "optional",
|
|
191
|
+
buildStructuralHash(node.expression, metadataByNode),
|
|
192
|
+
argumentHash
|
|
193
|
+
]);
|
|
194
|
+
}
|
|
195
|
+
if (typescriptBinding.isBinaryExpression(node)) return hashParts([
|
|
196
|
+
"binary-expression",
|
|
197
|
+
typescriptBinding.SyntaxKind[node.operatorToken.kind],
|
|
198
|
+
buildStructuralHash(node.left, metadataByNode),
|
|
199
|
+
buildStructuralHash(node.right, metadataByNode)
|
|
200
|
+
]);
|
|
201
|
+
if (typescriptBinding.isPrefixUnaryExpression(node) || typescriptBinding.isPostfixUnaryExpression(node)) return hashParts([
|
|
202
|
+
typescriptBinding.SyntaxKind[node.kind],
|
|
203
|
+
typescriptBinding.SyntaxKind[node.operator],
|
|
204
|
+
buildStructuralHash(node.operand, metadataByNode)
|
|
205
|
+
]);
|
|
206
|
+
if (typescriptBinding.isIdentifier(node)) return "identifier";
|
|
207
|
+
if (typescriptBinding.isStringLiteral(node) || typescriptBinding.isNumericLiteral(node) || typescriptBinding.isNoSubstitutionTemplateLiteral(node) || typescriptBinding.isRegularExpressionLiteral(node)) return typescriptBinding.SyntaxKind[node.kind];
|
|
208
|
+
if (typescriptBinding.isJsxAttribute(node)) {
|
|
209
|
+
let initializerHash = "present";
|
|
210
|
+
if (node.initializer !== void 0) if (typescriptBinding.isStringLiteral(node.initializer)) initializerHash = `string:${node.initializer.text}`;
|
|
211
|
+
else if (typescriptBinding.isJsxExpression(node.initializer) && node.initializer.expression !== void 0 && (typescriptBinding.isStringLiteral(node.initializer.expression) || typescriptBinding.isNumericLiteral(node.initializer.expression) || node.initializer.expression.kind === typescriptBinding.SyntaxKind.TrueKeyword || node.initializer.expression.kind === typescriptBinding.SyntaxKind.FalseKeyword || node.initializer.expression.kind === typescriptBinding.SyntaxKind.NullKeyword)) initializerHash = `static:${node.initializer.expression.getText()}`;
|
|
212
|
+
else initializerHash = buildStructuralHash(node.initializer, metadataByNode);
|
|
213
|
+
return hashParts([
|
|
214
|
+
"attribute",
|
|
215
|
+
node.name.getText(),
|
|
216
|
+
initializerHash
|
|
217
|
+
]);
|
|
218
|
+
}
|
|
219
|
+
if (typescriptBinding.isPropertyAssignment(node)) return hashParts([
|
|
220
|
+
"property-assignment",
|
|
221
|
+
node.name.getText(),
|
|
222
|
+
buildStructuralHash(node.initializer, metadataByNode)
|
|
223
|
+
]);
|
|
224
|
+
if (typescriptBinding.isShorthandPropertyAssignment(node)) return hashParts(["shorthand-property", node.name.text]);
|
|
225
|
+
if (typescriptBinding.isJsxSpreadAttribute(node)) return hashParts(["spread", buildStructuralHash(node.expression, metadataByNode)]);
|
|
226
|
+
const childHashes = [];
|
|
227
|
+
typescriptBinding.forEachChild(node, (child) => {
|
|
228
|
+
childHashes.push(buildStructuralHash(child, metadataByNode));
|
|
229
|
+
});
|
|
230
|
+
return hashParts([typescriptBinding.SyntaxKind[node.kind], ...childHashes]);
|
|
231
|
+
};
|
|
232
|
+
const buildJsxSubtreeMetadata = (node, metadataByNode) => {
|
|
233
|
+
const existingMetadata = metadataByNode.get(node);
|
|
234
|
+
if (existingMetadata) return existingMetadata;
|
|
235
|
+
const descendantMetadata = collectDirectJsxDescendants(node).map((descendant) => buildJsxSubtreeMetadata(descendant, metadataByNode));
|
|
236
|
+
const nodeParts = [typescriptBinding.SyntaxKind[node.kind]];
|
|
237
|
+
if (typescriptBinding.isJsxElement(node)) nodeParts.push(node.openingElement.tagName.getText());
|
|
238
|
+
else if (typescriptBinding.isJsxSelfClosingElement(node)) nodeParts.push(node.tagName.getText());
|
|
239
|
+
else nodeParts.push("fragment");
|
|
240
|
+
typescriptBinding.forEachChild(node, (child) => {
|
|
241
|
+
if (typescriptBinding.isJsxClosingElement(child) || typescriptBinding.isJsxClosingFragment(child)) return;
|
|
242
|
+
if (typescriptBinding.isJsxText(child) && child.getText().trim().length === 0) return;
|
|
243
|
+
if (typescriptBinding.isJsxExpression(child) && child.expression === void 0) return;
|
|
244
|
+
nodeParts.push(buildStructuralHash(child, metadataByNode));
|
|
245
|
+
});
|
|
246
|
+
const metadata = {
|
|
247
|
+
fingerprint: `jsx:${hashParts(nodeParts)}`,
|
|
248
|
+
nodeCount: 1 + descendantMetadata.reduce((total, descendant) => total + descendant.nodeCount, 0),
|
|
249
|
+
depth: 1 + descendantMetadata.reduce((maximum, descendant) => Math.max(maximum, descendant.depth), 0)
|
|
250
|
+
};
|
|
251
|
+
metadataByNode.set(node, metadata);
|
|
252
|
+
return metadata;
|
|
253
|
+
};
|
|
254
|
+
const getRootName = (node) => {
|
|
255
|
+
if (typescriptBinding.isJsxElement(node)) return node.openingElement.tagName.getText();
|
|
256
|
+
if (typescriptBinding.isJsxSelfClosingElement(node)) return node.tagName.getText();
|
|
257
|
+
return "Fragment";
|
|
258
|
+
};
|
|
259
|
+
const getFunctionIdentity = (node, identityByNode) => {
|
|
260
|
+
if (identityByNode.has(node)) return identityByNode.get(node) ?? null;
|
|
261
|
+
const traversedNodes = [node];
|
|
262
|
+
let currentNode = node.parent;
|
|
263
|
+
let functionIdentity = null;
|
|
264
|
+
while (currentNode !== void 0) {
|
|
265
|
+
if (identityByNode.has(currentNode)) {
|
|
266
|
+
functionIdentity = identityByNode.get(currentNode) ?? null;
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
traversedNodes.push(currentNode);
|
|
270
|
+
if (typescriptBinding.isFunctionDeclaration(currentNode)) {
|
|
271
|
+
if (currentNode.name !== void 0) {
|
|
272
|
+
functionIdentity = {
|
|
273
|
+
name: currentNode.name.text,
|
|
274
|
+
startOffset: currentNode.getStart()
|
|
275
|
+
};
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
if (typescriptBinding.getModifiers(currentNode)?.some((modifier) => modifier.kind === typescriptBinding.SyntaxKind.DefaultKeyword)) {
|
|
279
|
+
functionIdentity = {
|
|
280
|
+
name: "default export",
|
|
281
|
+
startOffset: currentNode.getStart()
|
|
282
|
+
};
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (typescriptBinding.isMethodDeclaration(currentNode)) {
|
|
287
|
+
const classDeclaration = currentNode.parent;
|
|
288
|
+
if (typescriptBinding.isClassDeclaration(classDeclaration) && classDeclaration.name !== void 0) {
|
|
289
|
+
functionIdentity = {
|
|
290
|
+
name: classDeclaration.name.text,
|
|
291
|
+
startOffset: classDeclaration.getStart()
|
|
292
|
+
};
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
functionIdentity = {
|
|
296
|
+
name: currentNode.name.getText(),
|
|
297
|
+
startOffset: currentNode.getStart()
|
|
298
|
+
};
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
if (typescriptBinding.isFunctionExpression(currentNode) && currentNode.name !== void 0) {
|
|
302
|
+
functionIdentity = {
|
|
303
|
+
name: currentNode.name.text,
|
|
304
|
+
startOffset: currentNode.getStart()
|
|
305
|
+
};
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
if (typescriptBinding.isArrowFunction(currentNode) || typescriptBinding.isFunctionExpression(currentNode)) {
|
|
309
|
+
let assignmentNode = currentNode.parent;
|
|
310
|
+
while (assignmentNode !== void 0 && (typescriptBinding.isCallExpression(assignmentNode) || typescriptBinding.isExpressionWithTypeArguments(assignmentNode) || typescriptBinding.isExpression(assignmentNode) && unwrapTypescriptExpression(assignmentNode) !== assignmentNode)) assignmentNode = assignmentNode.parent;
|
|
311
|
+
if (assignmentNode !== void 0 && typescriptBinding.isVariableDeclaration(assignmentNode)) {
|
|
312
|
+
functionIdentity = {
|
|
313
|
+
name: assignmentNode.name.getText(),
|
|
314
|
+
startOffset: assignmentNode.getStart()
|
|
315
|
+
};
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
if (assignmentNode !== void 0 && typescriptBinding.isPropertyAssignment(assignmentNode)) {
|
|
319
|
+
functionIdentity = {
|
|
320
|
+
name: assignmentNode.name.getText(),
|
|
321
|
+
startOffset: assignmentNode.getStart()
|
|
322
|
+
};
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
if (assignmentNode !== void 0 && typescriptBinding.isExportAssignment(assignmentNode) && !assignmentNode.isExportEquals) {
|
|
326
|
+
functionIdentity = {
|
|
327
|
+
name: "default export",
|
|
328
|
+
startOffset: assignmentNode.getStart()
|
|
329
|
+
};
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
currentNode = currentNode.parent;
|
|
334
|
+
}
|
|
335
|
+
for (const traversedNode of traversedNodes) identityByNode.set(traversedNode, functionIdentity);
|
|
336
|
+
return functionIdentity;
|
|
337
|
+
};
|
|
338
|
+
const buildOccurrence = (path, sourceFile, node, ancestorRootNames, functionIdentityByNode) => {
|
|
339
|
+
const startOffset = node.getStart(sourceFile);
|
|
340
|
+
const endOffset = node.getEnd();
|
|
341
|
+
const start = sourceFile.getLineAndCharacterOfPosition(startOffset);
|
|
342
|
+
const end = sourceFile.getLineAndCharacterOfPosition(endOffset);
|
|
343
|
+
const functionIdentity = getFunctionIdentity(node, functionIdentityByNode);
|
|
344
|
+
const compositionPath = [...ancestorRootNames, getRootName(node)];
|
|
345
|
+
if (functionIdentity !== null) compositionPath.unshift(functionIdentity.name);
|
|
346
|
+
return {
|
|
347
|
+
path,
|
|
348
|
+
startOffset,
|
|
349
|
+
endOffset,
|
|
350
|
+
startLine: start.line + 1,
|
|
351
|
+
startColumn: start.character + 1,
|
|
352
|
+
endLine: end.line + 1,
|
|
353
|
+
endColumn: end.character + 1,
|
|
354
|
+
rootName: getRootName(node),
|
|
355
|
+
parentRootName: ancestorRootNames.at(-1) ?? null,
|
|
356
|
+
compositionPath,
|
|
357
|
+
compositionRootStartOffset: functionIdentity?.startOffset ?? null
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
const collectCandidates = (source, sourceFile, signal, maximumCandidateCount) => {
|
|
361
|
+
const jsxNodes = [];
|
|
362
|
+
const pendingNodes = [sourceFile];
|
|
363
|
+
let limitExceeded = false;
|
|
364
|
+
while (pendingNodes.length > 0 && !limitExceeded && !signal?.aborted) {
|
|
365
|
+
const currentNode = pendingNodes.pop();
|
|
366
|
+
if (currentNode === void 0) continue;
|
|
367
|
+
if (isJsxSubtreeNode(currentNode)) {
|
|
368
|
+
if (jsxNodes.length >= maximumCandidateCount) {
|
|
369
|
+
limitExceeded = true;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
jsxNodes.push(currentNode);
|
|
373
|
+
}
|
|
374
|
+
const childNodes = [];
|
|
375
|
+
typescriptBinding.forEachChild(currentNode, (child) => {
|
|
376
|
+
childNodes.push(child);
|
|
377
|
+
});
|
|
378
|
+
for (let childIndex = childNodes.length - 1; childIndex >= 0; childIndex -= 1) pendingNodes.push(childNodes[childIndex]);
|
|
379
|
+
}
|
|
380
|
+
if (limitExceeded || signal?.aborted) return {
|
|
381
|
+
candidates: [],
|
|
382
|
+
aborted: signal?.aborted ?? false,
|
|
383
|
+
limitExceeded
|
|
384
|
+
};
|
|
385
|
+
const metadataByNode = /* @__PURE__ */ new Map();
|
|
386
|
+
const functionIdentityByNode = /* @__PURE__ */ new Map();
|
|
387
|
+
for (let nodeIndex = jsxNodes.length - 1; nodeIndex >= 0; nodeIndex -= 1) {
|
|
388
|
+
if (signal?.aborted) return {
|
|
389
|
+
candidates: [],
|
|
390
|
+
aborted: true,
|
|
391
|
+
limitExceeded: false
|
|
392
|
+
};
|
|
393
|
+
buildJsxSubtreeMetadata(jsxNodes[nodeIndex], metadataByNode);
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
candidates: jsxNodes.map((node) => {
|
|
397
|
+
const ancestorRootNames = [];
|
|
398
|
+
let ancestorNode = node.parent;
|
|
399
|
+
while (ancestorNode !== void 0 && ancestorRootNames.length < 19) {
|
|
400
|
+
if (isJsxSubtreeNode(ancestorNode)) ancestorRootNames.unshift(getRootName(ancestorNode));
|
|
401
|
+
ancestorNode = ancestorNode.parent;
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
metadata: buildJsxSubtreeMetadata(node, metadataByNode),
|
|
405
|
+
occurrence: buildOccurrence(source.path, sourceFile, node, ancestorRootNames, functionIdentityByNode)
|
|
406
|
+
};
|
|
407
|
+
}),
|
|
408
|
+
aborted: false,
|
|
409
|
+
limitExceeded: false
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
const scanSource = (input) => {
|
|
413
|
+
if (input.source.sourceText.length > input.options.maxSourceLengthChars) return {
|
|
414
|
+
candidates: [],
|
|
415
|
+
incompleteReason: {
|
|
416
|
+
kind: "source-length-limit",
|
|
417
|
+
limit: input.options.maxSourceLengthChars,
|
|
418
|
+
observed: input.source.sourceText.length,
|
|
419
|
+
path: input.source.path
|
|
420
|
+
},
|
|
421
|
+
didAbort: false,
|
|
422
|
+
didScan: false
|
|
423
|
+
};
|
|
424
|
+
const sourceFile = typescriptBinding.createSourceFile(input.source.path, input.source.sourceText, typescriptBinding.ScriptTarget.Latest, true, getTypescriptScriptKind(input.source.path));
|
|
425
|
+
if (isNonReactJsxSource(sourceFile)) return {
|
|
426
|
+
candidates: [],
|
|
427
|
+
incompleteReason: null,
|
|
428
|
+
didAbort: false,
|
|
429
|
+
didScan: true
|
|
430
|
+
};
|
|
431
|
+
const collectedCandidates = collectCandidates(input.source, sourceFile, input.signal, input.options.maxJsxNodes - input.scannedJsxNodeCount);
|
|
432
|
+
if (collectedCandidates.aborted) return {
|
|
433
|
+
candidates: [],
|
|
434
|
+
incompleteReason: {
|
|
435
|
+
kind: "aborted",
|
|
436
|
+
observed: input.scannedSourceFileCount
|
|
437
|
+
},
|
|
438
|
+
didAbort: true,
|
|
439
|
+
didScan: false
|
|
440
|
+
};
|
|
441
|
+
if (collectedCandidates.limitExceeded) return {
|
|
442
|
+
candidates: [],
|
|
443
|
+
incompleteReason: {
|
|
444
|
+
kind: "jsx-node-limit",
|
|
445
|
+
limit: input.options.maxJsxNodes,
|
|
446
|
+
observed: input.options.maxJsxNodes + 1,
|
|
447
|
+
path: input.source.path
|
|
448
|
+
},
|
|
449
|
+
didAbort: false,
|
|
450
|
+
didScan: false
|
|
451
|
+
};
|
|
452
|
+
return {
|
|
453
|
+
candidates: collectedCandidates.candidates,
|
|
454
|
+
incompleteReason: null,
|
|
455
|
+
didAbort: false,
|
|
456
|
+
didScan: true
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
const occurrenceIsContained = (inner, outer) => inner.path === outer.path && inner.startOffset >= outer.startOffset && inner.endOffset <= outer.endOffset;
|
|
460
|
+
const familyIsNestedWithin = (candidate, outer) => {
|
|
461
|
+
const outerOccurrences = [outer.primaryOccurrence, ...outer.relatedOccurrences];
|
|
462
|
+
return [candidate.primaryOccurrence, ...candidate.relatedOccurrences].every((occurrence) => outerOccurrences.some((outerOccurrence) => occurrenceIsContained(occurrence, outerOccurrence)));
|
|
463
|
+
};
|
|
464
|
+
const suppressNestedFamilies = (families) => {
|
|
465
|
+
const familiesBySize = [...families].sort((left, right) => right.nodeCount - left.nodeCount || right.depth - left.depth);
|
|
466
|
+
const maximalFamilies = [];
|
|
467
|
+
for (const family of familiesBySize) {
|
|
468
|
+
if (maximalFamilies.some((outer) => familyIsNestedWithin(family, outer))) continue;
|
|
469
|
+
maximalFamilies.push(family);
|
|
470
|
+
}
|
|
471
|
+
return maximalFamilies;
|
|
472
|
+
};
|
|
473
|
+
const compareOccurrences = (left, right) => left.path.localeCompare(right.path) || left.startOffset - right.startOffset || left.endOffset - right.endOffset;
|
|
474
|
+
const compareFamilies = (left, right) => right.estimatedRemovableNodeCount - left.estimatedRemovableNodeCount || right.estimatedRemovableLineCount - left.estimatedRemovableLineCount || right.occurrenceCount - left.occurrenceCount || right.distinctFileCount - left.distinctFileCount || right.nodeCount - left.nodeCount || compareOccurrences(left.primaryOccurrence, right.primaryOccurrence) || left.fingerprint.localeCompare(right.fingerprint);
|
|
475
|
+
const buildFamilies = (candidates, options) => {
|
|
476
|
+
const bucketsByFingerprint = /* @__PURE__ */ new Map();
|
|
477
|
+
for (const candidate of candidates) {
|
|
478
|
+
if (candidate.metadata.nodeCount < options.minimumNodeCount) continue;
|
|
479
|
+
if (candidate.metadata.depth < options.minimumDepth) continue;
|
|
480
|
+
const existingBucket = bucketsByFingerprint.get(candidate.metadata.fingerprint);
|
|
481
|
+
if (existingBucket) existingBucket.occurrences.push(candidate.occurrence);
|
|
482
|
+
else bucketsByFingerprint.set(candidate.metadata.fingerprint, {
|
|
483
|
+
metadata: candidate.metadata,
|
|
484
|
+
occurrences: [candidate.occurrence]
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
const families = [];
|
|
488
|
+
const familyProcessingLimit = Math.max(options.maxFamilies * 10, options.maxFamilies + 1);
|
|
489
|
+
for (const bucket of bucketsByFingerprint.values()) {
|
|
490
|
+
if (bucket.occurrences.length < options.minimumOccurrences) continue;
|
|
491
|
+
bucket.occurrences.sort(compareOccurrences);
|
|
492
|
+
const distinctFileCount = new Set(bucket.occurrences.map((occurrence) => occurrence.path)).size;
|
|
493
|
+
if (distinctFileCount < options.minimumDistinctFiles) continue;
|
|
494
|
+
if (distinctFileCount === 1) {
|
|
495
|
+
const compositionRootOffsets = /* @__PURE__ */ new Set();
|
|
496
|
+
for (const occurrence of bucket.occurrences) if (occurrence.compositionRootStartOffset !== null) compositionRootOffsets.add(occurrence.compositionRootStartOffset);
|
|
497
|
+
if (compositionRootOffsets.size < 2) continue;
|
|
498
|
+
}
|
|
499
|
+
families.push({
|
|
500
|
+
fingerprint: bucket.metadata.fingerprint,
|
|
501
|
+
nodeCount: bucket.metadata.nodeCount,
|
|
502
|
+
depth: bucket.metadata.depth,
|
|
503
|
+
occurrenceCount: bucket.occurrences.length,
|
|
504
|
+
distinctFileCount,
|
|
505
|
+
estimatedRemovableNodeCount: bucket.metadata.nodeCount * (bucket.occurrences.length - 1),
|
|
506
|
+
estimatedRemovableLineCount: bucket.occurrences.reduce((total, occurrence) => total + occurrence.endLine - occurrence.startLine + 1, 0) - Math.max(...bucket.occurrences.map((occurrence) => occurrence.endLine - occurrence.startLine + 1)),
|
|
507
|
+
primaryOccurrence: bucket.occurrences[0],
|
|
508
|
+
relatedOccurrences: bucket.occurrences.slice(1)
|
|
509
|
+
});
|
|
510
|
+
if (families.length > familyProcessingLimit) break;
|
|
511
|
+
}
|
|
512
|
+
return { families: suppressNestedFamilies(families).sort(compareFamilies) };
|
|
513
|
+
};
|
|
514
|
+
const buildResult = (input) => {
|
|
515
|
+
return {
|
|
516
|
+
families: buildFamilies(input.candidates, input.options).families.slice(0, input.options.maxFamilies),
|
|
517
|
+
scannedSourceFileCount: input.scannedSourceFileCount,
|
|
518
|
+
scannedJsxNodeCount: input.scannedJsxNodeCount,
|
|
519
|
+
incomplete: input.incompleteReasons.length > 0,
|
|
520
|
+
incompleteReasons: input.incompleteReasons
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
const detectDuplicateJsxSubtreesCooperative = async (sourceReader, options = {}) => {
|
|
524
|
+
const resolvedOptions = resolveOptions(options);
|
|
525
|
+
const incompleteReasons = [];
|
|
526
|
+
const sortedPaths = sourceReader.paths.filter((sourcePath) => JSX_DUPLICATION_SOURCE_FILE_PATTERN.test(sourcePath)).sort((left, right) => left.localeCompare(right));
|
|
527
|
+
if (sortedPaths.length > resolvedOptions.maxSourceFiles) incompleteReasons.push({
|
|
528
|
+
kind: "source-file-limit",
|
|
529
|
+
limit: resolvedOptions.maxSourceFiles,
|
|
530
|
+
observed: sortedPaths.length
|
|
531
|
+
});
|
|
532
|
+
const candidates = [];
|
|
533
|
+
let scannedSourceFileCount = 0;
|
|
534
|
+
let scannedJsxNodeCount = 0;
|
|
535
|
+
const scannedPaths = sortedPaths.slice(0, resolvedOptions.maxSourceFiles);
|
|
536
|
+
const readAhead = (pathIndex) => {
|
|
537
|
+
if (pathIndex >= scannedPaths.length) return null;
|
|
538
|
+
const pendingRead = sourceReader.read(scannedPaths[pathIndex], resolvedOptions.maxSourceLengthChars);
|
|
539
|
+
pendingRead.catch(() => void 0);
|
|
540
|
+
return pendingRead;
|
|
541
|
+
};
|
|
542
|
+
let pendingRead = readAhead(0);
|
|
543
|
+
for (const [pathIndex, sourcePath] of scannedPaths.entries()) {
|
|
544
|
+
if (options.signal?.aborted) {
|
|
545
|
+
incompleteReasons.push({
|
|
546
|
+
kind: "aborted",
|
|
547
|
+
observed: scannedSourceFileCount
|
|
548
|
+
});
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
const sourceText = await pendingRead;
|
|
552
|
+
pendingRead = readAhead(pathIndex + 1);
|
|
553
|
+
if (sourceText === null) continue;
|
|
554
|
+
const scannedSource = scanSource({
|
|
555
|
+
source: {
|
|
556
|
+
path: sourcePath,
|
|
557
|
+
sourceText
|
|
558
|
+
},
|
|
559
|
+
options: resolvedOptions,
|
|
560
|
+
signal: options.signal,
|
|
561
|
+
scannedSourceFileCount,
|
|
562
|
+
scannedJsxNodeCount
|
|
563
|
+
});
|
|
564
|
+
if (scannedSource.incompleteReason !== null) incompleteReasons.push(scannedSource.incompleteReason);
|
|
565
|
+
if (scannedSource.didScan) {
|
|
566
|
+
candidates.push(...scannedSource.candidates);
|
|
567
|
+
scannedJsxNodeCount += scannedSource.candidates.length;
|
|
568
|
+
scannedSourceFileCount += 1;
|
|
569
|
+
}
|
|
570
|
+
if (scannedSource.didAbort) break;
|
|
571
|
+
await yieldToEventLoop();
|
|
572
|
+
}
|
|
573
|
+
return buildResult({
|
|
574
|
+
candidates,
|
|
575
|
+
options: resolvedOptions,
|
|
576
|
+
incompleteReasons,
|
|
577
|
+
scannedSourceFileCount,
|
|
578
|
+
scannedJsxNodeCount
|
|
579
|
+
});
|
|
580
|
+
};
|
|
581
|
+
//#endregion
|
|
582
|
+
//#region ../core/src/start-duplicate-jsx-worker.ts
|
|
583
|
+
const serializeError = (error) => error instanceof Error ? {
|
|
584
|
+
name: error.name,
|
|
585
|
+
message: error.message,
|
|
586
|
+
stack: error.stack
|
|
587
|
+
} : { message: String(error) };
|
|
588
|
+
const isWorkerCommand = (value) => typeof value === "object" && value !== null && "type" in value && (value.type === "detect" || value.type === "abort") && "id" in value && typeof value.id === "number";
|
|
589
|
+
const startDuplicateJsxWorker = () => {
|
|
590
|
+
if (parentPort === null) throw new Error("Duplicate JSX worker must run as a worker thread.");
|
|
591
|
+
const port = parentPort;
|
|
592
|
+
const abortControllersById = /* @__PURE__ */ new Map();
|
|
593
|
+
let queue = Promise.resolve();
|
|
594
|
+
const reply = (message) => port.postMessage(message);
|
|
595
|
+
const detect = async (request) => {
|
|
596
|
+
const abortController = abortControllersById.get(request.id);
|
|
597
|
+
if (abortController === void 0) return;
|
|
598
|
+
try {
|
|
599
|
+
const result = await detectDuplicateJsxSubtreesCooperative(createJsxSourceReader({
|
|
600
|
+
rootDirectory: request.rootDirectory,
|
|
601
|
+
sourceFiles: request.sourceFiles,
|
|
602
|
+
useBlockingReads: true
|
|
603
|
+
}), { signal: abortController.signal });
|
|
604
|
+
reply({
|
|
605
|
+
id: request.id,
|
|
606
|
+
ok: true,
|
|
607
|
+
result
|
|
608
|
+
});
|
|
609
|
+
} catch (error) {
|
|
610
|
+
reply({
|
|
611
|
+
id: request.id,
|
|
612
|
+
ok: false,
|
|
613
|
+
error: serializeError(error)
|
|
614
|
+
});
|
|
615
|
+
} finally {
|
|
616
|
+
abortControllersById.delete(request.id);
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
port.on("message", (message) => {
|
|
620
|
+
if (!isWorkerCommand(message)) return;
|
|
621
|
+
if (message.type === "abort") {
|
|
622
|
+
abortControllersById.get(message.id)?.abort();
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
abortControllersById.set(message.id, new AbortController());
|
|
626
|
+
queue = queue.then(() => detect(message));
|
|
627
|
+
});
|
|
628
|
+
};
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/duplicate-jsx-worker.ts
|
|
631
|
+
startDuplicateJsxWorker();
|
|
632
|
+
//#endregion
|
|
633
|
+
export {};
|
|
634
|
+
|
|
635
|
+
//# sourceMappingURL=duplicate-jsx-worker.js.map
|
|
636
|
+
//# debugId=3fb1e6c0-870e-54f2-9dd3-ef90f8a0c9bf
|
|
@@ -1,9 +1,9 @@
|
|
|
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]="
|
|
3
|
-
import { d as isJsonModeActive, m as writeJsonCancellationReport } from "./record-metric-
|
|
4
|
-
import { n as shutdownTelemetry } from "./telemetry-runtime-
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
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]="17e2f835-4349-5113-af45-e629ce1701a8")}catch(e){}}();
|
|
3
|
+
import { d as isJsonModeActive, m as writeJsonCancellationReport } from "./record-metric-CQTcuE_T.js";
|
|
4
|
+
import { n as shutdownTelemetry, r as flushSentry } from "./telemetry-runtime-CbJQ0K-c.js";
|
|
5
|
+
import { t as activeScanAbortRegistry } from "./active-scan-abort-registry-CCTgal0O.js";
|
|
6
|
+
import { n as buildFooterLinkLines, t as buildSectionDivider } from "./build-section-divider-gekJe2aO.js";
|
|
7
7
|
//#region src/cli/utils/active-tui-renderer.ts
|
|
8
8
|
let activeTuiRenderer = null;
|
|
9
9
|
const registerActiveTuiRenderer = (renderer) => {
|
|
@@ -50,5 +50,5 @@ const exitGracefully = () => {
|
|
|
50
50
|
//#endregion
|
|
51
51
|
export { registerActiveTuiRenderer as n, exitGracefully as t };
|
|
52
52
|
|
|
53
|
-
//# sourceMappingURL=exit-gracefully-
|
|
54
|
-
//# debugId=
|
|
53
|
+
//# sourceMappingURL=exit-gracefully-D69nyRA4.js.map
|
|
54
|
+
//# debugId=17e2f835-4349-5113-af45-e629ce1701a8
|