@decantr/verifier 3.1.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/index.d.ts +134 -1
- package/dist/index.js +1203 -383
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/schema/evidence-bundle.v2.json +436 -0
- package/schema/runtime-probe-payload.v2.json +218 -0
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
|
-
import { existsSync as
|
|
3
|
+
import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6, realpathSync as realpathSync2, statSync as statSync5 } from "fs";
|
|
4
4
|
import { readFile } from "fs/promises";
|
|
5
|
-
import { basename as basename2, dirname, extname as
|
|
5
|
+
import { basename as basename2, dirname as dirname2, extname as extname6, isAbsolute as isAbsolute4, join as join6, relative as relative6, resolve as resolve3 } from "path";
|
|
6
6
|
import { evaluateGuard, isV4, validateEssence } from "@decantr/essence-spec";
|
|
7
|
-
import * as
|
|
7
|
+
import * as ts6 from "typescript";
|
|
8
8
|
|
|
9
9
|
// src/component-reuse.ts
|
|
10
10
|
import { readFileSync } from "fs";
|
|
@@ -968,6 +968,22 @@ function normalizePath2(path) {
|
|
|
968
968
|
function stringArray(value) {
|
|
969
969
|
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.length > 0) : [];
|
|
970
970
|
}
|
|
971
|
+
function normalizedConfidence(value) {
|
|
972
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
973
|
+
return Math.max(0, Math.min(1, value));
|
|
974
|
+
}
|
|
975
|
+
function nativeTokenHint(mapping) {
|
|
976
|
+
const kind = typeof mapping.native?.kind === "string" ? mapping.native.kind : null;
|
|
977
|
+
const ref = typeof mapping.native?.ref === "string" ? mapping.native.ref : null;
|
|
978
|
+
if (!kind || !ref) return null;
|
|
979
|
+
return kind === "css-var" || kind === "vanilla-extract-token" || kind === "sass-var" ? ref : null;
|
|
980
|
+
}
|
|
981
|
+
function nativeClassHint(mapping) {
|
|
982
|
+
const kind = typeof mapping.native?.kind === "string" ? mapping.native.kind : null;
|
|
983
|
+
const ref = typeof mapping.native?.ref === "string" ? mapping.native.ref : null;
|
|
984
|
+
if (!kind || !ref) return null;
|
|
985
|
+
return kind === "class" || kind === "tailwind-class" || kind === "component" ? ref : null;
|
|
986
|
+
}
|
|
971
987
|
function isNonProductionStyleBridgeDriftFile(file) {
|
|
972
988
|
const normalized = normalizePath2(file);
|
|
973
989
|
return /(?:^|\/)(?:__tests__|__mocks__|tests?|specs?|fixtures?|mocks?|stories?)(?:\/|$)/i.test(
|
|
@@ -1022,12 +1038,28 @@ function readAcceptedStyleBridge(projectRoot) {
|
|
|
1022
1038
|
(mapping, index) => typeof mapping.id === "string" && mapping.id.length > 0 ? mapping.id : typeof mapping.label === "string" && mapping.label.length > 0 ? mapping.label : `mapping-${index + 1}`
|
|
1023
1039
|
).slice(0, 12);
|
|
1024
1040
|
const tokenHints = [
|
|
1025
|
-
...new Set(
|
|
1026
|
-
|
|
1041
|
+
...new Set(
|
|
1042
|
+
mappings.flatMap((mapping) => [...stringArray(mapping.tokenHints), nativeTokenHint(mapping)])
|
|
1043
|
+
)
|
|
1044
|
+
].filter((entry) => Boolean(entry)).slice(0, 16);
|
|
1027
1045
|
const classHints = [
|
|
1028
|
-
...new Set(
|
|
1046
|
+
...new Set(
|
|
1047
|
+
mappings.flatMap((mapping) => [...stringArray(mapping.classHints), nativeClassHint(mapping)])
|
|
1048
|
+
)
|
|
1049
|
+
].filter((entry) => Boolean(entry)).slice(0, 16);
|
|
1050
|
+
const confidences = mappings.map((mapping) => normalizedConfidence(mapping.confidence)).filter((entry) => entry !== null);
|
|
1051
|
+
const sources = [
|
|
1052
|
+
...new Set(
|
|
1053
|
+
mappings.map((mapping) => mapping.source).filter((source) => typeof source === "string" && source.length > 0)
|
|
1054
|
+
)
|
|
1029
1055
|
].slice(0, 16);
|
|
1030
|
-
return {
|
|
1056
|
+
return {
|
|
1057
|
+
mappingIds,
|
|
1058
|
+
confidence: confidences.length > 0 ? Math.max(...confidences) : null,
|
|
1059
|
+
sources,
|
|
1060
|
+
tokenHints,
|
|
1061
|
+
classHints
|
|
1062
|
+
};
|
|
1031
1063
|
}
|
|
1032
1064
|
function lineForNode2(sourceFile, node) {
|
|
1033
1065
|
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
@@ -1128,13 +1160,16 @@ function isAcceptedTokenValue(value, tokenHints) {
|
|
|
1128
1160
|
return value.includes(normalizedHint) || value.includes(`var(${normalizedHint})`);
|
|
1129
1161
|
});
|
|
1130
1162
|
}
|
|
1131
|
-
function arbitraryInlineStyleValue(property, value, tokenHints) {
|
|
1163
|
+
function arbitraryInlineStyleValue(property, value, tokenHints, options = {}) {
|
|
1132
1164
|
const normalizedProperty = property.trim();
|
|
1133
1165
|
const normalizedValue = value.trim();
|
|
1134
1166
|
if (!normalizedProperty || !normalizedValue) return null;
|
|
1135
1167
|
const isVisualProperty = INLINE_STYLE_PROPERTIES.has(normalizedProperty) || STYLESHEET_VISUAL_PROPERTIES.has(normalizedProperty) || normalizedProperty.startsWith("--");
|
|
1136
1168
|
if (!isVisualProperty) return null;
|
|
1137
1169
|
if (isAcceptedTokenValue(normalizedValue, tokenHints)) return null;
|
|
1170
|
+
if (options.allowCssVariableValues && /\bvar\(\s*--[A-Za-z0-9_-]+/i.test(normalizedValue)) {
|
|
1171
|
+
return null;
|
|
1172
|
+
}
|
|
1138
1173
|
if (/(?:^|[\s,(])#[0-9a-f]{3,8}\b|(?:rgba?|hsla?|oklch|oklab|lch|lab|color-mix)\(/i.test(
|
|
1139
1174
|
normalizedValue
|
|
1140
1175
|
)) {
|
|
@@ -1184,11 +1219,15 @@ function collectStyleBridgeDriftFindings(input) {
|
|
|
1184
1219
|
source,
|
|
1185
1220
|
...property ? { property } : {},
|
|
1186
1221
|
bridgeMappingIds: input.bridge.mappingIds,
|
|
1222
|
+
bridgeConfidence: input.bridge.confidence,
|
|
1223
|
+
bridgeSources: input.bridge.sources,
|
|
1187
1224
|
tokenHints: input.bridge.tokenHints,
|
|
1188
1225
|
classHints: input.bridge.classHints,
|
|
1189
1226
|
evidence: [
|
|
1190
1227
|
styleBridgeEvidenceText(file, line, source, value),
|
|
1191
1228
|
`.decantr/style-bridge.json is accepted with mappings: ${input.bridge.mappingIds.join(", ")}`,
|
|
1229
|
+
input.bridge.confidence === null ? "Accepted style bridge has no mapping confidence metadata" : `Accepted style bridge max confidence: ${input.bridge.confidence.toFixed(2)}`,
|
|
1230
|
+
input.bridge.sources.length > 0 ? `Accepted style bridge mapping sources: ${input.bridge.sources.join(", ")}` : "Accepted style bridge has no mapping source metadata",
|
|
1192
1231
|
input.bridge.tokenHints.length > 0 ? `Accepted token hints: ${input.bridge.tokenHints.join(", ")}` : "Accepted style bridge has no token hints for this mapping set",
|
|
1193
1232
|
input.bridge.classHints.length > 0 ? `Accepted class hints: ${input.bridge.classHints.join(", ")}` : "Accepted style bridge has no class hints for this mapping set"
|
|
1194
1233
|
]
|
|
@@ -1250,7 +1289,9 @@ function collectStylesheetBridgeDriftFindings(input) {
|
|
|
1250
1289
|
const property = match.groups?.property;
|
|
1251
1290
|
const rawValue = match.groups?.value;
|
|
1252
1291
|
if (!property || !rawValue) continue;
|
|
1253
|
-
const value = arbitraryInlineStyleValue(property, rawValue, input.bridge.tokenHints
|
|
1292
|
+
const value = arbitraryInlineStyleValue(property, rawValue, input.bridge.tokenHints, {
|
|
1293
|
+
allowCssVariableValues: true
|
|
1294
|
+
});
|
|
1254
1295
|
if (!value) continue;
|
|
1255
1296
|
const lineNumber = lineIndex + 1;
|
|
1256
1297
|
const key = `${file}:${lineNumber}:${value}`;
|
|
@@ -1265,11 +1306,15 @@ function collectStylesheetBridgeDriftFindings(input) {
|
|
|
1265
1306
|
source: "stylesheet",
|
|
1266
1307
|
property,
|
|
1267
1308
|
bridgeMappingIds: input.bridge.mappingIds,
|
|
1309
|
+
bridgeConfidence: input.bridge.confidence,
|
|
1310
|
+
bridgeSources: input.bridge.sources,
|
|
1268
1311
|
tokenHints: input.bridge.tokenHints,
|
|
1269
1312
|
classHints: input.bridge.classHints,
|
|
1270
1313
|
evidence: [
|
|
1271
1314
|
`${file}:${lineNumber} uses stylesheet value "${value}"`,
|
|
1272
1315
|
`.decantr/style-bridge.json is accepted with mappings: ${input.bridge.mappingIds.join(", ")}`,
|
|
1316
|
+
input.bridge.confidence === null ? "Accepted style bridge has no mapping confidence metadata" : `Accepted style bridge max confidence: ${input.bridge.confidence.toFixed(2)}`,
|
|
1317
|
+
input.bridge.sources.length > 0 ? `Accepted style bridge mapping sources: ${input.bridge.sources.join(", ")}` : "Accepted style bridge has no mapping source metadata",
|
|
1273
1318
|
input.bridge.tokenHints.length > 0 ? `Accepted token hints: ${input.bridge.tokenHints.join(", ")}` : "Accepted style bridge has no token hints for this mapping set",
|
|
1274
1319
|
input.bridge.classHints.length > 0 ? `Accepted class hints: ${input.bridge.classHints.join(", ")}` : "Accepted style bridge has no class hints for this mapping set"
|
|
1275
1320
|
]
|
|
@@ -1324,6 +1369,18 @@ var KNOWN_VERIFICATION_DIAGNOSTICS = [
|
|
|
1324
1369
|
repairId: "fix-route-render",
|
|
1325
1370
|
family: "VISUAL"
|
|
1326
1371
|
},
|
|
1372
|
+
{
|
|
1373
|
+
rule: "browser-runtime-probes-failed",
|
|
1374
|
+
code: "RUNTIME010",
|
|
1375
|
+
repairId: "repair-browser-runtime-probes",
|
|
1376
|
+
family: "RUNTIME"
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
rule: "browser-axe-violations",
|
|
1380
|
+
code: "A11Y020",
|
|
1381
|
+
repairId: "fix-rendered-accessibility",
|
|
1382
|
+
family: "A11Y"
|
|
1383
|
+
},
|
|
1327
1384
|
{
|
|
1328
1385
|
rule: "visual-baseline-screenshot-drift",
|
|
1329
1386
|
code: "VISUAL010",
|
|
@@ -2965,6 +3022,716 @@ function resolveGitHubScanInput(input) {
|
|
|
2965
3022
|
throw new Error("V1 hosted scans support GitHub repositories and GitHub Pages URLs.");
|
|
2966
3023
|
}
|
|
2967
3024
|
|
|
3025
|
+
// src/source/ast.ts
|
|
3026
|
+
import * as ts4 from "typescript";
|
|
3027
|
+
|
|
3028
|
+
// src/source/inventory.ts
|
|
3029
|
+
import { existsSync as existsSync4, readdirSync as readdirSync4, realpathSync, statSync as statSync3 } from "fs";
|
|
3030
|
+
import { extname as extname4, isAbsolute as isAbsolute2, join as join4, relative as relative4, resolve } from "path";
|
|
3031
|
+
import * as ts3 from "typescript";
|
|
3032
|
+
var DEFAULT_MAX_FILES = 5e3;
|
|
3033
|
+
var DEFAULT_MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
3034
|
+
var DEFAULT_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
3035
|
+
var GENERATED_AND_DEPENDENCY_DIRS = /* @__PURE__ */ new Set([
|
|
3036
|
+
".cache",
|
|
3037
|
+
".git",
|
|
3038
|
+
".next",
|
|
3039
|
+
".nuxt",
|
|
3040
|
+
".svelte-kit",
|
|
3041
|
+
".turbo",
|
|
3042
|
+
".vite",
|
|
3043
|
+
"build",
|
|
3044
|
+
"coverage",
|
|
3045
|
+
"dist",
|
|
3046
|
+
"node_modules",
|
|
3047
|
+
"out",
|
|
3048
|
+
"target",
|
|
3049
|
+
"vendor"
|
|
3050
|
+
]);
|
|
3051
|
+
var TEST_OR_MOCK_DIR_RE = /(?:^|\/)(?:__mocks__|__tests__|mocks?|specs?|tests?)(?:\/|$)/i;
|
|
3052
|
+
var FIXTURE_DIR_RE = /(?:^|\/)fixtures?(?:\/|$)/i;
|
|
3053
|
+
var DECLARATION_FILE_RE = /\.d\.[cm]?ts$/i;
|
|
3054
|
+
var TEST_OR_MOCK_FILE_RE = /\.(?:mock|spec|test)\.[cm]?[jt]sx?$/i;
|
|
3055
|
+
var STORY_FILE_RE = /\.(?:stories|story)\.[cm]?[jt]sx?$/i;
|
|
3056
|
+
var FIXTURE_FILE_RE = /\.fixture\.[cm]?[jt]sx?$/i;
|
|
3057
|
+
function normalizeSourcePath(path) {
|
|
3058
|
+
return path.replace(/\\/g, "/");
|
|
3059
|
+
}
|
|
3060
|
+
function isPathInsideProject(projectRoot, absolutePath) {
|
|
3061
|
+
const normalizedRelative = normalizeSourcePath(relative4(projectRoot, absolutePath));
|
|
3062
|
+
return normalizedRelative === "" || !normalizedRelative.startsWith("../") && normalizedRelative !== "..";
|
|
3063
|
+
}
|
|
3064
|
+
function isSupportedSourceExtension(extension, extensions) {
|
|
3065
|
+
const normalized = extension.toLowerCase();
|
|
3066
|
+
return extensions ? extensions.map((entry) => entry.toLowerCase()).includes(normalized) : DEFAULT_EXTENSIONS.has(normalized);
|
|
3067
|
+
}
|
|
3068
|
+
function sourceKindFromPath(path) {
|
|
3069
|
+
const extension = extname4(path).toLowerCase();
|
|
3070
|
+
switch (extension) {
|
|
3071
|
+
case ".ts":
|
|
3072
|
+
return "ts";
|
|
3073
|
+
case ".tsx":
|
|
3074
|
+
return "tsx";
|
|
3075
|
+
case ".mts":
|
|
3076
|
+
return "mts";
|
|
3077
|
+
case ".cts":
|
|
3078
|
+
return "cts";
|
|
3079
|
+
case ".js":
|
|
3080
|
+
return "js";
|
|
3081
|
+
case ".jsx":
|
|
3082
|
+
return "jsx";
|
|
3083
|
+
case ".mjs":
|
|
3084
|
+
return "mjs";
|
|
3085
|
+
case ".cjs":
|
|
3086
|
+
return "cjs";
|
|
3087
|
+
default:
|
|
3088
|
+
return null;
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
function sourceScriptKindFromPath(path) {
|
|
3092
|
+
const kind = sourceKindFromPath(path);
|
|
3093
|
+
switch (kind) {
|
|
3094
|
+
case "ts":
|
|
3095
|
+
case "mts":
|
|
3096
|
+
case "cts":
|
|
3097
|
+
return ts3.ScriptKind.TS;
|
|
3098
|
+
case "tsx":
|
|
3099
|
+
return ts3.ScriptKind.TSX;
|
|
3100
|
+
case "jsx":
|
|
3101
|
+
return ts3.ScriptKind.JSX;
|
|
3102
|
+
case "js":
|
|
3103
|
+
case "mjs":
|
|
3104
|
+
case "cjs":
|
|
3105
|
+
return ts3.ScriptKind.JS;
|
|
3106
|
+
default:
|
|
3107
|
+
return ts3.ScriptKind.Unknown;
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
function sourceLanguageFromPath(path) {
|
|
3111
|
+
const kind = sourceKindFromPath(path);
|
|
3112
|
+
if (!kind) return null;
|
|
3113
|
+
return kind === "ts" || kind === "tsx" || kind === "mts" || kind === "cts" ? "typescript" : "javascript";
|
|
3114
|
+
}
|
|
3115
|
+
function shouldSkipDirectory(relativePath, options) {
|
|
3116
|
+
const normalized = normalizeSourcePath(relativePath);
|
|
3117
|
+
const basename3 = normalized.split("/").at(-1) ?? normalized;
|
|
3118
|
+
if (GENERATED_AND_DEPENDENCY_DIRS.has(basename3)) return true;
|
|
3119
|
+
if (!options.includeTests && TEST_OR_MOCK_DIR_RE.test(normalized)) return true;
|
|
3120
|
+
if (!options.includeFixtures && FIXTURE_DIR_RE.test(normalized)) return true;
|
|
3121
|
+
return false;
|
|
3122
|
+
}
|
|
3123
|
+
function shouldSkipFile(relativePath, options) {
|
|
3124
|
+
const normalized = normalizeSourcePath(relativePath);
|
|
3125
|
+
if (DECLARATION_FILE_RE.test(normalized)) return true;
|
|
3126
|
+
if (!options.includeTests && (TEST_OR_MOCK_FILE_RE.test(normalized) || STORY_FILE_RE.test(normalized))) {
|
|
3127
|
+
return true;
|
|
3128
|
+
}
|
|
3129
|
+
if (!options.includeFixtures && FIXTURE_FILE_RE.test(normalized)) return true;
|
|
3130
|
+
return false;
|
|
3131
|
+
}
|
|
3132
|
+
function inventoryFile(projectRoot, absolutePath) {
|
|
3133
|
+
const extension = extname4(absolutePath).toLowerCase();
|
|
3134
|
+
const kind = sourceKindFromPath(absolutePath);
|
|
3135
|
+
const language = sourceLanguageFromPath(absolutePath);
|
|
3136
|
+
if (!kind || !language) return null;
|
|
3137
|
+
const relativePath = normalizeSourcePath(relative4(projectRoot, absolutePath) || absolutePath);
|
|
3138
|
+
const sizeBytes = statSync3(absolutePath).size;
|
|
3139
|
+
return {
|
|
3140
|
+
absolutePath,
|
|
3141
|
+
relativePath,
|
|
3142
|
+
extension,
|
|
3143
|
+
kind,
|
|
3144
|
+
language,
|
|
3145
|
+
scriptKind: sourceScriptKindFromPath(absolutePath),
|
|
3146
|
+
jsx: kind === "tsx" || kind === "jsx",
|
|
3147
|
+
sizeBytes
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
function compareSourceFiles(a, b) {
|
|
3151
|
+
return a.relativePath.localeCompare(b.relativePath);
|
|
3152
|
+
}
|
|
3153
|
+
function compareSkipped(a, b) {
|
|
3154
|
+
return a.path.localeCompare(b.path) || a.reason.localeCompare(b.reason);
|
|
3155
|
+
}
|
|
3156
|
+
function createSourceInventory(projectRoot, options = {}) {
|
|
3157
|
+
const root = realpathSync(resolve(projectRoot));
|
|
3158
|
+
const files = [];
|
|
3159
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
3160
|
+
const skipped = [];
|
|
3161
|
+
const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
|
|
3162
|
+
const maxFileSizeBytes = options.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES;
|
|
3163
|
+
const requestedRoots = options.roots?.length ? [...options.roots] : ["."];
|
|
3164
|
+
const roots = requestedRoots.map((entry) => isAbsolute2(entry) ? resolve(entry) : resolve(root, entry)).filter((entry) => existsSync4(entry) && isPathInsideProject(root, entry));
|
|
3165
|
+
const addSkipped = (path, reason) => {
|
|
3166
|
+
skipped.push({ path: normalizeSourcePath(relative4(root, path) || path), reason });
|
|
3167
|
+
};
|
|
3168
|
+
const addFile = (absolutePath) => {
|
|
3169
|
+
const normalized = normalizeSourcePath(resolve(absolutePath));
|
|
3170
|
+
if (seenFiles.has(normalized)) return;
|
|
3171
|
+
const sourceFile = inventoryFile(root, absolutePath);
|
|
3172
|
+
if (!sourceFile) return;
|
|
3173
|
+
seenFiles.add(normalized);
|
|
3174
|
+
files.push(sourceFile);
|
|
3175
|
+
};
|
|
3176
|
+
const walk = (directory) => {
|
|
3177
|
+
if (files.length >= maxFiles) {
|
|
3178
|
+
addSkipped(directory, "walk-limit");
|
|
3179
|
+
return;
|
|
3180
|
+
}
|
|
3181
|
+
const entries = readdirSync4(directory, { withFileTypes: true }).sort(
|
|
3182
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
3183
|
+
);
|
|
3184
|
+
for (const entry of entries) {
|
|
3185
|
+
if (files.length >= maxFiles) {
|
|
3186
|
+
addSkipped(join4(directory, entry.name), "walk-limit");
|
|
3187
|
+
continue;
|
|
3188
|
+
}
|
|
3189
|
+
const absolutePath = join4(directory, entry.name);
|
|
3190
|
+
const relativePath = normalizeSourcePath(relative4(root, absolutePath) || absolutePath);
|
|
3191
|
+
if (entry.isSymbolicLink()) {
|
|
3192
|
+
addSkipped(absolutePath, "symlink");
|
|
3193
|
+
continue;
|
|
3194
|
+
}
|
|
3195
|
+
if (entry.isDirectory()) {
|
|
3196
|
+
if (shouldSkipDirectory(relativePath, options)) {
|
|
3197
|
+
addSkipped(absolutePath, "ignored-directory");
|
|
3198
|
+
continue;
|
|
3199
|
+
}
|
|
3200
|
+
walk(absolutePath);
|
|
3201
|
+
continue;
|
|
3202
|
+
}
|
|
3203
|
+
if (!entry.isFile()) continue;
|
|
3204
|
+
const extension = extname4(entry.name).toLowerCase();
|
|
3205
|
+
if (!isSupportedSourceExtension(extension, options.extensions)) continue;
|
|
3206
|
+
if (shouldSkipFile(relativePath, options)) {
|
|
3207
|
+
addSkipped(absolutePath, "ignored-file");
|
|
3208
|
+
continue;
|
|
3209
|
+
}
|
|
3210
|
+
const stat = statSync3(absolutePath);
|
|
3211
|
+
if (stat.size > maxFileSizeBytes) {
|
|
3212
|
+
addSkipped(absolutePath, "oversized");
|
|
3213
|
+
continue;
|
|
3214
|
+
}
|
|
3215
|
+
addFile(absolutePath);
|
|
3216
|
+
}
|
|
3217
|
+
};
|
|
3218
|
+
for (const rootPath of roots) {
|
|
3219
|
+
if (files.length >= maxFiles) {
|
|
3220
|
+
addSkipped(rootPath, "walk-limit");
|
|
3221
|
+
continue;
|
|
3222
|
+
}
|
|
3223
|
+
const stat = statSync3(rootPath);
|
|
3224
|
+
if (stat.isDirectory()) {
|
|
3225
|
+
const relativeRoot = normalizeSourcePath(relative4(root, rootPath));
|
|
3226
|
+
if (relativeRoot && shouldSkipDirectory(relativeRoot, options)) {
|
|
3227
|
+
addSkipped(rootPath, "ignored-directory");
|
|
3228
|
+
continue;
|
|
3229
|
+
}
|
|
3230
|
+
walk(rootPath);
|
|
3231
|
+
} else if (stat.isFile()) {
|
|
3232
|
+
const extension = extname4(rootPath).toLowerCase();
|
|
3233
|
+
if (!isSupportedSourceExtension(extension, options.extensions)) continue;
|
|
3234
|
+
const relativeFile = normalizeSourcePath(relative4(root, rootPath));
|
|
3235
|
+
if (shouldSkipFile(relativeFile, options)) {
|
|
3236
|
+
addSkipped(rootPath, "ignored-file");
|
|
3237
|
+
continue;
|
|
3238
|
+
}
|
|
3239
|
+
addFile(rootPath);
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
const sortedFiles = files.sort(compareSourceFiles);
|
|
3243
|
+
const hasTypeScript = sortedFiles.some((file) => file.language === "typescript");
|
|
3244
|
+
const hasJavaScript = sortedFiles.some((file) => file.language === "javascript");
|
|
3245
|
+
return {
|
|
3246
|
+
projectRoot: root,
|
|
3247
|
+
files: sortedFiles,
|
|
3248
|
+
skipped: skipped.sort(compareSkipped),
|
|
3249
|
+
hasTypeScript,
|
|
3250
|
+
hasJavaScript,
|
|
3251
|
+
primaryLanguage: hasTypeScript && hasJavaScript ? "mixed" : hasTypeScript ? "typescript" : hasJavaScript ? "javascript" : "unknown"
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
// src/source/ast.ts
|
|
3256
|
+
function sourceLocationForNode(sourceFile, node) {
|
|
3257
|
+
const position = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
3258
|
+
return {
|
|
3259
|
+
file: normalizeSourcePath(sourceFile.fileName),
|
|
3260
|
+
line: position.line + 1,
|
|
3261
|
+
column: position.character + 1
|
|
3262
|
+
};
|
|
3263
|
+
}
|
|
3264
|
+
function literalRawText(node) {
|
|
3265
|
+
return node.getText();
|
|
3266
|
+
}
|
|
3267
|
+
function isStringLiteralLike(node) {
|
|
3268
|
+
return ts4.isStringLiteral(node) || ts4.isNoSubstitutionTemplateLiteral(node);
|
|
3269
|
+
}
|
|
3270
|
+
function isImportSpecifierLiteral(node) {
|
|
3271
|
+
const parent = node.parent;
|
|
3272
|
+
return ts4.isImportDeclaration(parent) && parent.moduleSpecifier === node || ts4.isExternalModuleReference(parent) && parent.expression === node;
|
|
3273
|
+
}
|
|
3274
|
+
function isExportSpecifierLiteral(node) {
|
|
3275
|
+
const parent = node.parent;
|
|
3276
|
+
return ts4.isExportDeclaration(parent) && parent.moduleSpecifier === node;
|
|
3277
|
+
}
|
|
3278
|
+
function requireOrDynamicImportContext(node) {
|
|
3279
|
+
const parent = node.parent;
|
|
3280
|
+
if (!ts4.isCallExpression(parent) || parent.arguments[0] !== node) return null;
|
|
3281
|
+
if (parent.expression.kind === ts4.SyntaxKind.ImportKeyword) return "dynamic-import-specifier";
|
|
3282
|
+
if (ts4.isIdentifier(parent.expression) && parent.expression.text === "require") {
|
|
3283
|
+
return "require-specifier";
|
|
3284
|
+
}
|
|
3285
|
+
return null;
|
|
3286
|
+
}
|
|
3287
|
+
function propertyNameContext(node) {
|
|
3288
|
+
const parent = node.parent;
|
|
3289
|
+
if ((ts4.isPropertyAssignment(parent) || ts4.isPropertyDeclaration(parent) || ts4.isMethodDeclaration(parent) || ts4.isGetAccessorDeclaration(parent) || ts4.isSetAccessorDeclaration(parent)) && parent.name === node) {
|
|
3290
|
+
return "property-name";
|
|
3291
|
+
}
|
|
3292
|
+
return null;
|
|
3293
|
+
}
|
|
3294
|
+
function jsxAttributeContext(node) {
|
|
3295
|
+
const parent = node.parent;
|
|
3296
|
+
if (!ts4.isJsxAttribute(parent) || parent.initializer !== node) return null;
|
|
3297
|
+
return {
|
|
3298
|
+
context: "jsx-attribute",
|
|
3299
|
+
attributeName: parent.name.getText()
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
function literalContext(node) {
|
|
3303
|
+
const jsxContext = jsxAttributeContext(node);
|
|
3304
|
+
if (jsxContext) return jsxContext;
|
|
3305
|
+
const importLikeContext = requireOrDynamicImportContext(node);
|
|
3306
|
+
if (importLikeContext) return { context: importLikeContext };
|
|
3307
|
+
if (isImportSpecifierLiteral(node)) return { context: "import-specifier" };
|
|
3308
|
+
if (isExportSpecifierLiteral(node)) return { context: "export-specifier" };
|
|
3309
|
+
const propertyContext = propertyNameContext(node);
|
|
3310
|
+
if (propertyContext) return { context: propertyContext };
|
|
3311
|
+
return {
|
|
3312
|
+
context: ts4.isNoSubstitutionTemplateLiteral(node) ? "template-literal" : "string-literal"
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
function extractSourceStringLiterals(sourceFile, options = {}) {
|
|
3316
|
+
const includeImportSpecifiers = options.includeImportSpecifiers ?? true;
|
|
3317
|
+
const includeObjectPropertyNames = options.includeObjectPropertyNames ?? true;
|
|
3318
|
+
const literals = [];
|
|
3319
|
+
const visit = (node) => {
|
|
3320
|
+
if (isStringLiteralLike(node)) {
|
|
3321
|
+
const context = literalContext(node);
|
|
3322
|
+
const isImportLike = context.context === "import-specifier" || context.context === "export-specifier" || context.context === "require-specifier" || context.context === "dynamic-import-specifier";
|
|
3323
|
+
if ((includeImportSpecifiers || !isImportLike) && (includeObjectPropertyNames || context.context !== "property-name")) {
|
|
3324
|
+
literals.push({
|
|
3325
|
+
value: node.text,
|
|
3326
|
+
rawText: literalRawText(node),
|
|
3327
|
+
context: context.context,
|
|
3328
|
+
location: sourceLocationForNode(sourceFile, node),
|
|
3329
|
+
...context.attributeName ? { attributeName: context.attributeName } : {}
|
|
3330
|
+
});
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
3333
|
+
ts4.forEachChild(node, visit);
|
|
3334
|
+
};
|
|
3335
|
+
visit(sourceFile);
|
|
3336
|
+
return literals;
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
// src/source/program.ts
|
|
3340
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
|
|
3341
|
+
import { dirname, extname as extname5, isAbsolute as isAbsolute3, join as join5, relative as relative5, resolve as resolve2 } from "path";
|
|
3342
|
+
import * as ts5 from "typescript";
|
|
3343
|
+
var RESOLUTION_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3344
|
+
var DEFAULT_COMPILER_OPTIONS = {
|
|
3345
|
+
allowImportingTsExtensions: true,
|
|
3346
|
+
allowJs: true,
|
|
3347
|
+
allowSyntheticDefaultImports: true,
|
|
3348
|
+
checkJs: false,
|
|
3349
|
+
esModuleInterop: true,
|
|
3350
|
+
jsx: ts5.JsxEmit.ReactJSX,
|
|
3351
|
+
module: ts5.ModuleKind.ESNext,
|
|
3352
|
+
moduleResolution: ts5.ModuleResolutionKind.Bundler,
|
|
3353
|
+
noEmit: true,
|
|
3354
|
+
resolveJsonModule: true,
|
|
3355
|
+
skipLibCheck: true,
|
|
3356
|
+
target: ts5.ScriptTarget.ES2022
|
|
3357
|
+
};
|
|
3358
|
+
function findProjectTsConfig(projectRoot, tsconfigPath) {
|
|
3359
|
+
if (tsconfigPath === null) return null;
|
|
3360
|
+
if (tsconfigPath) {
|
|
3361
|
+
const absolutePath = isAbsolute3(tsconfigPath) ? resolve2(tsconfigPath) : resolve2(projectRoot, tsconfigPath);
|
|
3362
|
+
return existsSync5(absolutePath) ? absolutePath : null;
|
|
3363
|
+
}
|
|
3364
|
+
const localTsConfig = join5(projectRoot, "tsconfig.json");
|
|
3365
|
+
return existsSync5(localTsConfig) ? localTsConfig : null;
|
|
3366
|
+
}
|
|
3367
|
+
function fallbackCompilerConfig(tsconfigPath, options, diagnostics = []) {
|
|
3368
|
+
return {
|
|
3369
|
+
tsconfigPath,
|
|
3370
|
+
compilerOptions: {
|
|
3371
|
+
...DEFAULT_COMPILER_OPTIONS,
|
|
3372
|
+
...options.compilerOptions,
|
|
3373
|
+
allowJs: true,
|
|
3374
|
+
noEmit: true,
|
|
3375
|
+
skipLibCheck: true
|
|
3376
|
+
},
|
|
3377
|
+
diagnostics
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
function readCompilerConfig(projectRoot, options) {
|
|
3381
|
+
const tsconfigPath = findProjectTsConfig(projectRoot, options.tsconfigPath);
|
|
3382
|
+
if (!tsconfigPath) return fallbackCompilerConfig(null, options);
|
|
3383
|
+
const parsedJson = ts5.parseConfigFileTextToJson(
|
|
3384
|
+
tsconfigPath,
|
|
3385
|
+
readFileSync5(tsconfigPath, "utf-8")
|
|
3386
|
+
);
|
|
3387
|
+
if (parsedJson.error) return fallbackCompilerConfig(tsconfigPath, options, [parsedJson.error]);
|
|
3388
|
+
const parsed = ts5.parseJsonConfigFileContent(
|
|
3389
|
+
parsedJson.config,
|
|
3390
|
+
ts5.sys,
|
|
3391
|
+
dirname(tsconfigPath),
|
|
3392
|
+
DEFAULT_COMPILER_OPTIONS,
|
|
3393
|
+
tsconfigPath
|
|
3394
|
+
);
|
|
3395
|
+
return {
|
|
3396
|
+
tsconfigPath,
|
|
3397
|
+
compilerOptions: {
|
|
3398
|
+
...DEFAULT_COMPILER_OPTIONS,
|
|
3399
|
+
...parsed.options,
|
|
3400
|
+
...options.compilerOptions,
|
|
3401
|
+
allowJs: true,
|
|
3402
|
+
noEmit: true,
|
|
3403
|
+
skipLibCheck: true
|
|
3404
|
+
},
|
|
3405
|
+
diagnostics: parsed.errors
|
|
3406
|
+
};
|
|
3407
|
+
}
|
|
3408
|
+
function inventoryFileByAbsolutePath(inventory) {
|
|
3409
|
+
return new Map(
|
|
3410
|
+
inventory.files.map((file) => [normalizeSourcePath(resolve2(file.absolutePath)), file])
|
|
3411
|
+
);
|
|
3412
|
+
}
|
|
3413
|
+
function createProjectSourceProgram(projectRoot, options = {}) {
|
|
3414
|
+
const inventory = createSourceInventory(projectRoot, options);
|
|
3415
|
+
const config = readCompilerConfig(inventory.projectRoot, options);
|
|
3416
|
+
const host = ts5.createCompilerHost(config.compilerOptions, true);
|
|
3417
|
+
const program = ts5.createProgram({
|
|
3418
|
+
rootNames: inventory.files.map((file) => file.absolutePath),
|
|
3419
|
+
options: config.compilerOptions,
|
|
3420
|
+
host
|
|
3421
|
+
});
|
|
3422
|
+
return {
|
|
3423
|
+
projectRoot: inventory.projectRoot,
|
|
3424
|
+
tsconfigPath: config.tsconfigPath,
|
|
3425
|
+
inventory,
|
|
3426
|
+
program,
|
|
3427
|
+
compilerOptions: config.compilerOptions,
|
|
3428
|
+
diagnostics: [...config.diagnostics, ...program.getOptionsDiagnostics()]
|
|
3429
|
+
};
|
|
3430
|
+
}
|
|
3431
|
+
function getProjectSourceFile(context, pathOrSourceFile) {
|
|
3432
|
+
if (typeof pathOrSourceFile !== "string") return pathOrSourceFile;
|
|
3433
|
+
const absolutePath = isAbsolute3(pathOrSourceFile) ? resolve2(pathOrSourceFile) : resolve2(context.projectRoot, pathOrSourceFile);
|
|
3434
|
+
const normalized = normalizeSourcePath(absolutePath);
|
|
3435
|
+
return context.program.getSourceFiles().find((sourceFile) => normalizeSourcePath(resolve2(sourceFile.fileName)) === normalized);
|
|
3436
|
+
}
|
|
3437
|
+
function sourceFileRelativePath(context, sourceFile) {
|
|
3438
|
+
return normalizeSourcePath(
|
|
3439
|
+
relative5(context.projectRoot, sourceFile.fileName) || sourceFile.fileName
|
|
3440
|
+
);
|
|
3441
|
+
}
|
|
3442
|
+
function sourceLocationLineAndColumn(sourceFile, node) {
|
|
3443
|
+
const location = sourceLocationForNode(sourceFile, node);
|
|
3444
|
+
return { line: location.line, column: location.column };
|
|
3445
|
+
}
|
|
3446
|
+
function bindingNames(name) {
|
|
3447
|
+
if (ts5.isIdentifier(name)) return [name.text];
|
|
3448
|
+
return name.elements.flatMap((element) => {
|
|
3449
|
+
if (ts5.isOmittedExpression(element)) return [];
|
|
3450
|
+
return bindingNames(element.name);
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
function importSourceText(node) {
|
|
3454
|
+
if ((ts5.isImportDeclaration(node) || ts5.isExportDeclaration(node)) && node.moduleSpecifier && ts5.isStringLiteral(node.moduleSpecifier)) {
|
|
3455
|
+
return node.moduleSpecifier.text;
|
|
3456
|
+
}
|
|
3457
|
+
if (ts5.isImportEqualsDeclaration(node) && ts5.isExternalModuleReference(node.moduleReference) && node.moduleReference.expression && ts5.isStringLiteral(node.moduleReference.expression)) {
|
|
3458
|
+
return node.moduleReference.expression.text;
|
|
3459
|
+
}
|
|
3460
|
+
if (ts5.isCallExpression(node) && node.arguments.length > 0 && ts5.isStringLiteral(node.arguments[0])) {
|
|
3461
|
+
if (node.expression.kind === ts5.SyntaxKind.ImportKeyword) return node.arguments[0].text;
|
|
3462
|
+
if (ts5.isIdentifier(node.expression) && node.expression.text === "require") {
|
|
3463
|
+
return node.arguments[0].text;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
return null;
|
|
3467
|
+
}
|
|
3468
|
+
function hasExternalPackageShape(specifier) {
|
|
3469
|
+
return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("#");
|
|
3470
|
+
}
|
|
3471
|
+
function manualResolutionCandidates(context, importerPath, specifier) {
|
|
3472
|
+
const candidates = [];
|
|
3473
|
+
const addCandidates = (base) => {
|
|
3474
|
+
candidates.push(base);
|
|
3475
|
+
if (extname5(base)) return;
|
|
3476
|
+
for (const extension of RESOLUTION_EXTENSIONS) candidates.push(`${base}${extension}`);
|
|
3477
|
+
for (const extension of RESOLUTION_EXTENSIONS) {
|
|
3478
|
+
candidates.push(join5(base, `index${extension}`));
|
|
3479
|
+
}
|
|
3480
|
+
};
|
|
3481
|
+
if (specifier.startsWith(".") || specifier.startsWith("/")) {
|
|
3482
|
+
const base = specifier.startsWith("/") ? resolve2(context.projectRoot, specifier.slice(1)) : resolve2(dirname(importerPath), specifier);
|
|
3483
|
+
addCandidates(base);
|
|
3484
|
+
} else if (specifier.startsWith("@/")) {
|
|
3485
|
+
addCandidates(resolve2(context.projectRoot, specifier.slice(2)));
|
|
3486
|
+
addCandidates(resolve2(context.projectRoot, "src", specifier.slice(2)));
|
|
3487
|
+
}
|
|
3488
|
+
return candidates;
|
|
3489
|
+
}
|
|
3490
|
+
function resolveFromInventory(context, source, importerPath) {
|
|
3491
|
+
const inventoryByPath = inventoryFileByAbsolutePath(context.inventory);
|
|
3492
|
+
for (const candidate of manualResolutionCandidates(context, importerPath, source)) {
|
|
3493
|
+
const absolutePath = normalizeSourcePath(resolve2(candidate));
|
|
3494
|
+
const inventoryFile2 = inventoryByPath.get(absolutePath);
|
|
3495
|
+
if (!inventoryFile2 || !existsSync5(inventoryFile2.absolutePath) || !statSync4(inventoryFile2.absolutePath).isFile()) {
|
|
3496
|
+
continue;
|
|
3497
|
+
}
|
|
3498
|
+
return {
|
|
3499
|
+
source,
|
|
3500
|
+
importer: normalizeSourcePath(relative5(context.projectRoot, importerPath) || importerPath),
|
|
3501
|
+
kind: "project-local",
|
|
3502
|
+
resolvedFileName: inventoryFile2.absolutePath,
|
|
3503
|
+
relativePath: inventoryFile2.relativePath,
|
|
3504
|
+
extension: inventoryFile2.extension,
|
|
3505
|
+
isProjectLocal: true,
|
|
3506
|
+
isExternal: false,
|
|
3507
|
+
failed: false
|
|
3508
|
+
};
|
|
3509
|
+
}
|
|
3510
|
+
return null;
|
|
3511
|
+
}
|
|
3512
|
+
function resolveSourceImport(context, importer, source) {
|
|
3513
|
+
const sourceFile = getProjectSourceFile(context, importer);
|
|
3514
|
+
const importerPath = sourceFile ? resolve2(sourceFile.fileName) : isAbsolute3(String(importer)) ? resolve2(String(importer)) : resolve2(context.projectRoot, String(importer));
|
|
3515
|
+
const importerRelativePath = normalizeSourcePath(
|
|
3516
|
+
relative5(context.projectRoot, importerPath) || importerPath
|
|
3517
|
+
);
|
|
3518
|
+
const inventoryByPath = inventoryFileByAbsolutePath(context.inventory);
|
|
3519
|
+
const resolved = ts5.resolveModuleName(
|
|
3520
|
+
source,
|
|
3521
|
+
importerPath,
|
|
3522
|
+
context.compilerOptions,
|
|
3523
|
+
ts5.sys
|
|
3524
|
+
).resolvedModule;
|
|
3525
|
+
if (resolved) {
|
|
3526
|
+
const absolutePath = normalizeSourcePath(resolve2(resolved.resolvedFileName));
|
|
3527
|
+
const inventoryFile2 = inventoryByPath.get(absolutePath);
|
|
3528
|
+
if (inventoryFile2 && isPathInsideProject(context.projectRoot, absolutePath)) {
|
|
3529
|
+
return {
|
|
3530
|
+
source,
|
|
3531
|
+
importer: importerRelativePath,
|
|
3532
|
+
kind: "project-local",
|
|
3533
|
+
resolvedFileName: inventoryFile2.absolutePath,
|
|
3534
|
+
relativePath: inventoryFile2.relativePath,
|
|
3535
|
+
extension: inventoryFile2.extension,
|
|
3536
|
+
isProjectLocal: true,
|
|
3537
|
+
isExternal: false,
|
|
3538
|
+
failed: false
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
return {
|
|
3542
|
+
source,
|
|
3543
|
+
importer: importerRelativePath,
|
|
3544
|
+
kind: hasExternalPackageShape(source) ? "external" : "unresolved",
|
|
3545
|
+
resolvedFileName: resolved.resolvedFileName,
|
|
3546
|
+
relativePath: null,
|
|
3547
|
+
extension: extname5(resolved.resolvedFileName).toLowerCase() || null,
|
|
3548
|
+
isProjectLocal: false,
|
|
3549
|
+
isExternal: hasExternalPackageShape(source),
|
|
3550
|
+
failed: !hasExternalPackageShape(source)
|
|
3551
|
+
};
|
|
3552
|
+
}
|
|
3553
|
+
const fallback = resolveFromInventory(context, source, importerPath);
|
|
3554
|
+
if (fallback) return fallback;
|
|
3555
|
+
return {
|
|
3556
|
+
source,
|
|
3557
|
+
importer: importerRelativePath,
|
|
3558
|
+
kind: hasExternalPackageShape(source) ? "external" : "unresolved",
|
|
3559
|
+
resolvedFileName: null,
|
|
3560
|
+
relativePath: null,
|
|
3561
|
+
extension: null,
|
|
3562
|
+
isProjectLocal: false,
|
|
3563
|
+
isExternal: hasExternalPackageShape(source),
|
|
3564
|
+
failed: !hasExternalPackageShape(source)
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
function importReferenceBase(context, sourceFile, node, source, kind, localNames, imported = [], extra = {}) {
|
|
3568
|
+
const location = sourceLocationLineAndColumn(sourceFile, node);
|
|
3569
|
+
return {
|
|
3570
|
+
file: sourceFileRelativePath(context, sourceFile),
|
|
3571
|
+
source,
|
|
3572
|
+
kind,
|
|
3573
|
+
line: location.line,
|
|
3574
|
+
column: location.column,
|
|
3575
|
+
imported,
|
|
3576
|
+
localNames,
|
|
3577
|
+
typeOnly: extra.typeOnly ?? false,
|
|
3578
|
+
resolved: resolveSourceImport(context, sourceFile, source),
|
|
3579
|
+
...extra.defaultImport ? { defaultImport: extra.defaultImport } : {},
|
|
3580
|
+
...extra.namespaceImport ? { namespaceImport: extra.namespaceImport } : {}
|
|
3581
|
+
};
|
|
3582
|
+
}
|
|
3583
|
+
function collectSourceImports(context, pathOrSourceFile) {
|
|
3584
|
+
const sourceFile = getProjectSourceFile(context, pathOrSourceFile);
|
|
3585
|
+
if (!sourceFile) return [];
|
|
3586
|
+
const imports = [];
|
|
3587
|
+
const visit = (node) => {
|
|
3588
|
+
if (ts5.isImportDeclaration(node)) {
|
|
3589
|
+
const source = importSourceText(node);
|
|
3590
|
+
if (source) {
|
|
3591
|
+
const imported = [];
|
|
3592
|
+
const localNames = [];
|
|
3593
|
+
let defaultImport;
|
|
3594
|
+
let namespaceImport;
|
|
3595
|
+
let typeOnly = node.importClause?.isTypeOnly ?? false;
|
|
3596
|
+
if (node.importClause?.name) {
|
|
3597
|
+
defaultImport = node.importClause.name.text;
|
|
3598
|
+
localNames.push(defaultImport);
|
|
3599
|
+
}
|
|
3600
|
+
const namedBindings = node.importClause?.namedBindings;
|
|
3601
|
+
if (namedBindings && ts5.isNamedImports(namedBindings)) {
|
|
3602
|
+
for (const element of namedBindings.elements) {
|
|
3603
|
+
imported.push((element.propertyName ?? element.name).text);
|
|
3604
|
+
localNames.push(element.name.text);
|
|
3605
|
+
typeOnly ||= element.isTypeOnly;
|
|
3606
|
+
}
|
|
3607
|
+
} else if (namedBindings && ts5.isNamespaceImport(namedBindings)) {
|
|
3608
|
+
namespaceImport = namedBindings.name.text;
|
|
3609
|
+
localNames.push(namespaceImport);
|
|
3610
|
+
}
|
|
3611
|
+
imports.push(
|
|
3612
|
+
importReferenceBase(
|
|
3613
|
+
context,
|
|
3614
|
+
sourceFile,
|
|
3615
|
+
node,
|
|
3616
|
+
source,
|
|
3617
|
+
"static-import",
|
|
3618
|
+
localNames,
|
|
3619
|
+
imported,
|
|
3620
|
+
{
|
|
3621
|
+
...defaultImport ? { defaultImport } : {},
|
|
3622
|
+
...namespaceImport ? { namespaceImport } : {},
|
|
3623
|
+
typeOnly
|
|
3624
|
+
}
|
|
3625
|
+
)
|
|
3626
|
+
);
|
|
3627
|
+
}
|
|
3628
|
+
} else if (ts5.isExportDeclaration(node)) {
|
|
3629
|
+
const source = importSourceText(node);
|
|
3630
|
+
if (source) {
|
|
3631
|
+
const exported = node.exportClause && ts5.isNamedExports(node.exportClause) ? node.exportClause.elements.map(
|
|
3632
|
+
(element) => (element.propertyName ?? element.name).text
|
|
3633
|
+
) : [];
|
|
3634
|
+
imports.push(
|
|
3635
|
+
importReferenceBase(context, sourceFile, node, source, "re-export", [], exported, {
|
|
3636
|
+
typeOnly: node.isTypeOnly
|
|
3637
|
+
})
|
|
3638
|
+
);
|
|
3639
|
+
}
|
|
3640
|
+
} else if (ts5.isImportEqualsDeclaration(node)) {
|
|
3641
|
+
const source = importSourceText(node);
|
|
3642
|
+
if (source) {
|
|
3643
|
+
imports.push(
|
|
3644
|
+
importReferenceBase(context, sourceFile, node, source, "import-equals", [node.name.text])
|
|
3645
|
+
);
|
|
3646
|
+
}
|
|
3647
|
+
} else if (ts5.isCallExpression(node)) {
|
|
3648
|
+
const source = importSourceText(node);
|
|
3649
|
+
if (source) {
|
|
3650
|
+
const kind = node.expression.kind === ts5.SyntaxKind.ImportKeyword ? "dynamic-import" : "require";
|
|
3651
|
+
const parent = node.parent;
|
|
3652
|
+
const localNames = ts5.isVariableDeclaration(parent) && parent.initializer === node ? bindingNames(parent.name) : [];
|
|
3653
|
+
imports.push(importReferenceBase(context, sourceFile, node, source, kind, localNames));
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
ts5.forEachChild(node, visit);
|
|
3657
|
+
};
|
|
3658
|
+
visit(sourceFile);
|
|
3659
|
+
return imports;
|
|
3660
|
+
}
|
|
3661
|
+
function findImportedFrom(identifier) {
|
|
3662
|
+
let node = identifier;
|
|
3663
|
+
while (node) {
|
|
3664
|
+
if (ts5.isImportDeclaration(node) || ts5.isExportDeclaration(node) || ts5.isImportEqualsDeclaration(node)) {
|
|
3665
|
+
const source = importSourceText(node);
|
|
3666
|
+
return {
|
|
3667
|
+
...source ? { importSource: source } : {},
|
|
3668
|
+
importedFrom: ts5.SyntaxKind[node.kind]
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
node = node.parent;
|
|
3672
|
+
}
|
|
3673
|
+
return {};
|
|
3674
|
+
}
|
|
3675
|
+
function preferImportBinding(a, b) {
|
|
3676
|
+
if (!a) return b;
|
|
3677
|
+
const aImport = Boolean(findImportedFrom(a).importSource);
|
|
3678
|
+
const bImport = Boolean(findImportedFrom(b).importSource);
|
|
3679
|
+
if (aImport === bImport) return a;
|
|
3680
|
+
return bImport ? b : a;
|
|
3681
|
+
}
|
|
3682
|
+
function findIdentifier(sourceFile, name, position) {
|
|
3683
|
+
let matched = null;
|
|
3684
|
+
const visit = (node) => {
|
|
3685
|
+
if (matched && position !== void 0) return;
|
|
3686
|
+
if (ts5.isIdentifier(node) && node.text === name) {
|
|
3687
|
+
if (position === void 0) {
|
|
3688
|
+
matched = preferImportBinding(matched, node);
|
|
3689
|
+
} else if (node.getStart(sourceFile) <= position && position <= node.getEnd()) {
|
|
3690
|
+
matched = node;
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
ts5.forEachChild(node, visit);
|
|
3695
|
+
};
|
|
3696
|
+
visit(sourceFile);
|
|
3697
|
+
return matched;
|
|
3698
|
+
}
|
|
3699
|
+
function declarationKind(declaration) {
|
|
3700
|
+
return ts5.SyntaxKind[declaration.kind] ?? "Declaration";
|
|
3701
|
+
}
|
|
3702
|
+
function resolveSourceSymbolOrigin(context, pathOrSourceFile, localName, options = {}) {
|
|
3703
|
+
const sourceFile = getProjectSourceFile(context, pathOrSourceFile);
|
|
3704
|
+
if (!sourceFile) return null;
|
|
3705
|
+
const identifier = findIdentifier(sourceFile, localName, options.position);
|
|
3706
|
+
if (!identifier) return null;
|
|
3707
|
+
const checker = context.program.getTypeChecker();
|
|
3708
|
+
const symbol = checker.getSymbolAtLocation(identifier);
|
|
3709
|
+
if (!symbol) return null;
|
|
3710
|
+
const originSymbol = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
3711
|
+
const declarations = originSymbol.declarations ?? symbol.declarations ?? [];
|
|
3712
|
+
if (declarations.length === 0) return null;
|
|
3713
|
+
const projectFiles = inventoryFileByAbsolutePath(context.inventory);
|
|
3714
|
+
const declaration = declarations.find(
|
|
3715
|
+
(entry) => projectFiles.has(normalizeSourcePath(resolve2(entry.getSourceFile().fileName)))
|
|
3716
|
+
) ?? declarations[0];
|
|
3717
|
+
const declarationFile = declaration.getSourceFile();
|
|
3718
|
+
const declarationPath = normalizeSourcePath(resolve2(declarationFile.fileName));
|
|
3719
|
+
const projectFile = projectFiles.get(declarationPath);
|
|
3720
|
+
const isProjectLocal = Boolean(projectFile);
|
|
3721
|
+
if (!isProjectLocal && !options.includeExternal) return null;
|
|
3722
|
+
const imported = findImportedFrom(identifier);
|
|
3723
|
+
return {
|
|
3724
|
+
name: originSymbol.getName(),
|
|
3725
|
+
localName,
|
|
3726
|
+
file: projectFile?.relativePath ?? normalizeSourcePath(declarationFile.fileName),
|
|
3727
|
+
absolutePath: projectFile?.absolutePath ?? declarationPath,
|
|
3728
|
+
location: sourceLocationForNode(declarationFile, declaration),
|
|
3729
|
+
declarationKind: declarationKind(declaration),
|
|
3730
|
+
isProjectLocal,
|
|
3731
|
+
...imported
|
|
3732
|
+
};
|
|
3733
|
+
}
|
|
3734
|
+
|
|
2968
3735
|
// src/index.ts
|
|
2969
3736
|
var VERIFICATION_SCHEMA_URLS = {
|
|
2970
3737
|
common: "https://decantr.ai/schemas/verification-report.common.v1.json",
|
|
@@ -2982,16 +3749,16 @@ function hashString(value) {
|
|
|
2982
3749
|
return createHash("sha256").update(value).digest("hex").slice(0, 16);
|
|
2983
3750
|
}
|
|
2984
3751
|
function hashFile(path) {
|
|
2985
|
-
if (!
|
|
3752
|
+
if (!existsSync6(path)) return null;
|
|
2986
3753
|
try {
|
|
2987
|
-
return createHash("sha256").update(
|
|
3754
|
+
return createHash("sha256").update(readFileSync6(path)).digest("hex");
|
|
2988
3755
|
} catch {
|
|
2989
3756
|
return null;
|
|
2990
3757
|
}
|
|
2991
3758
|
}
|
|
2992
3759
|
function provenanceEntry(projectRoot, relativePath) {
|
|
2993
|
-
const path =
|
|
2994
|
-
if (!
|
|
3760
|
+
const path = join6(projectRoot, relativePath);
|
|
3761
|
+
if (!existsSync6(path)) {
|
|
2995
3762
|
return {
|
|
2996
3763
|
path: relativePath,
|
|
2997
3764
|
present: false,
|
|
@@ -3001,7 +3768,7 @@ function provenanceEntry(projectRoot, relativePath) {
|
|
|
3001
3768
|
}
|
|
3002
3769
|
let generatedAt = null;
|
|
3003
3770
|
try {
|
|
3004
|
-
generatedAt =
|
|
3771
|
+
generatedAt = statSync5(path).mtime.toISOString();
|
|
3005
3772
|
} catch {
|
|
3006
3773
|
generatedAt = null;
|
|
3007
3774
|
}
|
|
@@ -3013,7 +3780,7 @@ function provenanceEntry(projectRoot, relativePath) {
|
|
|
3013
3780
|
};
|
|
3014
3781
|
}
|
|
3015
3782
|
function provenanceForPath(projectRoot, path) {
|
|
3016
|
-
const rel =
|
|
3783
|
+
const rel = isAbsolute4(path) ? relative6(projectRoot, path).replace(/\\/g, "/") : path;
|
|
3017
3784
|
return provenanceEntry(projectRoot, rel && !rel.startsWith("..") ? rel : basename2(path));
|
|
3018
3785
|
}
|
|
3019
3786
|
function redactEvidenceText(projectRoot, value) {
|
|
@@ -3150,7 +3917,7 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
3150
3917
|
const assertions = [];
|
|
3151
3918
|
const essence = audit?.essence;
|
|
3152
3919
|
const v4 = essence && isV4(essence) ? essence : null;
|
|
3153
|
-
const contextDir =
|
|
3920
|
+
const contextDir = join6(projectRoot, ".decantr", "context");
|
|
3154
3921
|
const packManifest = audit?.packManifest ?? null;
|
|
3155
3922
|
assertions.push(
|
|
3156
3923
|
assertion({
|
|
@@ -3160,7 +3927,7 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
3160
3927
|
rule: "essence-present",
|
|
3161
3928
|
status: essence ? "passed" : "failed",
|
|
3162
3929
|
message: essence ? "Decantr Essence contract is present." : "No Decantr Essence contract was found.",
|
|
3163
|
-
evidence: [redactEvidenceText(projectRoot,
|
|
3930
|
+
evidence: [redactEvidenceText(projectRoot, join6(projectRoot, "decantr.essence.json"))],
|
|
3164
3931
|
suggestedFix: essence ? void 0 : "Run `decantr init` or restore decantr.essence.json."
|
|
3165
3932
|
})
|
|
3166
3933
|
);
|
|
@@ -3179,7 +3946,8 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
3179
3946
|
if (v4) {
|
|
3180
3947
|
const declaredRoutes = Object.keys(v4.blueprint.routes ?? {}).sort();
|
|
3181
3948
|
for (const route of declaredRoutes) {
|
|
3182
|
-
const routeTarget =
|
|
3949
|
+
const routeTarget = v4.blueprint.routes?.[route];
|
|
3950
|
+
if (!routeTarget) continue;
|
|
3183
3951
|
const section = v4.blueprint.sections.find((entry) => entry.id === routeTarget.section);
|
|
3184
3952
|
const page = section?.pages.find((entry) => entry.id === routeTarget.page);
|
|
3185
3953
|
assertions.push(
|
|
@@ -3232,7 +4000,7 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
3232
4000
|
rule: "pack-manifest-present",
|
|
3233
4001
|
status: packManifest ? "passed" : "failed",
|
|
3234
4002
|
message: packManifest ? "Compiled execution pack manifest is present." : "Compiled execution pack manifest is missing.",
|
|
3235
|
-
evidence: [redactEvidenceText(projectRoot,
|
|
4003
|
+
evidence: [redactEvidenceText(projectRoot, join6(contextDir, "pack-manifest.json"))],
|
|
3236
4004
|
suggestedFix: packManifest ? void 0 : "Run `decantr registry compile-packs decantr.essence.json --write-context` to hydrate the full context pack bundle."
|
|
3237
4005
|
})
|
|
3238
4006
|
);
|
|
@@ -3244,21 +4012,21 @@ function createContractAssertions(projectRoot, audit) {
|
|
|
3244
4012
|
rule: "review-pack-present",
|
|
3245
4013
|
status: audit?.reviewPack ? "passed" : "failed",
|
|
3246
4014
|
message: audit?.reviewPack ? "Compiled review pack is present." : "Compiled review pack is missing.",
|
|
3247
|
-
evidence: [redactEvidenceText(projectRoot,
|
|
4015
|
+
evidence: [redactEvidenceText(projectRoot, join6(contextDir, "review-pack.json"))],
|
|
3248
4016
|
suggestedFix: audit?.reviewPack ? void 0 : "Run `decantr registry compile-packs decantr.essence.json --write-context` so critique has the compiled review contract."
|
|
3249
4017
|
})
|
|
3250
4018
|
);
|
|
3251
|
-
const tokensPath =
|
|
4019
|
+
const tokensPath = join6(projectRoot, "src", "styles", "tokens.css");
|
|
3252
4020
|
assertions.push(
|
|
3253
4021
|
assertion({
|
|
3254
4022
|
id: "contract.design-token.tokens-file",
|
|
3255
4023
|
category: "design-token",
|
|
3256
|
-
severity:
|
|
4024
|
+
severity: existsSync6(tokensPath) ? "info" : "warn",
|
|
3257
4025
|
rule: "tokens-file-present",
|
|
3258
|
-
status:
|
|
3259
|
-
message:
|
|
4026
|
+
status: existsSync6(tokensPath) ? "passed" : "failed",
|
|
4027
|
+
message: existsSync6(tokensPath) ? "Decantr token CSS file is present." : "Decantr token CSS file was not found.",
|
|
3260
4028
|
evidence: [redactEvidenceText(projectRoot, tokensPath)],
|
|
3261
|
-
suggestedFix:
|
|
4029
|
+
suggestedFix: existsSync6(tokensPath) ? void 0 : "Run `decantr refresh` or map Decantr tokens into the existing styling system."
|
|
3262
4030
|
})
|
|
3263
4031
|
);
|
|
3264
4032
|
return assertions;
|
|
@@ -3267,9 +4035,9 @@ function createEvidenceBundle(input) {
|
|
|
3267
4035
|
const assertions = input.assertions ?? createContractAssertions(input.projectRoot, input.audit);
|
|
3268
4036
|
let resolvedProjectRoot = input.projectRoot;
|
|
3269
4037
|
try {
|
|
3270
|
-
resolvedProjectRoot =
|
|
4038
|
+
resolvedProjectRoot = realpathSync2(input.projectRoot);
|
|
3271
4039
|
} catch {
|
|
3272
|
-
resolvedProjectRoot =
|
|
4040
|
+
resolvedProjectRoot = resolve3(input.projectRoot);
|
|
3273
4041
|
}
|
|
3274
4042
|
const projectId = `project_${hashString(resolvedProjectRoot)}`;
|
|
3275
4043
|
return {
|
|
@@ -3371,21 +4139,21 @@ function scoreRatio(numerator, denominator) {
|
|
|
3371
4139
|
return Math.min(5, Math.max(1, Math.round(numerator / denominator * 5)));
|
|
3372
4140
|
}
|
|
3373
4141
|
function readJsonIfExists(path) {
|
|
3374
|
-
if (!
|
|
4142
|
+
if (!existsSync6(path)) return null;
|
|
3375
4143
|
try {
|
|
3376
|
-
return JSON.parse(
|
|
4144
|
+
return JSON.parse(readFileSync6(path, "utf-8"));
|
|
3377
4145
|
} catch {
|
|
3378
4146
|
return null;
|
|
3379
4147
|
}
|
|
3380
4148
|
}
|
|
3381
4149
|
function loadReviewPack(projectRoot) {
|
|
3382
4150
|
return readJsonIfExists(
|
|
3383
|
-
|
|
4151
|
+
join6(projectRoot, ".decantr", "context", "review-pack.json")
|
|
3384
4152
|
);
|
|
3385
4153
|
}
|
|
3386
4154
|
function loadPackManifest(projectRoot) {
|
|
3387
4155
|
return readJsonIfExists(
|
|
3388
|
-
|
|
4156
|
+
join6(projectRoot, ".decantr", "context", "pack-manifest.json")
|
|
3389
4157
|
);
|
|
3390
4158
|
}
|
|
3391
4159
|
function collectPackManifestReferences(packManifest) {
|
|
@@ -3434,14 +4202,14 @@ function collectPackManifestReferences(packManifest) {
|
|
|
3434
4202
|
}
|
|
3435
4203
|
function collectMissingPackManifestFiles(projectRoot, packManifest = loadPackManifest(projectRoot)) {
|
|
3436
4204
|
if (!packManifest) return [];
|
|
3437
|
-
const contextDir =
|
|
4205
|
+
const contextDir = join6(projectRoot, ".decantr", "context");
|
|
3438
4206
|
const missing = [];
|
|
3439
4207
|
for (const reference of collectPackManifestReferences(packManifest)) {
|
|
3440
4208
|
for (const field of ["markdown", "json"]) {
|
|
3441
4209
|
const fileName = reference[field];
|
|
3442
4210
|
if (!fileName) continue;
|
|
3443
|
-
const absolutePath =
|
|
3444
|
-
if (
|
|
4211
|
+
const absolutePath = join6(contextDir, fileName);
|
|
4212
|
+
if (existsSync6(absolutePath)) continue;
|
|
3445
4213
|
missing.push({
|
|
3446
4214
|
entryId: reference.entryId,
|
|
3447
4215
|
kind: reference.kind,
|
|
@@ -3455,13 +4223,13 @@ function collectMissingPackManifestFiles(projectRoot, packManifest = loadPackMan
|
|
|
3455
4223
|
}
|
|
3456
4224
|
function readTextIfExists(path) {
|
|
3457
4225
|
try {
|
|
3458
|
-
return
|
|
4226
|
+
return existsSync6(path) ? readFileSync6(path, "utf-8") : "";
|
|
3459
4227
|
} catch {
|
|
3460
4228
|
return "";
|
|
3461
4229
|
}
|
|
3462
4230
|
}
|
|
3463
4231
|
function readProjectAdoptionMode(projectRoot) {
|
|
3464
|
-
const projectJson = readJsonIfExists(
|
|
4232
|
+
const projectJson = readJsonIfExists(join6(projectRoot, ".decantr", "project.json"));
|
|
3465
4233
|
const adoptionMode = projectJson?.initialized?.adoptionMode;
|
|
3466
4234
|
return typeof adoptionMode === "string" ? adoptionMode : null;
|
|
3467
4235
|
}
|
|
@@ -3547,7 +4315,7 @@ function collectProjectSourceFiles(projectRoot) {
|
|
|
3547
4315
|
"hooks",
|
|
3548
4316
|
"providers",
|
|
3549
4317
|
"server"
|
|
3550
|
-
].map((dir) =>
|
|
4318
|
+
].map((dir) => join6(projectRoot, dir)).filter((dir) => existsSync6(dir));
|
|
3551
4319
|
const rootFileCandidates = [
|
|
3552
4320
|
"middleware.ts",
|
|
3553
4321
|
"middleware.tsx",
|
|
@@ -3561,7 +4329,7 @@ function collectProjectSourceFiles(projectRoot) {
|
|
|
3561
4329
|
"proxy.jsx",
|
|
3562
4330
|
"proxy.mts",
|
|
3563
4331
|
"proxy.cts"
|
|
3564
|
-
].map((file) =>
|
|
4332
|
+
].map((file) => join6(projectRoot, file)).filter((file) => existsSync6(file));
|
|
3565
4333
|
const files = /* @__PURE__ */ new Set();
|
|
3566
4334
|
const ignoredDirNames = /* @__PURE__ */ new Set([
|
|
3567
4335
|
"node_modules",
|
|
@@ -3572,9 +4340,9 @@ function collectProjectSourceFiles(projectRoot) {
|
|
|
3572
4340
|
"coverage"
|
|
3573
4341
|
]);
|
|
3574
4342
|
const walk = (dir) => {
|
|
3575
|
-
for (const entry of
|
|
4343
|
+
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
3576
4344
|
if (ignoredDirNames.has(entry.name)) continue;
|
|
3577
|
-
const absolutePath =
|
|
4345
|
+
const absolutePath = join6(dir, entry.name);
|
|
3578
4346
|
if (entry.isDirectory()) {
|
|
3579
4347
|
walk(absolutePath);
|
|
3580
4348
|
continue;
|
|
@@ -3605,7 +4373,7 @@ function isAuditableStyleFile(filePath) {
|
|
|
3605
4373
|
return /\.css$/i.test(filePath);
|
|
3606
4374
|
}
|
|
3607
4375
|
function collectProjectStyleFiles2(projectRoot) {
|
|
3608
|
-
const candidates = ["src", "app", "styles"].map((dir) =>
|
|
4376
|
+
const candidates = ["src", "app", "styles"].map((dir) => join6(projectRoot, dir)).filter((dir) => existsSync6(dir));
|
|
3609
4377
|
const files = /* @__PURE__ */ new Set();
|
|
3610
4378
|
const ignoredDirNames = /* @__PURE__ */ new Set([
|
|
3611
4379
|
"node_modules",
|
|
@@ -3616,9 +4384,9 @@ function collectProjectStyleFiles2(projectRoot) {
|
|
|
3616
4384
|
"coverage"
|
|
3617
4385
|
]);
|
|
3618
4386
|
const walk = (dir) => {
|
|
3619
|
-
for (const entry of
|
|
4387
|
+
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
3620
4388
|
if (ignoredDirNames.has(entry.name)) continue;
|
|
3621
|
-
const absolutePath =
|
|
4389
|
+
const absolutePath = join6(dir, entry.name);
|
|
3622
4390
|
if (entry.isDirectory()) {
|
|
3623
4391
|
walk(absolutePath);
|
|
3624
4392
|
continue;
|
|
@@ -3646,15 +4414,15 @@ function countReducedMotionSignals(code) {
|
|
|
3646
4414
|
return patterns.reduce((count, pattern) => count + (pattern.test(code) ? 1 : 0), 0);
|
|
3647
4415
|
}
|
|
3648
4416
|
function hasModuleDirective(filePath, code, directive) {
|
|
3649
|
-
const sourceFile =
|
|
4417
|
+
const sourceFile = ts6.createSourceFile(
|
|
3650
4418
|
filePath,
|
|
3651
4419
|
code,
|
|
3652
|
-
|
|
4420
|
+
ts6.ScriptTarget.Latest,
|
|
3653
4421
|
true,
|
|
3654
4422
|
getScriptKind(filePath)
|
|
3655
4423
|
);
|
|
3656
4424
|
for (const statement of sourceFile.statements) {
|
|
3657
|
-
if (
|
|
4425
|
+
if (ts6.isExpressionStatement(statement) && ts6.isStringLiteralLike(statement.expression)) {
|
|
3658
4426
|
if (statement.expression.text === directive) {
|
|
3659
4427
|
return true;
|
|
3660
4428
|
}
|
|
@@ -3670,20 +4438,20 @@ function importDeclarationHasRuntimeBinding(statement) {
|
|
|
3670
4438
|
if (clause.isTypeOnly) return false;
|
|
3671
4439
|
if (clause.name) return true;
|
|
3672
4440
|
if (!clause.namedBindings) return true;
|
|
3673
|
-
if (
|
|
4441
|
+
if (ts6.isNamespaceImport(clause.namedBindings)) return true;
|
|
3674
4442
|
return clause.namedBindings.elements.some((element) => !element.isTypeOnly);
|
|
3675
4443
|
}
|
|
3676
4444
|
function collectRuntimeImportSpecifiers(entry) {
|
|
3677
|
-
const sourceFile =
|
|
4445
|
+
const sourceFile = ts6.createSourceFile(
|
|
3678
4446
|
entry.relativePath,
|
|
3679
4447
|
entry.code,
|
|
3680
|
-
|
|
4448
|
+
ts6.ScriptTarget.Latest,
|
|
3681
4449
|
true,
|
|
3682
4450
|
getScriptKind(entry.relativePath)
|
|
3683
4451
|
);
|
|
3684
4452
|
const specifiers = [];
|
|
3685
4453
|
for (const statement of sourceFile.statements) {
|
|
3686
|
-
if (
|
|
4454
|
+
if (ts6.isImportDeclaration(statement) && ts6.isStringLiteralLike(statement.moduleSpecifier) && importDeclarationHasRuntimeBinding(statement)) {
|
|
3687
4455
|
specifiers.push(statement.moduleSpecifier.text);
|
|
3688
4456
|
}
|
|
3689
4457
|
}
|
|
@@ -3692,9 +4460,9 @@ function collectRuntimeImportSpecifiers(entry) {
|
|
|
3692
4460
|
function resolveSourceImportTarget(projectRoot, sourceAbsolutePath, specifier) {
|
|
3693
4461
|
let basePath = null;
|
|
3694
4462
|
if (specifier.startsWith("@/")) {
|
|
3695
|
-
basePath =
|
|
4463
|
+
basePath = join6(projectRoot, "src", specifier.slice(2));
|
|
3696
4464
|
} else if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
3697
|
-
basePath =
|
|
4465
|
+
basePath = resolve3(dirname2(sourceAbsolutePath), specifier);
|
|
3698
4466
|
}
|
|
3699
4467
|
if (!basePath) return null;
|
|
3700
4468
|
const candidates = [
|
|
@@ -3705,14 +4473,14 @@ function resolveSourceImportTarget(projectRoot, sourceAbsolutePath, specifier) {
|
|
|
3705
4473
|
`${basePath}.jsx`,
|
|
3706
4474
|
`${basePath}.mts`,
|
|
3707
4475
|
`${basePath}.cts`,
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
4476
|
+
join6(basePath, "index.ts"),
|
|
4477
|
+
join6(basePath, "index.tsx"),
|
|
4478
|
+
join6(basePath, "index.js"),
|
|
4479
|
+
join6(basePath, "index.jsx")
|
|
3712
4480
|
];
|
|
3713
4481
|
for (const candidate of candidates) {
|
|
3714
|
-
if (
|
|
3715
|
-
return
|
|
4482
|
+
if (existsSync6(candidate) && isAuditableSourceFile(candidate)) {
|
|
4483
|
+
return relative6(projectRoot, candidate) || candidate;
|
|
3716
4484
|
}
|
|
3717
4485
|
}
|
|
3718
4486
|
return null;
|
|
@@ -3760,8 +4528,8 @@ function isClientAuthHeaderSource(relativePath, code, clientReachableFiles) {
|
|
|
3760
4528
|
function auditProjectSourceTree(projectRoot, sourceFiles = collectProjectSourceFiles(projectRoot)) {
|
|
3761
4529
|
const sourceEntries = sourceFiles.map((sourceFile) => ({
|
|
3762
4530
|
absolutePath: sourceFile,
|
|
3763
|
-
relativePath:
|
|
3764
|
-
code:
|
|
4531
|
+
relativePath: relative6(projectRoot, sourceFile) || sourceFile,
|
|
4532
|
+
code: readFileSync6(sourceFile, "utf-8")
|
|
3765
4533
|
})).filter((entry) => !isNonProductionSourceAuditFile(entry.relativePath));
|
|
3766
4534
|
const clientReachableFiles = collectClientReachableSourceFiles(projectRoot, sourceEntries);
|
|
3767
4535
|
const summary = {
|
|
@@ -4074,8 +4842,8 @@ function auditProjectStyleContracts(projectRoot) {
|
|
|
4074
4842
|
reducedMotionSignals: createSourceAuditBucket()
|
|
4075
4843
|
};
|
|
4076
4844
|
for (const styleFile of styleFiles) {
|
|
4077
|
-
const relativePath =
|
|
4078
|
-
const css =
|
|
4845
|
+
const relativePath = relative6(projectRoot, styleFile) || styleFile;
|
|
4846
|
+
const css = readFileSync6(styleFile, "utf-8");
|
|
4079
4847
|
recordSourceAudit(summary.focusVisibleSignals, relativePath, countFocusVisibleSignals(css));
|
|
4080
4848
|
recordSourceAudit(summary.reducedMotionSignals, relativePath, countReducedMotionSignals(css));
|
|
4081
4849
|
}
|
|
@@ -4084,15 +4852,15 @@ function auditProjectStyleContracts(projectRoot) {
|
|
|
4084
4852
|
function buildRegistryContext(projectRoot) {
|
|
4085
4853
|
const themeRegistry = /* @__PURE__ */ new Map();
|
|
4086
4854
|
const patternRegistry = /* @__PURE__ */ new Map();
|
|
4087
|
-
const cacheDir =
|
|
4088
|
-
const customDir =
|
|
4089
|
-
const cachedThemesDir =
|
|
4855
|
+
const cacheDir = join6(projectRoot, ".decantr", "cache");
|
|
4856
|
+
const customDir = join6(projectRoot, ".decantr", "custom");
|
|
4857
|
+
const cachedThemesDir = join6(cacheDir, "@official", "themes");
|
|
4090
4858
|
try {
|
|
4091
|
-
if (
|
|
4092
|
-
for (const file of
|
|
4859
|
+
if (existsSync6(cachedThemesDir)) {
|
|
4860
|
+
for (const file of readdirSync5(cachedThemesDir).filter(
|
|
4093
4861
|
(name) => name.endsWith(".json") && name !== "index.json"
|
|
4094
4862
|
)) {
|
|
4095
|
-
const data = JSON.parse(
|
|
4863
|
+
const data = JSON.parse(readFileSync6(join6(cachedThemesDir, file), "utf-8"));
|
|
4096
4864
|
if (data.id && !themeRegistry.has(data.id)) {
|
|
4097
4865
|
themeRegistry.set(data.id, { modes: data.modes || ["light", "dark"] });
|
|
4098
4866
|
}
|
|
@@ -4100,11 +4868,11 @@ function buildRegistryContext(projectRoot) {
|
|
|
4100
4868
|
}
|
|
4101
4869
|
} catch {
|
|
4102
4870
|
}
|
|
4103
|
-
const customThemesDir =
|
|
4871
|
+
const customThemesDir = join6(customDir, "themes");
|
|
4104
4872
|
try {
|
|
4105
|
-
if (
|
|
4106
|
-
for (const file of
|
|
4107
|
-
const data = JSON.parse(
|
|
4873
|
+
if (existsSync6(customThemesDir)) {
|
|
4874
|
+
for (const file of readdirSync5(customThemesDir).filter((name) => name.endsWith(".json"))) {
|
|
4875
|
+
const data = JSON.parse(readFileSync6(join6(customThemesDir, file), "utf-8"));
|
|
4108
4876
|
if (data.id) {
|
|
4109
4877
|
themeRegistry.set(`custom:${data.id}`, { modes: data.modes || ["light", "dark"] });
|
|
4110
4878
|
}
|
|
@@ -4112,13 +4880,13 @@ function buildRegistryContext(projectRoot) {
|
|
|
4112
4880
|
}
|
|
4113
4881
|
} catch {
|
|
4114
4882
|
}
|
|
4115
|
-
const cachedPatternsDir =
|
|
4883
|
+
const cachedPatternsDir = join6(cacheDir, "@official", "patterns");
|
|
4116
4884
|
try {
|
|
4117
|
-
if (
|
|
4118
|
-
for (const file of
|
|
4885
|
+
if (existsSync6(cachedPatternsDir)) {
|
|
4886
|
+
for (const file of readdirSync5(cachedPatternsDir).filter(
|
|
4119
4887
|
(name) => name.endsWith(".json") && name !== "index.json"
|
|
4120
4888
|
)) {
|
|
4121
|
-
const data = JSON.parse(
|
|
4889
|
+
const data = JSON.parse(readFileSync6(join6(cachedPatternsDir, file), "utf-8"));
|
|
4122
4890
|
if (data.id && !patternRegistry.has(data.id)) {
|
|
4123
4891
|
patternRegistry.set(data.id, data);
|
|
4124
4892
|
}
|
|
@@ -4432,8 +5200,8 @@ function extractFailedRouteDocumentHardening(runtimeAudit) {
|
|
|
4432
5200
|
return runtimeAudit.failures.filter((failure) => failure.startsWith("route-document-hardening-failed:")).map((failure) => normalizeRouteHint2(failure.slice("route-document-hardening-failed:".length))).filter(Boolean);
|
|
4433
5201
|
}
|
|
4434
5202
|
function appendRuntimeAuditFindings(findings, runtimeAudit, projectRoot, topology, sourceAudit) {
|
|
4435
|
-
const distPath =
|
|
4436
|
-
const indexPath =
|
|
5203
|
+
const distPath = join6(projectRoot, "dist");
|
|
5204
|
+
const indexPath = join6(distPath, "index.html");
|
|
4437
5205
|
const isFrameworkBuildOutput = runtimeAudit.failures.includes("next-build-output");
|
|
4438
5206
|
if (!runtimeAudit.distPresent) {
|
|
4439
5207
|
findings.push(
|
|
@@ -4978,7 +5746,7 @@ function appendRuntimeAuditFindings(findings, runtimeAudit, projectRoot, topolog
|
|
|
4978
5746
|
}
|
|
4979
5747
|
function readBehaviorPatterns(projectRoot) {
|
|
4980
5748
|
const pack = readJsonIfExists(
|
|
4981
|
-
|
|
5749
|
+
join6(projectRoot, ".decantr", "local-patterns.json")
|
|
4982
5750
|
);
|
|
4983
5751
|
return (pack?.patterns ?? []).filter(
|
|
4984
5752
|
(pattern) => pattern.behavior_obligations && Array.isArray(pattern.behavior_obligations.obligations) && pattern.behavior_obligations.obligations.length > 0
|
|
@@ -5025,15 +5793,15 @@ function isFormPrimitiveDefinitionFile(pattern, relativeFile) {
|
|
|
5025
5793
|
);
|
|
5026
5794
|
}
|
|
5027
5795
|
function sourceAuditFilePath(projectRoot, file) {
|
|
5028
|
-
return
|
|
5796
|
+
return isAbsolute4(file) ? file : join6(projectRoot, file);
|
|
5029
5797
|
}
|
|
5030
5798
|
function sourceAuditRelativePath(projectRoot, file) {
|
|
5031
|
-
return (
|
|
5799
|
+
return (isAbsolute4(file) ? relative6(projectRoot, file) : file).replace(/\\/g, "/");
|
|
5032
5800
|
}
|
|
5033
5801
|
function sourceFileContainsAny(projectRoot, sourceFiles, patterns) {
|
|
5034
5802
|
for (const file of sourceFiles.slice(0, 400)) {
|
|
5035
5803
|
try {
|
|
5036
|
-
const code =
|
|
5804
|
+
const code = readFileSync6(sourceAuditFilePath(projectRoot, file), "utf-8");
|
|
5037
5805
|
if (patterns.some((pattern) => pattern.test(code))) return true;
|
|
5038
5806
|
} catch {
|
|
5039
5807
|
}
|
|
@@ -5087,7 +5855,7 @@ function appendBehaviorObligationFindings(findings, projectRoot, sourceFiles) {
|
|
|
5087
5855
|
const relativeFile = sourceAuditRelativePath(projectRoot, file);
|
|
5088
5856
|
let code = "";
|
|
5089
5857
|
try {
|
|
5090
|
-
code =
|
|
5858
|
+
code = readFileSync6(sourceAuditFilePath(projectRoot, file), "utf-8");
|
|
5091
5859
|
} catch {
|
|
5092
5860
|
continue;
|
|
5093
5861
|
}
|
|
@@ -5164,7 +5932,7 @@ function appendBehaviorObligationFindings(findings, projectRoot, sourceFiles) {
|
|
|
5164
5932
|
const relativeFile = sourceAuditRelativePath(projectRoot, file);
|
|
5165
5933
|
let code = "";
|
|
5166
5934
|
try {
|
|
5167
|
-
code =
|
|
5935
|
+
code = readFileSync6(sourceAuditFilePath(projectRoot, file), "utf-8");
|
|
5168
5936
|
} catch {
|
|
5169
5937
|
continue;
|
|
5170
5938
|
}
|
|
@@ -6486,6 +7254,8 @@ function appendStyleBridgeDriftFindings(findings, audit) {
|
|
|
6486
7254
|
source: finding.source,
|
|
6487
7255
|
property: finding.property,
|
|
6488
7256
|
bridge_mappings: finding.bridgeMappingIds,
|
|
7257
|
+
bridge_confidence: finding.bridgeConfidence,
|
|
7258
|
+
bridge_sources: finding.bridgeSources,
|
|
6489
7259
|
token_hints: finding.tokenHints,
|
|
6490
7260
|
class_hints: finding.classHints
|
|
6491
7261
|
}
|
|
@@ -6529,7 +7299,7 @@ function appendStyleContractFindings(findings, styleAudit, essence) {
|
|
|
6529
7299
|
}
|
|
6530
7300
|
}
|
|
6531
7301
|
async function auditProject(projectRoot) {
|
|
6532
|
-
const essencePath =
|
|
7302
|
+
const essencePath = join6(projectRoot, "decantr.essence.json");
|
|
6533
7303
|
const findings = [];
|
|
6534
7304
|
const reviewPack = loadReviewPack(projectRoot);
|
|
6535
7305
|
const packManifest = loadPackManifest(projectRoot);
|
|
@@ -6537,7 +7307,7 @@ async function auditProject(projectRoot) {
|
|
|
6537
7307
|
const packHydrationOptional = adoptionMode === "contract-only" || adoptionMode === "style-bridge";
|
|
6538
7308
|
const packHydrationSeverity = packHydrationOptional ? "info" : "warn";
|
|
6539
7309
|
const runtimeAudit = emptyRuntimeAudit();
|
|
6540
|
-
if (!
|
|
7310
|
+
if (!existsSync6(essencePath)) {
|
|
6541
7311
|
findings.push(
|
|
6542
7312
|
makeFinding({
|
|
6543
7313
|
id: "essence-missing",
|
|
@@ -6572,7 +7342,7 @@ async function auditProject(projectRoot) {
|
|
|
6572
7342
|
}
|
|
6573
7343
|
let essence = null;
|
|
6574
7344
|
try {
|
|
6575
|
-
essence = JSON.parse(
|
|
7345
|
+
essence = JSON.parse(readFileSync6(essencePath, "utf-8"));
|
|
6576
7346
|
} catch (error) {
|
|
6577
7347
|
findings.push(
|
|
6578
7348
|
makeFinding({
|
|
@@ -6615,7 +7385,7 @@ async function auditProject(projectRoot) {
|
|
|
6615
7385
|
category: "Execution Packs",
|
|
6616
7386
|
severity: packHydrationSeverity,
|
|
6617
7387
|
message: packHydrationOptional ? "Compiled execution pack manifest is not hydrated yet; this is optional for contract-only/style-bridge Brownfield adoption." : "Compiled execution pack manifest is missing.",
|
|
6618
|
-
evidence: [
|
|
7388
|
+
evidence: [join6(projectRoot, ".decantr", "context", "pack-manifest.json")],
|
|
6619
7389
|
suggestedFix: packHydrationOptional ? "Optional: run `decantr registry compile-packs decantr.essence.json --write-context` when you want hosted page packs and review packs for richer assistant context." : "Run `decantr registry compile-packs decantr.essence.json --write-context` to hydrate scaffold, review, mutation, section, and page packs."
|
|
6620
7390
|
})
|
|
6621
7391
|
);
|
|
@@ -6679,7 +7449,7 @@ async function auditProject(projectRoot) {
|
|
|
6679
7449
|
category: "Review Contract",
|
|
6680
7450
|
severity: packHydrationSeverity,
|
|
6681
7451
|
message: packHydrationOptional ? "The compiled review pack file is not hydrated yet; contract-only/style-bridge Brownfield projects can continue without it." : "The compiled review pack file is missing.",
|
|
6682
|
-
evidence: [
|
|
7452
|
+
evidence: [join6(projectRoot, ".decantr", "context", "review-pack.json")],
|
|
6683
7453
|
suggestedFix: packHydrationOptional ? "Optional: hydrate hosted packs later if you want critique consumers to anchor findings to the compiled review contract." : "Hydrate the full hosted context bundle with `decantr registry compile-packs decantr.essence.json --write-context` so critique consumers can anchor findings to the compiled review contract."
|
|
6684
7454
|
})
|
|
6685
7455
|
);
|
|
@@ -6826,74 +7596,74 @@ function countKeyboardShortcutSignals(code) {
|
|
|
6826
7596
|
return matches.length;
|
|
6827
7597
|
}
|
|
6828
7598
|
function getScriptKind(filePath) {
|
|
6829
|
-
switch (
|
|
7599
|
+
switch (extname6(filePath).toLowerCase()) {
|
|
6830
7600
|
case ".tsx":
|
|
6831
|
-
return
|
|
7601
|
+
return ts6.ScriptKind.TSX;
|
|
6832
7602
|
case ".jsx":
|
|
6833
|
-
return
|
|
7603
|
+
return ts6.ScriptKind.JSX;
|
|
6834
7604
|
case ".ts":
|
|
6835
|
-
return
|
|
7605
|
+
return ts6.ScriptKind.TS;
|
|
6836
7606
|
case ".js":
|
|
6837
|
-
return
|
|
7607
|
+
return ts6.ScriptKind.JS;
|
|
6838
7608
|
default:
|
|
6839
|
-
return
|
|
7609
|
+
return ts6.ScriptKind.TSX;
|
|
6840
7610
|
}
|
|
6841
7611
|
}
|
|
6842
7612
|
function isPropertyNamed(node, ...names) {
|
|
6843
7613
|
if (!node) return false;
|
|
6844
|
-
if (
|
|
7614
|
+
if (ts6.isIdentifier(node)) {
|
|
6845
7615
|
return names.includes(node.text);
|
|
6846
7616
|
}
|
|
6847
|
-
if (
|
|
7617
|
+
if (ts6.isPrivateIdentifier(node)) {
|
|
6848
7618
|
return names.includes(node.text);
|
|
6849
7619
|
}
|
|
6850
|
-
if (
|
|
7620
|
+
if (ts6.isStringLiteral(node)) {
|
|
6851
7621
|
return names.includes(node.text);
|
|
6852
7622
|
}
|
|
6853
7623
|
return false;
|
|
6854
7624
|
}
|
|
6855
7625
|
function getJsxAttribute(attributes, ...names) {
|
|
6856
7626
|
return attributes.properties.find(
|
|
6857
|
-
(property) =>
|
|
7627
|
+
(property) => ts6.isJsxAttribute(property) && isPropertyNamed(property.name, ...names)
|
|
6858
7628
|
);
|
|
6859
7629
|
}
|
|
6860
7630
|
function getJsxTagName(node) {
|
|
6861
|
-
if (
|
|
7631
|
+
if (ts6.isIdentifier(node.tagName)) {
|
|
6862
7632
|
return node.tagName.text;
|
|
6863
7633
|
}
|
|
6864
|
-
if (
|
|
7634
|
+
if (ts6.isPropertyAccessExpression(node.tagName)) {
|
|
6865
7635
|
return node.tagName.name.text;
|
|
6866
7636
|
}
|
|
6867
7637
|
return null;
|
|
6868
7638
|
}
|
|
6869
7639
|
function getJsxAttributeLiteralValue(attribute) {
|
|
6870
7640
|
if (!attribute?.initializer) return null;
|
|
6871
|
-
if (
|
|
7641
|
+
if (ts6.isStringLiteral(attribute.initializer)) {
|
|
6872
7642
|
return attribute.initializer.text;
|
|
6873
7643
|
}
|
|
6874
|
-
if (
|
|
7644
|
+
if (ts6.isJsxExpression(attribute.initializer)) {
|
|
6875
7645
|
const expression = attribute.initializer.expression;
|
|
6876
7646
|
if (!expression) return "";
|
|
6877
|
-
if (
|
|
7647
|
+
if (ts6.isStringLiteral(expression) || ts6.isNoSubstitutionTemplateLiteral(expression)) {
|
|
6878
7648
|
return expression.text;
|
|
6879
7649
|
}
|
|
6880
7650
|
}
|
|
6881
7651
|
return null;
|
|
6882
7652
|
}
|
|
6883
7653
|
function getJsxTextContent(node) {
|
|
6884
|
-
if (
|
|
7654
|
+
if (ts6.isJsxText(node)) {
|
|
6885
7655
|
return node.getText();
|
|
6886
7656
|
}
|
|
6887
|
-
if (
|
|
7657
|
+
if (ts6.isStringLiteral(node) || ts6.isNoSubstitutionTemplateLiteral(node)) {
|
|
6888
7658
|
return node.text;
|
|
6889
7659
|
}
|
|
6890
|
-
if (
|
|
7660
|
+
if (ts6.isJsxExpression(node)) {
|
|
6891
7661
|
return node.expression ? getJsxTextContent(node.expression) : "";
|
|
6892
7662
|
}
|
|
6893
|
-
if (
|
|
7663
|
+
if (ts6.isJsxSelfClosingElement(node) || ts6.isJsxOpeningElement(node)) {
|
|
6894
7664
|
return "";
|
|
6895
7665
|
}
|
|
6896
|
-
if (
|
|
7666
|
+
if (ts6.isJsxElement(node) || ts6.isJsxFragment(node)) {
|
|
6897
7667
|
return node.children.map((child) => getJsxTextContent(child)).join("");
|
|
6898
7668
|
}
|
|
6899
7669
|
let text = "";
|
|
@@ -6902,9 +7672,15 @@ function getJsxTextContent(node) {
|
|
|
6902
7672
|
});
|
|
6903
7673
|
return text;
|
|
6904
7674
|
}
|
|
7675
|
+
function hasNonEmptyJsxAttribute(attributes, ...names) {
|
|
7676
|
+
const attribute = getJsxAttribute(attributes, ...names);
|
|
7677
|
+
if (!attribute?.initializer) return false;
|
|
7678
|
+
const literalValue = getJsxAttributeLiteralValue(attribute);
|
|
7679
|
+
return literalValue === null || literalValue.trim().length > 0;
|
|
7680
|
+
}
|
|
6905
7681
|
function hasAccessibleLabel(attributes, textContent) {
|
|
6906
7682
|
return Boolean(
|
|
6907
|
-
|
|
7683
|
+
hasNonEmptyJsxAttribute(attributes, "aria-label", "aria-labelledby", "title") || textContent.trim().length > 0
|
|
6908
7684
|
);
|
|
6909
7685
|
}
|
|
6910
7686
|
function isNonSemanticInteractiveTag(tagName) {
|
|
@@ -6913,7 +7689,7 @@ function isNonSemanticInteractiveTag(tagName) {
|
|
|
6913
7689
|
function collectLabelForIds(root) {
|
|
6914
7690
|
const ids = /* @__PURE__ */ new Set();
|
|
6915
7691
|
const walk = (node) => {
|
|
6916
|
-
if (
|
|
7692
|
+
if (ts6.isJsxSelfClosingElement(node) || ts6.isJsxOpeningElement(node)) {
|
|
6917
7693
|
const tagName = getJsxTagName(node);
|
|
6918
7694
|
if (tagName === "label") {
|
|
6919
7695
|
const htmlForValue = getJsxAttributeLiteralValue(
|
|
@@ -6924,7 +7700,19 @@ function collectLabelForIds(root) {
|
|
|
6924
7700
|
}
|
|
6925
7701
|
}
|
|
6926
7702
|
}
|
|
6927
|
-
|
|
7703
|
+
ts6.forEachChild(node, walk);
|
|
7704
|
+
};
|
|
7705
|
+
walk(root);
|
|
7706
|
+
return ids;
|
|
7707
|
+
}
|
|
7708
|
+
function collectElementIds(root) {
|
|
7709
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7710
|
+
const walk = (node) => {
|
|
7711
|
+
if (ts6.isJsxSelfClosingElement(node) || ts6.isJsxOpeningElement(node)) {
|
|
7712
|
+
const idValue = getJsxAttributeLiteralValue(getJsxAttribute(node.attributes, "id"));
|
|
7713
|
+
if (idValue?.trim()) ids.add(idValue.trim());
|
|
7714
|
+
}
|
|
7715
|
+
ts6.forEachChild(node, walk);
|
|
6928
7716
|
};
|
|
6929
7717
|
walk(root);
|
|
6930
7718
|
return ids;
|
|
@@ -6932,7 +7720,7 @@ function collectLabelForIds(root) {
|
|
|
6932
7720
|
function isWrappedInJsxLabel(node) {
|
|
6933
7721
|
let current = node.parent;
|
|
6934
7722
|
while (current) {
|
|
6935
|
-
if (
|
|
7723
|
+
if (ts6.isJsxElement(current) && getJsxTagName(current.openingElement) === "label") {
|
|
6936
7724
|
return true;
|
|
6937
7725
|
}
|
|
6938
7726
|
current = current.parent;
|
|
@@ -6942,7 +7730,7 @@ function isWrappedInJsxLabel(node) {
|
|
|
6942
7730
|
function hasAncestorJsxTag(node, tagName) {
|
|
6943
7731
|
let current = node.parent;
|
|
6944
7732
|
while (current) {
|
|
6945
|
-
if (
|
|
7733
|
+
if (ts6.isJsxElement(current) && getJsxTagName(current.openingElement) === tagName) {
|
|
6946
7734
|
return true;
|
|
6947
7735
|
}
|
|
6948
7736
|
current = current.parent;
|
|
@@ -6951,21 +7739,37 @@ function hasAncestorJsxTag(node, tagName) {
|
|
|
6951
7739
|
}
|
|
6952
7740
|
function isLabelableFormControl(tagName, attributes) {
|
|
6953
7741
|
if (!tagName) return false;
|
|
6954
|
-
|
|
6955
|
-
if (
|
|
7742
|
+
const normalizedTagName = tagName.toLowerCase();
|
|
7743
|
+
if (normalizedTagName === "select" || normalizedTagName === "textarea") return true;
|
|
7744
|
+
if (normalizedTagName !== "input" && !isLikelyProjectFormControlTag(tagName)) return false;
|
|
6956
7745
|
const inputType = (getJsxAttributeLiteralValue(getJsxAttribute(attributes, "type")) ?? "text").toLowerCase();
|
|
6957
7746
|
return !["hidden", "submit", "reset", "button"].includes(inputType);
|
|
6958
7747
|
}
|
|
7748
|
+
function isLikelyProjectFormControlTag(tagName) {
|
|
7749
|
+
if (tagName === tagName.toLowerCase()) return false;
|
|
7750
|
+
const normalizedTagName = tagName.toLowerCase();
|
|
7751
|
+
return /(?:^|(?:text|email|password|search|number|tel|url|date))input$/.test(normalizedTagName) || /^(?:textarea|textArea|select|combobox|comboBox|checkbox|radio|switch)$/i.test(tagName);
|
|
7752
|
+
}
|
|
6959
7753
|
function getNormalizedInputType(attributes) {
|
|
6960
7754
|
return (getJsxAttributeLiteralValue(getJsxAttribute(attributes, "type")) ?? "text").trim().toLowerCase();
|
|
6961
7755
|
}
|
|
6962
|
-
function hasFormControlLabel(node, tagName, attributes, labelForIds, textContent) {
|
|
7756
|
+
function hasFormControlLabel(node, tagName, attributes, labelForIds, elementIds, textContent) {
|
|
6963
7757
|
if (!isLabelableFormControl(tagName, attributes)) return true;
|
|
6964
|
-
if (
|
|
7758
|
+
if (hasNonEmptyJsxAttribute(attributes, "aria-label", "title")) return true;
|
|
7759
|
+
if (hasAriaLabelledByReference(attributes, elementIds)) return true;
|
|
7760
|
+
if (textContent.trim().length > 0) return true;
|
|
6965
7761
|
if (isWrappedInJsxLabel(node)) return true;
|
|
6966
7762
|
const idValue = getJsxAttributeLiteralValue(getJsxAttribute(attributes, "id"));
|
|
6967
7763
|
return Boolean(idValue && labelForIds.has(idValue));
|
|
6968
7764
|
}
|
|
7765
|
+
function hasAriaLabelledByReference(attributes, elementIds) {
|
|
7766
|
+
const attribute = getJsxAttribute(attributes, "aria-labelledby");
|
|
7767
|
+
if (!attribute?.initializer) return false;
|
|
7768
|
+
const literalValue = getJsxAttributeLiteralValue(attribute);
|
|
7769
|
+
if (literalValue === null) return true;
|
|
7770
|
+
const references = literalValue.trim().split(/\s+/).filter(Boolean);
|
|
7771
|
+
return references.some((reference) => elementIds.has(reference));
|
|
7772
|
+
}
|
|
6969
7773
|
function isExternalLinkTargetBlankWithoutRel(attributes) {
|
|
6970
7774
|
const targetValue = getJsxAttributeLiteralValue(getJsxAttribute(attributes, "target"));
|
|
6971
7775
|
if (targetValue !== "_blank") return false;
|
|
@@ -7020,9 +7824,9 @@ function hasNavigationLabel(attributes) {
|
|
|
7020
7824
|
}
|
|
7021
7825
|
function getJsxAttributeOwner(attribute) {
|
|
7022
7826
|
const attributes = attribute.parent;
|
|
7023
|
-
if (!attributes || !
|
|
7827
|
+
if (!attributes || !ts6.isJsxAttributes(attributes)) return null;
|
|
7024
7828
|
const owner = attributes.parent;
|
|
7025
|
-
if (
|
|
7829
|
+
if (ts6.isJsxOpeningElement(owner) || ts6.isJsxSelfClosingElement(owner)) {
|
|
7026
7830
|
return owner;
|
|
7027
7831
|
}
|
|
7028
7832
|
return null;
|
|
@@ -7109,14 +7913,14 @@ function jsxTreeContainsAuthInput(node) {
|
|
|
7109
7913
|
let found = false;
|
|
7110
7914
|
const visit = (current) => {
|
|
7111
7915
|
if (found) return;
|
|
7112
|
-
if (
|
|
7916
|
+
if (ts6.isJsxSelfClosingElement(current)) {
|
|
7113
7917
|
const tagName = getJsxTagName(current);
|
|
7114
7918
|
if (tagName === "input" && isAuthLikeInputAttributes(current.attributes)) {
|
|
7115
7919
|
found = true;
|
|
7116
7920
|
}
|
|
7117
7921
|
return;
|
|
7118
7922
|
}
|
|
7119
|
-
if (
|
|
7923
|
+
if (ts6.isJsxElement(current)) {
|
|
7120
7924
|
const tagName = getJsxTagName(current.openingElement);
|
|
7121
7925
|
if (tagName === "input" && isAuthLikeInputAttributes(current.openingElement.attributes)) {
|
|
7122
7926
|
found = true;
|
|
@@ -7128,7 +7932,7 @@ function jsxTreeContainsAuthInput(node) {
|
|
|
7128
7932
|
}
|
|
7129
7933
|
return;
|
|
7130
7934
|
}
|
|
7131
|
-
if (
|
|
7935
|
+
if (ts6.isJsxFragment(current)) {
|
|
7132
7936
|
for (const child of current.children) {
|
|
7133
7937
|
visit(child);
|
|
7134
7938
|
if (found) return;
|
|
@@ -7152,7 +7956,7 @@ function jsxTreeHasSubmitControl(node) {
|
|
|
7152
7956
|
let found = false;
|
|
7153
7957
|
const visit = (current) => {
|
|
7154
7958
|
if (found) return;
|
|
7155
|
-
if (
|
|
7959
|
+
if (ts6.isJsxSelfClosingElement(current)) {
|
|
7156
7960
|
const tagName = getJsxTagName(current);
|
|
7157
7961
|
if (tagName === "button") {
|
|
7158
7962
|
const typeValue = getJsxAttributeLiteralValue(getJsxAttribute(current.attributes, "type"))?.trim().toLowerCase();
|
|
@@ -7168,7 +7972,7 @@ function jsxTreeHasSubmitControl(node) {
|
|
|
7168
7972
|
}
|
|
7169
7973
|
return;
|
|
7170
7974
|
}
|
|
7171
|
-
if (
|
|
7975
|
+
if (ts6.isJsxElement(current)) {
|
|
7172
7976
|
const tagName = getJsxTagName(current.openingElement);
|
|
7173
7977
|
if (tagName === "button") {
|
|
7174
7978
|
const typeValue = getJsxAttributeLiteralValue(
|
|
@@ -7192,7 +7996,7 @@ function jsxTreeHasSubmitControl(node) {
|
|
|
7192
7996
|
}
|
|
7193
7997
|
return;
|
|
7194
7998
|
}
|
|
7195
|
-
if (
|
|
7999
|
+
if (ts6.isJsxFragment(current)) {
|
|
7196
8000
|
for (const child of current.children) {
|
|
7197
8001
|
visit(child);
|
|
7198
8002
|
if (found) return;
|
|
@@ -7209,14 +8013,14 @@ function jsxTreeHasTag(node, tagNames) {
|
|
|
7209
8013
|
const wanted = new Set(tagNames);
|
|
7210
8014
|
const visit = (current) => {
|
|
7211
8015
|
if (found) return;
|
|
7212
|
-
if (
|
|
8016
|
+
if (ts6.isJsxSelfClosingElement(current)) {
|
|
7213
8017
|
const tagName = getJsxTagName(current);
|
|
7214
8018
|
if (tagName && wanted.has(tagName)) {
|
|
7215
8019
|
found = true;
|
|
7216
8020
|
}
|
|
7217
8021
|
return;
|
|
7218
8022
|
}
|
|
7219
|
-
if (
|
|
8023
|
+
if (ts6.isJsxElement(current)) {
|
|
7220
8024
|
const tagName = getJsxTagName(current.openingElement);
|
|
7221
8025
|
if (tagName && wanted.has(tagName)) {
|
|
7222
8026
|
found = true;
|
|
@@ -7228,7 +8032,7 @@ function jsxTreeHasTag(node, tagNames) {
|
|
|
7228
8032
|
}
|
|
7229
8033
|
return;
|
|
7230
8034
|
}
|
|
7231
|
-
if (
|
|
8035
|
+
if (ts6.isJsxFragment(current)) {
|
|
7232
8036
|
for (const child of current.children) {
|
|
7233
8037
|
visit(child);
|
|
7234
8038
|
if (found) return;
|
|
@@ -7245,22 +8049,22 @@ function hasAuthFormWithoutSubmitControl(node) {
|
|
|
7245
8049
|
}
|
|
7246
8050
|
function getExpressionLiteralValue(expression) {
|
|
7247
8051
|
if (!expression) return null;
|
|
7248
|
-
if (
|
|
8052
|
+
if (ts6.isStringLiteral(expression) || ts6.isNoSubstitutionTemplateLiteral(expression)) {
|
|
7249
8053
|
return expression.text;
|
|
7250
8054
|
}
|
|
7251
|
-
if (
|
|
8055
|
+
if (ts6.isParenthesizedExpression(expression)) {
|
|
7252
8056
|
return getExpressionLiteralValue(expression.expression);
|
|
7253
8057
|
}
|
|
7254
|
-
if (
|
|
8058
|
+
if (ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression)) {
|
|
7255
8059
|
return getExpressionLiteralValue(expression.expression);
|
|
7256
8060
|
}
|
|
7257
8061
|
return null;
|
|
7258
8062
|
}
|
|
7259
8063
|
function getObjectLiteralStringPropertyValue(expression, ...propertyNames) {
|
|
7260
|
-
if (!expression || !
|
|
8064
|
+
if (!expression || !ts6.isObjectLiteralExpression(expression)) return null;
|
|
7261
8065
|
for (const property of expression.properties) {
|
|
7262
|
-
if (!
|
|
7263
|
-
const propertyName2 =
|
|
8066
|
+
if (!ts6.isPropertyAssignment(property)) continue;
|
|
8067
|
+
const propertyName2 = ts6.isIdentifier(property.name) ? property.name.text : ts6.isStringLiteral(property.name) ? property.name.text : null;
|
|
7264
8068
|
if (!propertyName2 || !propertyNames.includes(propertyName2)) continue;
|
|
7265
8069
|
const value = getExpressionLiteralValue(property.initializer);
|
|
7266
8070
|
if (value) return value;
|
|
@@ -7268,24 +8072,24 @@ function getObjectLiteralStringPropertyValue(expression, ...propertyNames) {
|
|
|
7268
8072
|
return null;
|
|
7269
8073
|
}
|
|
7270
8074
|
function getObjectLiteralBooleanPropertyValue(expression, ...propertyNames) {
|
|
7271
|
-
if (!expression || !
|
|
8075
|
+
if (!expression || !ts6.isObjectLiteralExpression(expression)) return null;
|
|
7272
8076
|
for (const property of expression.properties) {
|
|
7273
|
-
if (!
|
|
7274
|
-
const propertyName2 =
|
|
8077
|
+
if (!ts6.isPropertyAssignment(property)) continue;
|
|
8078
|
+
const propertyName2 = ts6.isIdentifier(property.name) ? property.name.text : ts6.isStringLiteral(property.name) ? property.name.text : null;
|
|
7275
8079
|
if (!propertyName2 || !propertyNames.includes(propertyName2)) continue;
|
|
7276
|
-
if (property.initializer.kind ===
|
|
7277
|
-
if (property.initializer.kind ===
|
|
8080
|
+
if (property.initializer.kind === ts6.SyntaxKind.TrueKeyword) return true;
|
|
8081
|
+
if (property.initializer.kind === ts6.SyntaxKind.FalseKeyword) return false;
|
|
7278
8082
|
}
|
|
7279
8083
|
return null;
|
|
7280
8084
|
}
|
|
7281
8085
|
function collectNamedFunctionLikeDeclarations(root) {
|
|
7282
8086
|
const declarations = /* @__PURE__ */ new Map();
|
|
7283
8087
|
const visit = (node) => {
|
|
7284
|
-
if (
|
|
8088
|
+
if (ts6.isFunctionDeclaration(node) && node.name && ts6.isIdentifier(node.name)) {
|
|
7285
8089
|
declarations.set(node.name.text, node);
|
|
7286
8090
|
}
|
|
7287
|
-
if (
|
|
7288
|
-
if (
|
|
8091
|
+
if (ts6.isVariableDeclaration(node) && ts6.isIdentifier(node.name) && node.initializer) {
|
|
8092
|
+
if (ts6.isArrowFunction(node.initializer) || ts6.isFunctionExpression(node.initializer)) {
|
|
7289
8093
|
declarations.set(node.name.text, node.initializer);
|
|
7290
8094
|
}
|
|
7291
8095
|
}
|
|
@@ -7305,12 +8109,12 @@ function getCachedNamedFunctionLikeDeclarations(sourceFile) {
|
|
|
7305
8109
|
function collectNamedExpressionInitializers(root) {
|
|
7306
8110
|
const initializers = /* @__PURE__ */ new Map();
|
|
7307
8111
|
const visit = (node) => {
|
|
7308
|
-
if (
|
|
8112
|
+
if (ts6.isVariableDeclaration(node) && ts6.isIdentifier(node.name) && node.initializer) {
|
|
7309
8113
|
initializers.set(node.name.text, node.initializer);
|
|
7310
8114
|
}
|
|
7311
|
-
if (
|
|
8115
|
+
if (ts6.isVariableDeclaration(node) && ts6.isArrayBindingPattern(node.name) && node.initializer) {
|
|
7312
8116
|
const firstElement = node.name.elements[0];
|
|
7313
|
-
if (firstElement && !
|
|
8117
|
+
if (firstElement && !ts6.isOmittedExpression(firstElement) && ts6.isBindingElement(firstElement) && ts6.isIdentifier(firstElement.name)) {
|
|
7314
8118
|
initializers.set(firstElement.name.text, node.initializer);
|
|
7315
8119
|
}
|
|
7316
8120
|
}
|
|
@@ -7321,7 +8125,7 @@ function collectNamedExpressionInitializers(root) {
|
|
|
7321
8125
|
}
|
|
7322
8126
|
function getPropertyNameText(name) {
|
|
7323
8127
|
if (!name) return null;
|
|
7324
|
-
if (
|
|
8128
|
+
if (ts6.isIdentifier(name) || ts6.isStringLiteral(name) || ts6.isNumericLiteral(name)) {
|
|
7325
8129
|
return name.text;
|
|
7326
8130
|
}
|
|
7327
8131
|
return null;
|
|
@@ -7334,20 +8138,20 @@ function collectNamedPropertyAliases(root) {
|
|
|
7334
8138
|
const propertyName2 = getPropertyNameText(element.propertyName) ?? getPropertyNameText(element.name);
|
|
7335
8139
|
if (!propertyName2) continue;
|
|
7336
8140
|
const nextPath = [...propertyPath, propertyName2];
|
|
7337
|
-
if (
|
|
8141
|
+
if (ts6.isIdentifier(element.name)) {
|
|
7338
8142
|
aliases.set(element.name.text, { initializer, propertyName: propertyName2, propertyPath: nextPath });
|
|
7339
8143
|
continue;
|
|
7340
8144
|
}
|
|
7341
|
-
if (
|
|
8145
|
+
if (ts6.isObjectBindingPattern(element.name)) {
|
|
7342
8146
|
collectFromBindingPattern(element.name, initializer, nextPath);
|
|
7343
8147
|
}
|
|
7344
8148
|
}
|
|
7345
8149
|
};
|
|
7346
8150
|
const visit = (node) => {
|
|
7347
|
-
if (
|
|
8151
|
+
if (ts6.isVariableDeclaration(node) && ts6.isObjectBindingPattern(node.name) && node.initializer) {
|
|
7348
8152
|
collectFromBindingPattern(node.name, node.initializer, []);
|
|
7349
8153
|
}
|
|
7350
|
-
if (
|
|
8154
|
+
if (ts6.isParameter(node) && ts6.isObjectBindingPattern(node.name)) {
|
|
7351
8155
|
collectFromBindingPattern(node.name, void 0, []);
|
|
7352
8156
|
}
|
|
7353
8157
|
node.forEachChild(visit);
|
|
@@ -7357,28 +8161,28 @@ function collectNamedPropertyAliases(root) {
|
|
|
7357
8161
|
}
|
|
7358
8162
|
function resolveFunctionLikeHandler(expression, namedFunctions) {
|
|
7359
8163
|
if (!expression) return null;
|
|
7360
|
-
if (
|
|
8164
|
+
if (ts6.isArrowFunction(expression) || ts6.isFunctionExpression(expression)) {
|
|
7361
8165
|
return expression;
|
|
7362
8166
|
}
|
|
7363
|
-
if (
|
|
8167
|
+
if (ts6.isIdentifier(expression)) {
|
|
7364
8168
|
return namedFunctions.get(expression.text) ?? null;
|
|
7365
8169
|
}
|
|
7366
8170
|
return null;
|
|
7367
8171
|
}
|
|
7368
8172
|
function getFunctionLikeReturnExpressions(node) {
|
|
7369
|
-
if (
|
|
8173
|
+
if (ts6.isArrowFunction(node) && !ts6.isBlock(node.body)) {
|
|
7370
8174
|
return [node.body];
|
|
7371
8175
|
}
|
|
7372
8176
|
const body = node.body;
|
|
7373
|
-
if (!body || !
|
|
8177
|
+
if (!body || !ts6.isBlock(body)) {
|
|
7374
8178
|
return [];
|
|
7375
8179
|
}
|
|
7376
8180
|
const expressions = [];
|
|
7377
8181
|
const visit = (current) => {
|
|
7378
|
-
if (current !== body && (
|
|
8182
|
+
if (current !== body && (ts6.isFunctionDeclaration(current) || ts6.isFunctionExpression(current) || ts6.isArrowFunction(current) || ts6.isMethodDeclaration(current) || ts6.isGetAccessorDeclaration(current) || ts6.isSetAccessorDeclaration(current) || ts6.isConstructorDeclaration(current))) {
|
|
7379
8183
|
return;
|
|
7380
8184
|
}
|
|
7381
|
-
if (
|
|
8185
|
+
if (ts6.isReturnStatement(current) && current.expression) {
|
|
7382
8186
|
expressions.push(current.expression);
|
|
7383
8187
|
return;
|
|
7384
8188
|
}
|
|
@@ -7394,7 +8198,7 @@ function bindFunctionLikeArguments(functionLike, args, namedExpressions) {
|
|
|
7394
8198
|
const boundExpressions = new Map(namedExpressions);
|
|
7395
8199
|
functionLike.parameters.forEach((parameter, index) => {
|
|
7396
8200
|
const argument = args[index];
|
|
7397
|
-
if (!argument || !
|
|
8201
|
+
if (!argument || !ts6.isIdentifier(parameter.name)) return;
|
|
7398
8202
|
boundExpressions.set(parameter.name.text, argument);
|
|
7399
8203
|
});
|
|
7400
8204
|
return boundExpressions;
|
|
@@ -7408,10 +8212,10 @@ function getMemberAccessPropertyName(expression) {
|
|
|
7408
8212
|
}
|
|
7409
8213
|
function getObjectLiteralPropertyExpression(objectLiteral, propertyName2, namedExpressions) {
|
|
7410
8214
|
for (const property of objectLiteral.properties) {
|
|
7411
|
-
if (
|
|
8215
|
+
if (ts6.isPropertyAssignment(property) && getPropertyNameText(property.name) === propertyName2) {
|
|
7412
8216
|
return property.initializer;
|
|
7413
8217
|
}
|
|
7414
|
-
if (
|
|
8218
|
+
if (ts6.isShorthandPropertyAssignment(property) && property.name.text === propertyName2) {
|
|
7415
8219
|
return namedExpressions.get(property.name.text) ?? null;
|
|
7416
8220
|
}
|
|
7417
8221
|
}
|
|
@@ -7477,7 +8281,7 @@ function resolveReturnedObjectLiteralExpression(functionLike, args, sourceFile,
|
|
|
7477
8281
|
function resolveObjectLiteralExpression(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers, seenFunctions = /* @__PURE__ */ new Set(), depth = 0) {
|
|
7478
8282
|
if (!expression) return null;
|
|
7479
8283
|
if (depth > MAX_OPEN_REDIRECT_RESOLUTION_DEPTH) return null;
|
|
7480
|
-
if (
|
|
8284
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
7481
8285
|
return resolveObjectLiteralExpression(
|
|
7482
8286
|
expression.expression,
|
|
7483
8287
|
sourceFile,
|
|
@@ -7488,10 +8292,10 @@ function resolveObjectLiteralExpression(expression, sourceFile, namedExpressions
|
|
|
7488
8292
|
depth + 1
|
|
7489
8293
|
);
|
|
7490
8294
|
}
|
|
7491
|
-
if (
|
|
8295
|
+
if (ts6.isObjectLiteralExpression(expression)) {
|
|
7492
8296
|
return { objectLiteral: expression, namedExpressions };
|
|
7493
8297
|
}
|
|
7494
|
-
if (
|
|
8298
|
+
if (ts6.isIdentifier(expression)) {
|
|
7495
8299
|
if (seenIdentifiers.has(expression.text)) return null;
|
|
7496
8300
|
const initializer = namedExpressions.get(expression.text);
|
|
7497
8301
|
if (initializer) {
|
|
@@ -7564,13 +8368,13 @@ function resolveObjectLiteralExpression(expression, sourceFile, namedExpressions
|
|
|
7564
8368
|
}
|
|
7565
8369
|
function findFunctionLikeOnObjectLiteral(objectLiteral, propertyName2, namedFunctions) {
|
|
7566
8370
|
for (const property of objectLiteral.properties) {
|
|
7567
|
-
if (
|
|
8371
|
+
if (ts6.isMethodDeclaration(property) && getPropertyNameText(property.name) === propertyName2) {
|
|
7568
8372
|
return property;
|
|
7569
8373
|
}
|
|
7570
|
-
if (
|
|
8374
|
+
if (ts6.isPropertyAssignment(property) && getPropertyNameText(property.name) === propertyName2) {
|
|
7571
8375
|
return resolveFunctionLikeHandler(property.initializer, namedFunctions);
|
|
7572
8376
|
}
|
|
7573
|
-
if (
|
|
8377
|
+
if (ts6.isShorthandPropertyAssignment(property) && property.name.text === propertyName2) {
|
|
7574
8378
|
return namedFunctions.get(property.name.text) ?? null;
|
|
7575
8379
|
}
|
|
7576
8380
|
}
|
|
@@ -7605,7 +8409,7 @@ function resolveTrackedOpenRedirectFunctionLike(expression, sourceFile, namedExp
|
|
|
7605
8409
|
if (directFunctionLike) {
|
|
7606
8410
|
return { functionLike: directFunctionLike, namedExpressions };
|
|
7607
8411
|
}
|
|
7608
|
-
if (
|
|
8412
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
7609
8413
|
return resolveTrackedOpenRedirectFunctionLike(
|
|
7610
8414
|
expression.expression,
|
|
7611
8415
|
sourceFile,
|
|
@@ -7638,7 +8442,7 @@ function resolveTrackedOpenRedirectFunctionLike(expression, sourceFile, namedExp
|
|
|
7638
8442
|
depth + 1
|
|
7639
8443
|
);
|
|
7640
8444
|
}
|
|
7641
|
-
if (
|
|
8445
|
+
if (ts6.isIdentifier(expression)) {
|
|
7642
8446
|
if (seenIdentifiers.has(expression.text)) return null;
|
|
7643
8447
|
const initializer = namedExpressions.get(expression.text);
|
|
7644
8448
|
if (initializer) {
|
|
@@ -7701,16 +8505,16 @@ function functionLikeReferencesOrigin(node) {
|
|
|
7701
8505
|
let found = false;
|
|
7702
8506
|
const visit = (current) => {
|
|
7703
8507
|
if (found) return;
|
|
7704
|
-
if (
|
|
8508
|
+
if (ts6.isPropertyAccessExpression(current) && isPropertyNamed(current.name, "origin")) {
|
|
7705
8509
|
found = true;
|
|
7706
8510
|
return;
|
|
7707
8511
|
}
|
|
7708
|
-
if (
|
|
8512
|
+
if (ts6.isIdentifier(current) && current.text === "origin") {
|
|
7709
8513
|
found = true;
|
|
7710
8514
|
return;
|
|
7711
8515
|
}
|
|
7712
|
-
if (
|
|
7713
|
-
if (
|
|
8516
|
+
if (ts6.isBindingElement(current)) {
|
|
8517
|
+
if (ts6.isIdentifier(current.name) && current.name.text === "origin") {
|
|
7714
8518
|
found = true;
|
|
7715
8519
|
return;
|
|
7716
8520
|
}
|
|
@@ -7725,13 +8529,13 @@ function functionLikeReferencesOrigin(node) {
|
|
|
7725
8529
|
return found;
|
|
7726
8530
|
}
|
|
7727
8531
|
function isAddEventListenerCall(node) {
|
|
7728
|
-
return
|
|
8532
|
+
return ts6.isIdentifier(node.expression) && node.expression.text === "addEventListener" || ts6.isPropertyAccessExpression(node.expression) && isPropertyNamed(node.expression.name, "addEventListener");
|
|
7729
8533
|
}
|
|
7730
8534
|
function isCookieMutationSetCall(node) {
|
|
7731
|
-
if (!
|
|
8535
|
+
if (!ts6.isPropertyAccessExpression(node.expression) || !isPropertyNamed(node.expression.name, "set")) {
|
|
7732
8536
|
return false;
|
|
7733
8537
|
}
|
|
7734
|
-
return
|
|
8538
|
+
return ts6.isIdentifier(node.expression.expression) && ["Cookies", "cookieStore", "cookies"].includes(node.expression.expression.text) || ts6.isPropertyAccessExpression(node.expression.expression) && isPropertyNamed(node.expression.expression.name, "cookies", "cookieStore");
|
|
7735
8539
|
}
|
|
7736
8540
|
function expressionLooksLikeAuthCookieName(node, sourceFile) {
|
|
7737
8541
|
if (!node) return false;
|
|
@@ -7739,17 +8543,17 @@ function expressionLooksLikeAuthCookieName(node, sourceFile) {
|
|
|
7739
8543
|
return hasAuthCredentialText(node, sourceFile);
|
|
7740
8544
|
}
|
|
7741
8545
|
function objectLiteralLooksLikeAuthCookieConfig(expression, sourceFile) {
|
|
7742
|
-
if (!expression || !
|
|
8546
|
+
if (!expression || !ts6.isObjectLiteralExpression(expression)) return false;
|
|
7743
8547
|
for (const property of expression.properties) {
|
|
7744
|
-
if (!
|
|
7745
|
-
const propertyName2 =
|
|
8548
|
+
if (!ts6.isPropertyAssignment(property)) continue;
|
|
8549
|
+
const propertyName2 = ts6.isIdentifier(property.name) ? property.name.text : ts6.isStringLiteral(property.name) ? property.name.text : null;
|
|
7746
8550
|
if (!propertyName2 || !["name", "key", "cookie"].includes(propertyName2)) continue;
|
|
7747
8551
|
return expressionLooksLikeAuthCookieName(property.initializer, sourceFile);
|
|
7748
8552
|
}
|
|
7749
8553
|
return false;
|
|
7750
8554
|
}
|
|
7751
8555
|
function hasExplicitAuthCookieHardening(expression) {
|
|
7752
|
-
if (!expression || !
|
|
8556
|
+
if (!expression || !ts6.isObjectLiteralExpression(expression)) return false;
|
|
7753
8557
|
const httpOnly = getObjectLiteralBooleanPropertyValue(expression, "httpOnly", "http_only");
|
|
7754
8558
|
const secure = getObjectLiteralBooleanPropertyValue(expression, "secure");
|
|
7755
8559
|
const sameSite = getObjectLiteralStringPropertyValue(expression, "sameSite", "same_site");
|
|
@@ -7769,8 +8573,8 @@ function collectCookieHeaderStrings(expression) {
|
|
|
7769
8573
|
if (!expression) return [];
|
|
7770
8574
|
const literal = getExpressionLiteralValue(expression);
|
|
7771
8575
|
if (literal !== null) return [literal];
|
|
7772
|
-
if (
|
|
7773
|
-
return expression.elements.map((element) =>
|
|
8576
|
+
if (ts6.isArrayLiteralExpression(expression)) {
|
|
8577
|
+
return expression.elements.map((element) => ts6.isExpression(element) ? getExpressionLiteralValue(element) : null).filter((value) => value !== null);
|
|
7774
8578
|
}
|
|
7775
8579
|
return [];
|
|
7776
8580
|
}
|
|
@@ -7778,16 +8582,16 @@ function isInsecureTransportUrl(value) {
|
|
|
7778
8582
|
return typeof value === "string" && /^(?:http|ws):\/\//i.test(value.trim());
|
|
7779
8583
|
}
|
|
7780
8584
|
function isPropertyLikeAccessExpression(node) {
|
|
7781
|
-
return Boolean(node && (
|
|
8585
|
+
return Boolean(node && (ts6.isPropertyAccessExpression(node) || ts6.isPropertyAccessChain(node)));
|
|
7782
8586
|
}
|
|
7783
8587
|
function isElementLikeAccessExpression(node) {
|
|
7784
|
-
return Boolean(node && (
|
|
8588
|
+
return Boolean(node && (ts6.isElementAccessExpression(node) || ts6.isElementAccessChain(node)));
|
|
7785
8589
|
}
|
|
7786
8590
|
function isMemberAccessExpression(node) {
|
|
7787
8591
|
return isPropertyLikeAccessExpression(node) || isElementLikeAccessExpression(node);
|
|
7788
8592
|
}
|
|
7789
8593
|
function isCallLikeExpression(node) {
|
|
7790
|
-
return Boolean(node && (
|
|
8594
|
+
return Boolean(node && (ts6.isCallExpression(node) || ts6.isCallChain(node)));
|
|
7791
8595
|
}
|
|
7792
8596
|
function isMemberAccessNamed(node, ...names) {
|
|
7793
8597
|
if (!node) return false;
|
|
@@ -7800,19 +8604,19 @@ function isMemberAccessNamed(node, ...names) {
|
|
|
7800
8604
|
return false;
|
|
7801
8605
|
}
|
|
7802
8606
|
function isLocationObjectExpression(expression) {
|
|
7803
|
-
return
|
|
8607
|
+
return ts6.isIdentifier(expression) && expression.text === "location" || (ts6.isPropertyAccessExpression(expression) || ts6.isElementAccessExpression(expression)) && ts6.isIdentifier(expression.expression) && ["window", "globalThis", "document", "self", "parent", "top"].includes(
|
|
7804
8608
|
expression.expression.text
|
|
7805
8609
|
) && isMemberAccessNamed(expression, "location");
|
|
7806
8610
|
}
|
|
7807
8611
|
function isLocationAssignmentTarget(expression) {
|
|
7808
|
-
return isLocationObjectExpression(expression) || (
|
|
8612
|
+
return isLocationObjectExpression(expression) || (ts6.isPropertyAccessExpression(expression) || ts6.isElementAccessExpression(expression)) && isLocationObjectExpression(expression.expression) && isMemberAccessNamed(expression, "href");
|
|
7809
8613
|
}
|
|
7810
8614
|
function isFetchLikeCall(node) {
|
|
7811
|
-
return
|
|
8615
|
+
return ts6.isIdentifier(node.expression) && node.expression.text === "fetch" || ts6.isPropertyAccessExpression(node.expression) && isPropertyNamed(node.expression.name, "fetch");
|
|
7812
8616
|
}
|
|
7813
8617
|
function isAxiosLikeCall(node) {
|
|
7814
|
-
if (!
|
|
7815
|
-
return
|
|
8618
|
+
if (!ts6.isPropertyAccessExpression(node.expression)) return false;
|
|
8619
|
+
return ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "axios" && isPropertyNamed(
|
|
7816
8620
|
node.expression.name,
|
|
7817
8621
|
"get",
|
|
7818
8622
|
"post",
|
|
@@ -7825,10 +8629,10 @@ function isAxiosLikeCall(node) {
|
|
|
7825
8629
|
);
|
|
7826
8630
|
}
|
|
7827
8631
|
function isAxiosConfigCall(node) {
|
|
7828
|
-
return
|
|
8632
|
+
return ts6.isIdentifier(node.expression) && node.expression.text === "axios";
|
|
7829
8633
|
}
|
|
7830
8634
|
function isRealtimeTransportConstructor(node) {
|
|
7831
|
-
return
|
|
8635
|
+
return ts6.isIdentifier(node.expression) && (node.expression.text === "WebSocket" || node.expression.text === "EventSource");
|
|
7832
8636
|
}
|
|
7833
8637
|
function hasPlaceholderNavigationTarget(attributes) {
|
|
7834
8638
|
const targetValue = getJsxAttributeLiteralValue(getJsxAttribute(attributes, "href", "to"));
|
|
@@ -7895,40 +8699,40 @@ function getSkipNavTargetId(attributes, tagName) {
|
|
|
7895
8699
|
}
|
|
7896
8700
|
function isAuthStorageKeyLiteral(node) {
|
|
7897
8701
|
if (!node) return false;
|
|
7898
|
-
if (
|
|
8702
|
+
if (ts6.isStringLiteral(node) || ts6.isNoSubstitutionTemplateLiteral(node)) {
|
|
7899
8703
|
if (node.text === "decantr_authenticated") return false;
|
|
7900
8704
|
return /(?:token|auth|jwt|session|access_token|refresh_token)/i.test(node.text);
|
|
7901
8705
|
}
|
|
7902
8706
|
return false;
|
|
7903
8707
|
}
|
|
7904
8708
|
function isBrowserStorageObject(node) {
|
|
7905
|
-
return
|
|
8709
|
+
return ts6.isIdentifier(node) && (node.text === "localStorage" || node.text === "sessionStorage");
|
|
7906
8710
|
}
|
|
7907
8711
|
function isDocumentObject(node) {
|
|
7908
|
-
return
|
|
8712
|
+
return ts6.isIdentifier(node) && node.text === "document";
|
|
7909
8713
|
}
|
|
7910
8714
|
function isCookiePropertyAccess(node) {
|
|
7911
|
-
return
|
|
8715
|
+
return ts6.isPropertyAccessExpression(node) && isDocumentObject(node.expression) && isPropertyNamed(node.name, "cookie");
|
|
7912
8716
|
}
|
|
7913
8717
|
function hasAuthCredentialText(node, sourceFile) {
|
|
7914
8718
|
return /(?:token|auth|jwt|session|access_token|refresh_token)/i.test(node.getText(sourceFile));
|
|
7915
8719
|
}
|
|
7916
8720
|
function isAuthorizationHeaderName(node) {
|
|
7917
8721
|
if (!node) return false;
|
|
7918
|
-
if (
|
|
8722
|
+
if (ts6.isIdentifier(node)) {
|
|
7919
8723
|
return /^authorization$/i.test(node.text);
|
|
7920
8724
|
}
|
|
7921
|
-
if (
|
|
8725
|
+
if (ts6.isStringLiteral(node) || ts6.isNoSubstitutionTemplateLiteral(node)) {
|
|
7922
8726
|
return /^authorization$/i.test(node.text);
|
|
7923
8727
|
}
|
|
7924
|
-
if (
|
|
8728
|
+
if (ts6.isComputedPropertyName(node)) {
|
|
7925
8729
|
return isAuthorizationHeaderName(node.expression);
|
|
7926
8730
|
}
|
|
7927
8731
|
return false;
|
|
7928
8732
|
}
|
|
7929
8733
|
function isAuthorizationHeaderAccess(node) {
|
|
7930
8734
|
if (!node) return false;
|
|
7931
|
-
return
|
|
8735
|
+
return ts6.isPropertyAccessExpression(node) && isAuthorizationHeaderName(node.name) || ts6.isElementAccessExpression(node) && isAuthorizationHeaderName(node.argumentExpression);
|
|
7932
8736
|
}
|
|
7933
8737
|
function isHeaderClearValue(node) {
|
|
7934
8738
|
if (!node) return false;
|
|
@@ -7936,7 +8740,7 @@ function isHeaderClearValue(node) {
|
|
|
7936
8740
|
if (literal !== null) {
|
|
7937
8741
|
return literal.trim().length === 0;
|
|
7938
8742
|
}
|
|
7939
|
-
return node.kind ===
|
|
8743
|
+
return node.kind === ts6.SyntaxKind.NullKeyword || node.kind === ts6.SyntaxKind.UndefinedKeyword || ts6.isIdentifier(node) && node.text === "undefined";
|
|
7940
8744
|
}
|
|
7941
8745
|
function countAuthGuardSignals(code) {
|
|
7942
8746
|
const patterns = [
|
|
@@ -8650,7 +9454,7 @@ function countAuthAnonymousRedirectSignals(code) {
|
|
|
8650
9454
|
];
|
|
8651
9455
|
return patterns.reduce((count, pattern) => count + (pattern.test(code) ? 1 : 0), 0);
|
|
8652
9456
|
}
|
|
8653
|
-
var OPEN_REDIRECT_QUERY_KEY_PATTERN =
|
|
9457
|
+
var OPEN_REDIRECT_QUERY_KEY_PATTERN = "next|redirect(?:To|[_-]to)?|return(?:To|[_-]to)?|callback(?:Url|[_-]url)?|continue(?:Url|[_-]url)?|from";
|
|
8654
9458
|
var OPEN_REDIRECT_SOURCE_PATTERN = String.raw`\b(?:searchParams|(?:request|req)\.nextUrl\.searchParams|url\.searchParams)\.get\s*\(\s*['"\`](?:${OPEN_REDIRECT_QUERY_KEY_PATTERN})['"\`]\s*\)|\b(?:router\.query|route\.query|query)\.(?:${OPEN_REDIRECT_QUERY_KEY_PATTERN})\b|\b(?:new\s+)?URLSearchParams\s*\(\s*(?:(?:window|globalThis|document|self|parent|top)\.)?location\.(?:search|hash)(?:\.slice\(\s*1\s*\)|\.replace\([^)]*\))?\s*\)\.get\s*\(\s*['"\`](?:${OPEN_REDIRECT_QUERY_KEY_PATTERN})['"\`]\s*\)|\bnew\s+URL\(\s*(?:request|req)\.url\s*\)\.searchParams\.get\s*\(\s*['"\`](?:${OPEN_REDIRECT_QUERY_KEY_PATTERN})['"\`]\s*\)`;
|
|
8655
9459
|
var OPEN_REDIRECT_SOURCE_REGEX = new RegExp(OPEN_REDIRECT_SOURCE_PATTERN, "i");
|
|
8656
9460
|
var OPEN_REDIRECT_QUERY_KEY_REGEX = new RegExp(`^(?:${OPEN_REDIRECT_QUERY_KEY_PATTERN})$`, "i");
|
|
@@ -8685,7 +9489,7 @@ function propertyPathLooksLikeOpenRedirectQueryContainerBase(propertyPath) {
|
|
|
8685
9489
|
}
|
|
8686
9490
|
function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFile, namedExpressions = /* @__PURE__ */ new Map(), namedPropertyAliases = /* @__PURE__ */ new Map(), seenIdentifiers = /* @__PURE__ */ new Set(), seenFunctions = /* @__PURE__ */ new Set()) {
|
|
8687
9491
|
if (!expression) return false;
|
|
8688
|
-
if (
|
|
9492
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
8689
9493
|
return expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
8690
9494
|
expression.expression,
|
|
8691
9495
|
sourceFile,
|
|
@@ -8712,7 +9516,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8712
9516
|
)
|
|
8713
9517
|
);
|
|
8714
9518
|
}
|
|
8715
|
-
if (
|
|
9519
|
+
if (ts6.isBinaryExpression(expression) && (expression.operatorToken.kind === ts6.SyntaxKind.QuestionQuestionToken || expression.operatorToken.kind === ts6.SyntaxKind.BarBarToken)) {
|
|
8716
9520
|
return expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
8717
9521
|
expression.left,
|
|
8718
9522
|
sourceFile,
|
|
@@ -8729,7 +9533,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8729
9533
|
seenFunctions
|
|
8730
9534
|
);
|
|
8731
9535
|
}
|
|
8732
|
-
if (
|
|
9536
|
+
if (ts6.isConditionalExpression(expression)) {
|
|
8733
9537
|
return expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
8734
9538
|
expression.whenTrue,
|
|
8735
9539
|
sourceFile,
|
|
@@ -8746,7 +9550,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8746
9550
|
seenFunctions
|
|
8747
9551
|
);
|
|
8748
9552
|
}
|
|
8749
|
-
if (
|
|
9553
|
+
if (ts6.isTemplateExpression(expression)) {
|
|
8750
9554
|
return expression.templateSpans.some(
|
|
8751
9555
|
(span) => expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
8752
9556
|
span.expression,
|
|
@@ -8758,7 +9562,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8758
9562
|
)
|
|
8759
9563
|
);
|
|
8760
9564
|
}
|
|
8761
|
-
if (
|
|
9565
|
+
if (ts6.isTaggedTemplateExpression(expression)) {
|
|
8762
9566
|
return expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
8763
9567
|
expression.template,
|
|
8764
9568
|
sourceFile,
|
|
@@ -8768,7 +9572,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8768
9572
|
seenFunctions
|
|
8769
9573
|
);
|
|
8770
9574
|
}
|
|
8771
|
-
if (
|
|
9575
|
+
if (ts6.isNewExpression(expression) && expression.arguments && expression.arguments.length > 0 && expressionLooksLikeBrowserGlobalBooleanHelper(
|
|
8772
9576
|
expression.expression,
|
|
8773
9577
|
sourceFile,
|
|
8774
9578
|
namedExpressions,
|
|
@@ -8784,7 +9588,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8784
9588
|
)) {
|
|
8785
9589
|
return true;
|
|
8786
9590
|
}
|
|
8787
|
-
if (
|
|
9591
|
+
if (ts6.isNewExpression(expression) && expression.arguments && expression.arguments.length > 0 && expressionLooksLikeBrowserGlobalNumberHelper(
|
|
8788
9592
|
expression.expression,
|
|
8789
9593
|
sourceFile,
|
|
8790
9594
|
namedExpressions,
|
|
@@ -8800,7 +9604,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8800
9604
|
)) {
|
|
8801
9605
|
return true;
|
|
8802
9606
|
}
|
|
8803
|
-
if (
|
|
9607
|
+
if (ts6.isNewExpression(expression) && expression.arguments && expression.arguments.length > 0 && expressionLooksLikeBrowserGlobalObjectHelper(
|
|
8804
9608
|
expression.expression,
|
|
8805
9609
|
sourceFile,
|
|
8806
9610
|
namedExpressions,
|
|
@@ -8816,7 +9620,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8816
9620
|
)) {
|
|
8817
9621
|
return true;
|
|
8818
9622
|
}
|
|
8819
|
-
if (
|
|
9623
|
+
if (ts6.isNewExpression(expression) && expression.arguments && expression.arguments.length > 0 && expressionLooksLikeBrowserGlobalStringHelper(
|
|
8820
9624
|
expression.expression,
|
|
8821
9625
|
sourceFile,
|
|
8822
9626
|
namedExpressions,
|
|
@@ -8848,7 +9652,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8848
9652
|
)) {
|
|
8849
9653
|
return true;
|
|
8850
9654
|
}
|
|
8851
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9655
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalSymbolHelper(
|
|
8852
9656
|
expression.arguments[0],
|
|
8853
9657
|
sourceFile,
|
|
8854
9658
|
namedExpressions,
|
|
@@ -8912,7 +9716,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8912
9716
|
)) {
|
|
8913
9717
|
return true;
|
|
8914
9718
|
}
|
|
8915
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9719
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalBigIntHelper(
|
|
8916
9720
|
expression.arguments[0],
|
|
8917
9721
|
sourceFile,
|
|
8918
9722
|
namedExpressions,
|
|
@@ -8976,7 +9780,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
8976
9780
|
)) {
|
|
8977
9781
|
return true;
|
|
8978
9782
|
}
|
|
8979
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9783
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalBooleanHelper(
|
|
8980
9784
|
expression.arguments[0],
|
|
8981
9785
|
sourceFile,
|
|
8982
9786
|
namedExpressions,
|
|
@@ -9040,7 +9844,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9040
9844
|
)) {
|
|
9041
9845
|
return true;
|
|
9042
9846
|
}
|
|
9043
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9847
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalNumberHelper(
|
|
9044
9848
|
expression.arguments[0],
|
|
9045
9849
|
sourceFile,
|
|
9046
9850
|
namedExpressions,
|
|
@@ -9104,7 +9908,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9104
9908
|
)) {
|
|
9105
9909
|
return true;
|
|
9106
9910
|
}
|
|
9107
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9911
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalObjectHelper(
|
|
9108
9912
|
expression.arguments[0],
|
|
9109
9913
|
sourceFile,
|
|
9110
9914
|
namedExpressions,
|
|
@@ -9152,7 +9956,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9152
9956
|
)) {
|
|
9153
9957
|
return true;
|
|
9154
9958
|
}
|
|
9155
|
-
if (isCallLikeExpression(expression) &&
|
|
9959
|
+
if (isCallLikeExpression(expression) && ts6.isIdentifier(expression.expression) && [
|
|
9156
9960
|
"String",
|
|
9157
9961
|
"atob",
|
|
9158
9962
|
"btoa",
|
|
@@ -9188,7 +9992,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9188
9992
|
)) {
|
|
9189
9993
|
return true;
|
|
9190
9994
|
}
|
|
9191
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
9995
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeJsonStringifyHelper(
|
|
9192
9996
|
expression.arguments[0],
|
|
9193
9997
|
sourceFile,
|
|
9194
9998
|
namedExpressions,
|
|
@@ -9252,7 +10056,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9252
10056
|
)) {
|
|
9253
10057
|
return true;
|
|
9254
10058
|
}
|
|
9255
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10059
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeJsonParseHelper(
|
|
9256
10060
|
expression.arguments[0],
|
|
9257
10061
|
sourceFile,
|
|
9258
10062
|
namedExpressions,
|
|
@@ -9316,7 +10120,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9316
10120
|
)) {
|
|
9317
10121
|
return true;
|
|
9318
10122
|
}
|
|
9319
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10123
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeStructuredCloneHelper(
|
|
9320
10124
|
expression.arguments[0],
|
|
9321
10125
|
sourceFile,
|
|
9322
10126
|
namedExpressions,
|
|
@@ -9380,7 +10184,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9380
10184
|
)) {
|
|
9381
10185
|
return true;
|
|
9382
10186
|
}
|
|
9383
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10187
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalStringHelper(
|
|
9384
10188
|
expression.arguments[0],
|
|
9385
10189
|
sourceFile,
|
|
9386
10190
|
namedExpressions,
|
|
@@ -9460,7 +10264,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9460
10264
|
)) {
|
|
9461
10265
|
return true;
|
|
9462
10266
|
}
|
|
9463
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10267
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalUriCodecHelper(
|
|
9464
10268
|
expression.arguments[0],
|
|
9465
10269
|
sourceFile,
|
|
9466
10270
|
namedExpressions,
|
|
@@ -9508,7 +10312,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9508
10312
|
)) {
|
|
9509
10313
|
return true;
|
|
9510
10314
|
}
|
|
9511
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10315
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBrowserGlobalBase64Helper(
|
|
9512
10316
|
expression.arguments[0],
|
|
9513
10317
|
sourceFile,
|
|
9514
10318
|
namedExpressions,
|
|
@@ -9556,7 +10360,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9556
10360
|
)) {
|
|
9557
10361
|
return true;
|
|
9558
10362
|
}
|
|
9559
|
-
if (isCallLikeExpression(expression) && (
|
|
10363
|
+
if (isCallLikeExpression(expression) && (ts6.isIdentifier(expression.expression) || isMemberAccessExpression(expression.expression)) && expression.arguments.length > 0 && expressionLooksLikeBufferFromHelper(
|
|
9560
10364
|
expression.expression,
|
|
9561
10365
|
sourceFile,
|
|
9562
10366
|
namedExpressions,
|
|
@@ -9608,7 +10412,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9608
10412
|
)) {
|
|
9609
10413
|
return true;
|
|
9610
10414
|
}
|
|
9611
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10415
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && expression.arguments.length > 2 && expressionLooksLikeBufferFromHelper(
|
|
9612
10416
|
expression.arguments[0],
|
|
9613
10417
|
sourceFile,
|
|
9614
10418
|
namedExpressions,
|
|
@@ -9656,7 +10460,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9656
10460
|
)) {
|
|
9657
10461
|
return true;
|
|
9658
10462
|
}
|
|
9659
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "from") &&
|
|
10463
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "from") && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Buffer" && expression.arguments.length > 0 && expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
9660
10464
|
expression.arguments[0],
|
|
9661
10465
|
sourceFile,
|
|
9662
10466
|
namedExpressions,
|
|
@@ -9835,7 +10639,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9835
10639
|
)) {
|
|
9836
10640
|
return true;
|
|
9837
10641
|
}
|
|
9838
|
-
if (isElementLikeAccessExpression(expression) &&
|
|
10642
|
+
if (isElementLikeAccessExpression(expression) && ts6.isNumericLiteral(expression.argumentExpression) && expression.argumentExpression.text === "1" && isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "value") && isCallLikeExpression(expression.expression.expression) && isMemberAccessExpression(expression.expression.expression.expression) && isMemberAccessNamed(expression.expression.expression.expression, "next") && isCallLikeExpression(expression.expression.expression.expression.expression) && isMemberAccessExpression(expression.expression.expression.expression.expression.expression) && isMemberAccessNamed(
|
|
9839
10643
|
expression.expression.expression.expression.expression.expression,
|
|
9840
10644
|
"entries"
|
|
9841
10645
|
) && expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
@@ -9868,7 +10672,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9868
10672
|
)) {
|
|
9869
10673
|
return true;
|
|
9870
10674
|
}
|
|
9871
|
-
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) &&
|
|
10675
|
+
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Array" && isPropertyNamed(expression.expression.name, "from") && expression.arguments.length > 0 && expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
9872
10676
|
expression.arguments[0],
|
|
9873
10677
|
sourceFile,
|
|
9874
10678
|
namedExpressions,
|
|
@@ -9878,8 +10682,8 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9878
10682
|
)) {
|
|
9879
10683
|
return true;
|
|
9880
10684
|
}
|
|
9881
|
-
if (
|
|
9882
|
-
(element) =>
|
|
10685
|
+
if (ts6.isArrayLiteralExpression(expression) && expression.elements.some(
|
|
10686
|
+
(element) => ts6.isSpreadElement(element) && expressionLooksLikeOpenRedirectQueryGetterFunction(
|
|
9883
10687
|
element.expression,
|
|
9884
10688
|
sourceFile,
|
|
9885
10689
|
namedExpressions,
|
|
@@ -9930,7 +10734,7 @@ function expressionLooksLikeOpenRedirectQueryGetterFunction(expression, sourceFi
|
|
|
9930
10734
|
)) {
|
|
9931
10735
|
return true;
|
|
9932
10736
|
}
|
|
9933
|
-
if (
|
|
10737
|
+
if (ts6.isIdentifier(expression)) {
|
|
9934
10738
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
9935
10739
|
const initializer = namedExpressions.get(expression.text);
|
|
9936
10740
|
if (initializer) {
|
|
@@ -9964,7 +10768,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
9964
10768
|
if (OPEN_REDIRECT_SOURCE_REGEX.test(expression.getText(sourceFile))) {
|
|
9965
10769
|
return true;
|
|
9966
10770
|
}
|
|
9967
|
-
if (
|
|
10771
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
9968
10772
|
return expressionContainsOpenRedirectSource(
|
|
9969
10773
|
expression.expression,
|
|
9970
10774
|
sourceFile,
|
|
@@ -9974,7 +10778,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
9974
10778
|
seenFunctions
|
|
9975
10779
|
);
|
|
9976
10780
|
}
|
|
9977
|
-
if (
|
|
10781
|
+
if (ts6.isBinaryExpression(expression)) {
|
|
9978
10782
|
return expressionContainsOpenRedirectSource(
|
|
9979
10783
|
expression.left,
|
|
9980
10784
|
sourceFile,
|
|
@@ -9991,7 +10795,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
9991
10795
|
seenFunctions
|
|
9992
10796
|
);
|
|
9993
10797
|
}
|
|
9994
|
-
if (
|
|
10798
|
+
if (ts6.isConditionalExpression(expression)) {
|
|
9995
10799
|
return expressionContainsOpenRedirectSource(
|
|
9996
10800
|
expression.condition,
|
|
9997
10801
|
sourceFile,
|
|
@@ -10015,7 +10819,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10015
10819
|
seenFunctions
|
|
10016
10820
|
);
|
|
10017
10821
|
}
|
|
10018
|
-
if (
|
|
10822
|
+
if (ts6.isTemplateExpression(expression)) {
|
|
10019
10823
|
return expression.templateSpans.some(
|
|
10020
10824
|
(span) => expressionContainsOpenRedirectSource(
|
|
10021
10825
|
span.expression,
|
|
@@ -10027,7 +10831,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10027
10831
|
)
|
|
10028
10832
|
);
|
|
10029
10833
|
}
|
|
10030
|
-
if (
|
|
10834
|
+
if (ts6.isTaggedTemplateExpression(expression)) {
|
|
10031
10835
|
return expressionContainsOpenRedirectSource(
|
|
10032
10836
|
expression.template,
|
|
10033
10837
|
sourceFile,
|
|
@@ -10037,7 +10841,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10037
10841
|
seenFunctions
|
|
10038
10842
|
);
|
|
10039
10843
|
}
|
|
10040
|
-
if (
|
|
10844
|
+
if (ts6.isNewExpression(expression)) {
|
|
10041
10845
|
return (expression.arguments ?? []).some(
|
|
10042
10846
|
(argument) => expressionContainsOpenRedirectSource(
|
|
10043
10847
|
argument,
|
|
@@ -10049,9 +10853,9 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10049
10853
|
)
|
|
10050
10854
|
);
|
|
10051
10855
|
}
|
|
10052
|
-
if (
|
|
10856
|
+
if (ts6.isArrayLiteralExpression(expression)) {
|
|
10053
10857
|
return expression.elements.some((element) => {
|
|
10054
|
-
if (
|
|
10858
|
+
if (ts6.isSpreadElement(element)) {
|
|
10055
10859
|
return expressionContainsOpenRedirectSource(
|
|
10056
10860
|
element.expression,
|
|
10057
10861
|
sourceFile,
|
|
@@ -10061,7 +10865,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10061
10865
|
seenFunctions
|
|
10062
10866
|
);
|
|
10063
10867
|
}
|
|
10064
|
-
return
|
|
10868
|
+
return ts6.isExpression(element) && expressionContainsOpenRedirectSource(
|
|
10065
10869
|
element,
|
|
10066
10870
|
sourceFile,
|
|
10067
10871
|
namedExpressions,
|
|
@@ -10071,9 +10875,9 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10071
10875
|
);
|
|
10072
10876
|
});
|
|
10073
10877
|
}
|
|
10074
|
-
if (
|
|
10878
|
+
if (ts6.isObjectLiteralExpression(expression)) {
|
|
10075
10879
|
return expression.properties.some((property) => {
|
|
10076
|
-
if (
|
|
10880
|
+
if (ts6.isPropertyAssignment(property)) {
|
|
10077
10881
|
return expressionContainsOpenRedirectSource(
|
|
10078
10882
|
property.initializer,
|
|
10079
10883
|
sourceFile,
|
|
@@ -10083,7 +10887,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10083
10887
|
seenFunctions
|
|
10084
10888
|
);
|
|
10085
10889
|
}
|
|
10086
|
-
if (
|
|
10890
|
+
if (ts6.isShorthandPropertyAssignment(property)) {
|
|
10087
10891
|
return expressionContainsOpenRedirectSource(
|
|
10088
10892
|
property.name,
|
|
10089
10893
|
sourceFile,
|
|
@@ -10093,7 +10897,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10093
10897
|
seenFunctions
|
|
10094
10898
|
);
|
|
10095
10899
|
}
|
|
10096
|
-
if (
|
|
10900
|
+
if (ts6.isSpreadAssignment(property)) {
|
|
10097
10901
|
return expressionContainsOpenRedirectSource(
|
|
10098
10902
|
property.expression,
|
|
10099
10903
|
sourceFile,
|
|
@@ -10148,7 +10952,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10148
10952
|
}
|
|
10149
10953
|
}
|
|
10150
10954
|
}
|
|
10151
|
-
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) &&
|
|
10955
|
+
if (isCallLikeExpression(expression) && isMemberAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Reflect" && isMemberAccessNamed(expression.expression, "apply") && isOpenRedirectQueryKeyExpression(
|
|
10152
10956
|
getAliasedApplyArgumentExpression(expression.arguments[2], 0, namedExpressions, /* @__PURE__ */ new Set()),
|
|
10153
10957
|
namedExpressions,
|
|
10154
10958
|
seenIdentifiers
|
|
@@ -10264,7 +11068,7 @@ function expressionContainsOpenRedirectSource(expression, sourceFile, namedExpre
|
|
|
10264
11068
|
)) {
|
|
10265
11069
|
return true;
|
|
10266
11070
|
}
|
|
10267
|
-
if (
|
|
11071
|
+
if (ts6.isIdentifier(expression)) {
|
|
10268
11072
|
if (seenIdentifiers.has(expression.text)) {
|
|
10269
11073
|
return false;
|
|
10270
11074
|
}
|
|
@@ -10302,14 +11106,14 @@ function isOpenRedirectQueryKeyExpression(expression, namedExpressions = /* @__P
|
|
|
10302
11106
|
return true;
|
|
10303
11107
|
}
|
|
10304
11108
|
if (!expression) return false;
|
|
10305
|
-
if (
|
|
11109
|
+
if (ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression) || ts6.isParenthesizedExpression(expression)) {
|
|
10306
11110
|
return isOpenRedirectQueryKeyExpression(
|
|
10307
11111
|
expression.expression,
|
|
10308
11112
|
namedExpressions,
|
|
10309
11113
|
seenIdentifiers
|
|
10310
11114
|
);
|
|
10311
11115
|
}
|
|
10312
|
-
if (
|
|
11116
|
+
if (ts6.isIdentifier(expression)) {
|
|
10313
11117
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10314
11118
|
const initializer = namedExpressions.get(expression.text);
|
|
10315
11119
|
if (!initializer) return false;
|
|
@@ -10325,7 +11129,7 @@ function expressionLooksLikeOpenRedirectQueryCarrier(expression, sourceFile, nam
|
|
|
10325
11129
|
if (OPEN_REDIRECT_QUERY_CARRIER_REGEX.test(expression.getText(sourceFile))) {
|
|
10326
11130
|
return true;
|
|
10327
11131
|
}
|
|
10328
|
-
if (
|
|
11132
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10329
11133
|
return expressionLooksLikeOpenRedirectQueryCarrier(
|
|
10330
11134
|
expression.expression,
|
|
10331
11135
|
sourceFile,
|
|
@@ -10334,7 +11138,7 @@ function expressionLooksLikeOpenRedirectQueryCarrier(expression, sourceFile, nam
|
|
|
10334
11138
|
seenIdentifiers
|
|
10335
11139
|
);
|
|
10336
11140
|
}
|
|
10337
|
-
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) &&
|
|
11141
|
+
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Object" && isPropertyNamed(expression.expression.name, "fromEntries") && expression.arguments.length > 0) {
|
|
10338
11142
|
const entriesExpression = expression.arguments[0];
|
|
10339
11143
|
if (expressionLooksLikeOpenRedirectSearchParamsCarrier(
|
|
10340
11144
|
entriesExpression,
|
|
@@ -10364,7 +11168,7 @@ function expressionLooksLikeOpenRedirectQueryCarrier(expression, sourceFile, nam
|
|
|
10364
11168
|
seenIdentifiers
|
|
10365
11169
|
);
|
|
10366
11170
|
}
|
|
10367
|
-
if (
|
|
11171
|
+
if (ts6.isIdentifier(expression)) {
|
|
10368
11172
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10369
11173
|
const initializer = namedExpressions.get(expression.text);
|
|
10370
11174
|
if (initializer) {
|
|
@@ -10397,7 +11201,7 @@ function expressionLooksLikeOpenRedirectQueryCarrier(expression, sourceFile, nam
|
|
|
10397
11201
|
}
|
|
10398
11202
|
function expressionLooksLikeOpenRedirectEntriesCarrier(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
10399
11203
|
if (!expression) return false;
|
|
10400
|
-
if (
|
|
11204
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10401
11205
|
return expressionLooksLikeOpenRedirectEntriesCarrier(
|
|
10402
11206
|
expression.expression,
|
|
10403
11207
|
sourceFile,
|
|
@@ -10406,7 +11210,7 @@ function expressionLooksLikeOpenRedirectEntriesCarrier(expression, sourceFile, n
|
|
|
10406
11210
|
seenIdentifiers
|
|
10407
11211
|
);
|
|
10408
11212
|
}
|
|
10409
|
-
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) &&
|
|
11213
|
+
if (isCallLikeExpression(expression) && isPropertyLikeAccessExpression(expression.expression) && ts6.isIdentifier(expression.expression.expression) && expression.expression.expression.text === "Array" && isPropertyNamed(expression.expression.name, "from") && expression.arguments.length > 0 && (expressionLooksLikeOpenRedirectEntriesCarrier(
|
|
10410
11214
|
expression.arguments[0],
|
|
10411
11215
|
sourceFile,
|
|
10412
11216
|
namedExpressions,
|
|
@@ -10421,8 +11225,8 @@ function expressionLooksLikeOpenRedirectEntriesCarrier(expression, sourceFile, n
|
|
|
10421
11225
|
))) {
|
|
10422
11226
|
return true;
|
|
10423
11227
|
}
|
|
10424
|
-
if (
|
|
10425
|
-
(element) =>
|
|
11228
|
+
if (ts6.isArrayLiteralExpression(expression) && expression.elements.some(
|
|
11229
|
+
(element) => ts6.isSpreadElement(element) && (expressionLooksLikeOpenRedirectEntriesCarrier(
|
|
10426
11230
|
element.expression,
|
|
10427
11231
|
sourceFile,
|
|
10428
11232
|
namedExpressions,
|
|
@@ -10447,7 +11251,7 @@ function expressionLooksLikeOpenRedirectEntriesCarrier(expression, sourceFile, n
|
|
|
10447
11251
|
)) {
|
|
10448
11252
|
return true;
|
|
10449
11253
|
}
|
|
10450
|
-
if (
|
|
11254
|
+
if (ts6.isIdentifier(expression)) {
|
|
10451
11255
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10452
11256
|
const initializer = namedExpressions.get(expression.text);
|
|
10453
11257
|
if (!initializer) return false;
|
|
@@ -10469,7 +11273,7 @@ function expressionLooksLikeOpenRedirectQueryContainerBase(expression, sourceFil
|
|
|
10469
11273
|
if (OPEN_REDIRECT_QUERY_CONTAINER_BASE_REGEX.test(expression.getText(sourceFile))) {
|
|
10470
11274
|
return true;
|
|
10471
11275
|
}
|
|
10472
|
-
if (
|
|
11276
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10473
11277
|
return expressionLooksLikeOpenRedirectQueryContainerBase(
|
|
10474
11278
|
expression.expression,
|
|
10475
11279
|
sourceFile,
|
|
@@ -10478,10 +11282,10 @@ function expressionLooksLikeOpenRedirectQueryContainerBase(expression, sourceFil
|
|
|
10478
11282
|
seenIdentifiers
|
|
10479
11283
|
);
|
|
10480
11284
|
}
|
|
10481
|
-
if (isCallLikeExpression(expression) && (
|
|
11285
|
+
if (isCallLikeExpression(expression) && (ts6.isIdentifier(expression.expression) && expression.expression.text === "useRouter" || isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "useRouter"))) {
|
|
10482
11286
|
return true;
|
|
10483
11287
|
}
|
|
10484
|
-
if (
|
|
11288
|
+
if (ts6.isIdentifier(expression)) {
|
|
10485
11289
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10486
11290
|
const initializer = namedExpressions.get(expression.text);
|
|
10487
11291
|
if (initializer) {
|
|
@@ -10519,7 +11323,7 @@ function expressionLooksLikeLocationQuerySource(expression, sourceFile, namedExp
|
|
|
10519
11323
|
if (LOCATION_QUERY_SOURCE_REGEX.test(expression.getText(sourceFile))) {
|
|
10520
11324
|
return true;
|
|
10521
11325
|
}
|
|
10522
|
-
if (
|
|
11326
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10523
11327
|
return expressionLooksLikeLocationQuerySource(
|
|
10524
11328
|
expression.expression,
|
|
10525
11329
|
sourceFile,
|
|
@@ -10552,7 +11356,7 @@ function expressionLooksLikeLocationQuerySource(expression, sourceFile, namedExp
|
|
|
10552
11356
|
))) {
|
|
10553
11357
|
return true;
|
|
10554
11358
|
}
|
|
10555
|
-
if (
|
|
11359
|
+
if (ts6.isIdentifier(expression)) {
|
|
10556
11360
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10557
11361
|
const initializer = namedExpressions.get(expression.text);
|
|
10558
11362
|
if (initializer) {
|
|
@@ -10588,10 +11392,10 @@ function expressionLooksLikeLocationQuerySource(expression, sourceFile, namedExp
|
|
|
10588
11392
|
}
|
|
10589
11393
|
function expressionLooksLikeWindowObjectSource(expression, sourceFile, namedExpressions, seenIdentifiers) {
|
|
10590
11394
|
if (!expression) return false;
|
|
10591
|
-
if (
|
|
11395
|
+
if (ts6.isIdentifier(expression) && ["window", "globalThis", "document", "self", "parent", "top"].includes(expression.text)) {
|
|
10592
11396
|
return true;
|
|
10593
11397
|
}
|
|
10594
|
-
if (
|
|
11398
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10595
11399
|
return expressionLooksLikeWindowObjectSource(
|
|
10596
11400
|
expression.expression,
|
|
10597
11401
|
sourceFile,
|
|
@@ -10599,7 +11403,7 @@ function expressionLooksLikeWindowObjectSource(expression, sourceFile, namedExpr
|
|
|
10599
11403
|
seenIdentifiers
|
|
10600
11404
|
);
|
|
10601
11405
|
}
|
|
10602
|
-
if (
|
|
11406
|
+
if (ts6.isIdentifier(expression)) {
|
|
10603
11407
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10604
11408
|
const initializer = namedExpressions.get(expression.text);
|
|
10605
11409
|
if (!initializer) return false;
|
|
@@ -10620,7 +11424,7 @@ function expressionLooksLikeLocationObjectSource(expression, sourceFile, namedEx
|
|
|
10620
11424
|
if (isLocationObjectExpression(expression)) {
|
|
10621
11425
|
return true;
|
|
10622
11426
|
}
|
|
10623
|
-
if (
|
|
11427
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10624
11428
|
return expressionLooksLikeLocationObjectSource(
|
|
10625
11429
|
expression.expression,
|
|
10626
11430
|
sourceFile,
|
|
@@ -10629,7 +11433,7 @@ function expressionLooksLikeLocationObjectSource(expression, sourceFile, namedEx
|
|
|
10629
11433
|
seenIdentifiers
|
|
10630
11434
|
);
|
|
10631
11435
|
}
|
|
10632
|
-
if (isCallLikeExpression(expression) && (
|
|
11436
|
+
if (isCallLikeExpression(expression) && (ts6.isIdentifier(expression.expression) && expression.expression.text === "useLocation" || isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "useLocation"))) {
|
|
10633
11437
|
return true;
|
|
10634
11438
|
}
|
|
10635
11439
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "location") && expressionLooksLikeWindowObjectSource(
|
|
@@ -10640,7 +11444,7 @@ function expressionLooksLikeLocationObjectSource(expression, sourceFile, namedEx
|
|
|
10640
11444
|
)) {
|
|
10641
11445
|
return true;
|
|
10642
11446
|
}
|
|
10643
|
-
if (
|
|
11447
|
+
if (ts6.isIdentifier(expression)) {
|
|
10644
11448
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10645
11449
|
const initializer = namedExpressions.get(expression.text);
|
|
10646
11450
|
if (initializer) {
|
|
@@ -10669,10 +11473,10 @@ function expressionLooksLikeLocationObjectSource(expression, sourceFile, namedEx
|
|
|
10669
11473
|
}
|
|
10670
11474
|
function expressionLooksLikeHistoryObjectSource(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
10671
11475
|
if (!expression) return false;
|
|
10672
|
-
if (
|
|
11476
|
+
if (ts6.isIdentifier(expression) && expression.text === "history") {
|
|
10673
11477
|
return true;
|
|
10674
11478
|
}
|
|
10675
|
-
if (
|
|
11479
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10676
11480
|
return expressionLooksLikeHistoryObjectSource(
|
|
10677
11481
|
expression.expression,
|
|
10678
11482
|
sourceFile,
|
|
@@ -10689,7 +11493,7 @@ function expressionLooksLikeHistoryObjectSource(expression, sourceFile, namedExp
|
|
|
10689
11493
|
)) {
|
|
10690
11494
|
return true;
|
|
10691
11495
|
}
|
|
10692
|
-
if (
|
|
11496
|
+
if (ts6.isIdentifier(expression)) {
|
|
10693
11497
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10694
11498
|
const initializer = namedExpressions.get(expression.text);
|
|
10695
11499
|
if (initializer) {
|
|
@@ -10718,10 +11522,10 @@ function expressionLooksLikeHistoryObjectSource(expression, sourceFile, namedExp
|
|
|
10718
11522
|
}
|
|
10719
11523
|
function expressionLooksLikeBufferObjectSource(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
10720
11524
|
if (!expression) return false;
|
|
10721
|
-
if (
|
|
11525
|
+
if (ts6.isIdentifier(expression) && expression.text === "Buffer") {
|
|
10722
11526
|
return true;
|
|
10723
11527
|
}
|
|
10724
|
-
if (
|
|
11528
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10725
11529
|
return expressionLooksLikeBufferObjectSource(
|
|
10726
11530
|
expression.expression,
|
|
10727
11531
|
sourceFile,
|
|
@@ -10738,7 +11542,7 @@ function expressionLooksLikeBufferObjectSource(expression, sourceFile, namedExpr
|
|
|
10738
11542
|
)) {
|
|
10739
11543
|
return true;
|
|
10740
11544
|
}
|
|
10741
|
-
if (
|
|
11545
|
+
if (ts6.isIdentifier(expression)) {
|
|
10742
11546
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10743
11547
|
const initializer = namedExpressions.get(expression.text);
|
|
10744
11548
|
if (initializer) {
|
|
@@ -10785,7 +11589,7 @@ function expressionLooksLikeBufferFromHelper(expression, sourceFile, namedExpres
|
|
|
10785
11589
|
)) {
|
|
10786
11590
|
return true;
|
|
10787
11591
|
}
|
|
10788
|
-
if (
|
|
11592
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10789
11593
|
return expressionLooksLikeBufferFromHelper(
|
|
10790
11594
|
expression.expression,
|
|
10791
11595
|
sourceFile,
|
|
@@ -10794,7 +11598,7 @@ function expressionLooksLikeBufferFromHelper(expression, sourceFile, namedExpres
|
|
|
10794
11598
|
seenIdentifiers
|
|
10795
11599
|
);
|
|
10796
11600
|
}
|
|
10797
|
-
if (
|
|
11601
|
+
if (ts6.isIdentifier(expression)) {
|
|
10798
11602
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10799
11603
|
const initializer = namedExpressions.get(expression.text);
|
|
10800
11604
|
if (initializer) {
|
|
@@ -10824,10 +11628,10 @@ function expressionLooksLikeBufferFromHelper(expression, sourceFile, namedExpres
|
|
|
10824
11628
|
}
|
|
10825
11629
|
function expressionLooksLikeJsonObjectSource(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
10826
11630
|
if (!expression) return false;
|
|
10827
|
-
if (
|
|
11631
|
+
if (ts6.isIdentifier(expression) && expression.text === "JSON") {
|
|
10828
11632
|
return true;
|
|
10829
11633
|
}
|
|
10830
|
-
if (
|
|
11634
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10831
11635
|
return expressionLooksLikeJsonObjectSource(
|
|
10832
11636
|
expression.expression,
|
|
10833
11637
|
sourceFile,
|
|
@@ -10844,7 +11648,7 @@ function expressionLooksLikeJsonObjectSource(expression, sourceFile, namedExpres
|
|
|
10844
11648
|
)) {
|
|
10845
11649
|
return true;
|
|
10846
11650
|
}
|
|
10847
|
-
if (
|
|
11651
|
+
if (ts6.isIdentifier(expression)) {
|
|
10848
11652
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10849
11653
|
const initializer = namedExpressions.get(expression.text);
|
|
10850
11654
|
if (initializer) {
|
|
@@ -10891,7 +11695,7 @@ function expressionLooksLikeJsonStringifyHelper(expression, sourceFile, namedExp
|
|
|
10891
11695
|
)) {
|
|
10892
11696
|
return true;
|
|
10893
11697
|
}
|
|
10894
|
-
if (
|
|
11698
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10895
11699
|
return expressionLooksLikeJsonStringifyHelper(
|
|
10896
11700
|
expression.expression,
|
|
10897
11701
|
sourceFile,
|
|
@@ -10900,7 +11704,7 @@ function expressionLooksLikeJsonStringifyHelper(expression, sourceFile, namedExp
|
|
|
10900
11704
|
seenIdentifiers
|
|
10901
11705
|
);
|
|
10902
11706
|
}
|
|
10903
|
-
if (
|
|
11707
|
+
if (ts6.isIdentifier(expression)) {
|
|
10904
11708
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10905
11709
|
const initializer = namedExpressions.get(expression.text);
|
|
10906
11710
|
if (initializer) {
|
|
@@ -10948,7 +11752,7 @@ function expressionLooksLikeJsonParseHelper(expression, sourceFile, namedExpress
|
|
|
10948
11752
|
)) {
|
|
10949
11753
|
return true;
|
|
10950
11754
|
}
|
|
10951
|
-
if (
|
|
11755
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
10952
11756
|
return expressionLooksLikeJsonParseHelper(
|
|
10953
11757
|
expression.expression,
|
|
10954
11758
|
sourceFile,
|
|
@@ -10957,7 +11761,7 @@ function expressionLooksLikeJsonParseHelper(expression, sourceFile, namedExpress
|
|
|
10957
11761
|
seenIdentifiers
|
|
10958
11762
|
);
|
|
10959
11763
|
}
|
|
10960
|
-
if (
|
|
11764
|
+
if (ts6.isIdentifier(expression)) {
|
|
10961
11765
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
10962
11766
|
const initializer = namedExpressions.get(expression.text);
|
|
10963
11767
|
if (initializer) {
|
|
@@ -10987,7 +11791,7 @@ function expressionLooksLikeJsonParseHelper(expression, sourceFile, namedExpress
|
|
|
10987
11791
|
}
|
|
10988
11792
|
function expressionLooksLikeStructuredCloneHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
10989
11793
|
if (!expression) return false;
|
|
10990
|
-
if (
|
|
11794
|
+
if (ts6.isIdentifier(expression) && expression.text === "structuredClone") {
|
|
10991
11795
|
return true;
|
|
10992
11796
|
}
|
|
10993
11797
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "structuredClone") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11007,7 +11811,7 @@ function expressionLooksLikeStructuredCloneHelper(expression, sourceFile, namedE
|
|
|
11007
11811
|
)) {
|
|
11008
11812
|
return true;
|
|
11009
11813
|
}
|
|
11010
|
-
if (
|
|
11814
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11011
11815
|
return expressionLooksLikeStructuredCloneHelper(
|
|
11012
11816
|
expression.expression,
|
|
11013
11817
|
sourceFile,
|
|
@@ -11016,7 +11820,7 @@ function expressionLooksLikeStructuredCloneHelper(expression, sourceFile, namedE
|
|
|
11016
11820
|
seenIdentifiers
|
|
11017
11821
|
);
|
|
11018
11822
|
}
|
|
11019
|
-
if (
|
|
11823
|
+
if (ts6.isIdentifier(expression)) {
|
|
11020
11824
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11021
11825
|
const initializer = namedExpressions.get(expression.text);
|
|
11022
11826
|
if (initializer) {
|
|
@@ -11045,7 +11849,7 @@ function expressionLooksLikeStructuredCloneHelper(expression, sourceFile, namedE
|
|
|
11045
11849
|
}
|
|
11046
11850
|
function expressionLooksLikeBrowserGlobalSymbolHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11047
11851
|
if (!expression) return false;
|
|
11048
|
-
if (
|
|
11852
|
+
if (ts6.isIdentifier(expression) && expression.text === "Symbol") {
|
|
11049
11853
|
return true;
|
|
11050
11854
|
}
|
|
11051
11855
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "Symbol") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11065,7 +11869,7 @@ function expressionLooksLikeBrowserGlobalSymbolHelper(expression, sourceFile, na
|
|
|
11065
11869
|
)) {
|
|
11066
11870
|
return true;
|
|
11067
11871
|
}
|
|
11068
|
-
if (
|
|
11872
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11069
11873
|
return expressionLooksLikeBrowserGlobalSymbolHelper(
|
|
11070
11874
|
expression.expression,
|
|
11071
11875
|
sourceFile,
|
|
@@ -11074,7 +11878,7 @@ function expressionLooksLikeBrowserGlobalSymbolHelper(expression, sourceFile, na
|
|
|
11074
11878
|
seenIdentifiers
|
|
11075
11879
|
);
|
|
11076
11880
|
}
|
|
11077
|
-
if (
|
|
11881
|
+
if (ts6.isIdentifier(expression)) {
|
|
11078
11882
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11079
11883
|
const initializer = namedExpressions.get(expression.text);
|
|
11080
11884
|
if (initializer) {
|
|
@@ -11103,7 +11907,7 @@ function expressionLooksLikeBrowserGlobalSymbolHelper(expression, sourceFile, na
|
|
|
11103
11907
|
}
|
|
11104
11908
|
function expressionLooksLikeBrowserGlobalBigIntHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11105
11909
|
if (!expression) return false;
|
|
11106
|
-
if (
|
|
11910
|
+
if (ts6.isIdentifier(expression) && expression.text === "BigInt") {
|
|
11107
11911
|
return true;
|
|
11108
11912
|
}
|
|
11109
11913
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "BigInt") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11123,7 +11927,7 @@ function expressionLooksLikeBrowserGlobalBigIntHelper(expression, sourceFile, na
|
|
|
11123
11927
|
)) {
|
|
11124
11928
|
return true;
|
|
11125
11929
|
}
|
|
11126
|
-
if (
|
|
11930
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11127
11931
|
return expressionLooksLikeBrowserGlobalBigIntHelper(
|
|
11128
11932
|
expression.expression,
|
|
11129
11933
|
sourceFile,
|
|
@@ -11132,7 +11936,7 @@ function expressionLooksLikeBrowserGlobalBigIntHelper(expression, sourceFile, na
|
|
|
11132
11936
|
seenIdentifiers
|
|
11133
11937
|
);
|
|
11134
11938
|
}
|
|
11135
|
-
if (
|
|
11939
|
+
if (ts6.isIdentifier(expression)) {
|
|
11136
11940
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11137
11941
|
const initializer = namedExpressions.get(expression.text);
|
|
11138
11942
|
if (initializer) {
|
|
@@ -11161,7 +11965,7 @@ function expressionLooksLikeBrowserGlobalBigIntHelper(expression, sourceFile, na
|
|
|
11161
11965
|
}
|
|
11162
11966
|
function expressionLooksLikeBrowserGlobalBooleanHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11163
11967
|
if (!expression) return false;
|
|
11164
|
-
if (
|
|
11968
|
+
if (ts6.isIdentifier(expression) && expression.text === "Boolean") {
|
|
11165
11969
|
return true;
|
|
11166
11970
|
}
|
|
11167
11971
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "Boolean") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11181,7 +11985,7 @@ function expressionLooksLikeBrowserGlobalBooleanHelper(expression, sourceFile, n
|
|
|
11181
11985
|
)) {
|
|
11182
11986
|
return true;
|
|
11183
11987
|
}
|
|
11184
|
-
if (
|
|
11988
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11185
11989
|
return expressionLooksLikeBrowserGlobalBooleanHelper(
|
|
11186
11990
|
expression.expression,
|
|
11187
11991
|
sourceFile,
|
|
@@ -11190,7 +11994,7 @@ function expressionLooksLikeBrowserGlobalBooleanHelper(expression, sourceFile, n
|
|
|
11190
11994
|
seenIdentifiers
|
|
11191
11995
|
);
|
|
11192
11996
|
}
|
|
11193
|
-
if (
|
|
11997
|
+
if (ts6.isIdentifier(expression)) {
|
|
11194
11998
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11195
11999
|
const initializer = namedExpressions.get(expression.text);
|
|
11196
12000
|
if (initializer) {
|
|
@@ -11219,7 +12023,7 @@ function expressionLooksLikeBrowserGlobalBooleanHelper(expression, sourceFile, n
|
|
|
11219
12023
|
}
|
|
11220
12024
|
function expressionLooksLikeBrowserGlobalNumberHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11221
12025
|
if (!expression) return false;
|
|
11222
|
-
if (
|
|
12026
|
+
if (ts6.isIdentifier(expression) && expression.text === "Number") {
|
|
11223
12027
|
return true;
|
|
11224
12028
|
}
|
|
11225
12029
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "Number") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11239,7 +12043,7 @@ function expressionLooksLikeBrowserGlobalNumberHelper(expression, sourceFile, na
|
|
|
11239
12043
|
)) {
|
|
11240
12044
|
return true;
|
|
11241
12045
|
}
|
|
11242
|
-
if (
|
|
12046
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11243
12047
|
return expressionLooksLikeBrowserGlobalNumberHelper(
|
|
11244
12048
|
expression.expression,
|
|
11245
12049
|
sourceFile,
|
|
@@ -11248,7 +12052,7 @@ function expressionLooksLikeBrowserGlobalNumberHelper(expression, sourceFile, na
|
|
|
11248
12052
|
seenIdentifiers
|
|
11249
12053
|
);
|
|
11250
12054
|
}
|
|
11251
|
-
if (
|
|
12055
|
+
if (ts6.isIdentifier(expression)) {
|
|
11252
12056
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11253
12057
|
const initializer = namedExpressions.get(expression.text);
|
|
11254
12058
|
if (initializer) {
|
|
@@ -11277,7 +12081,7 @@ function expressionLooksLikeBrowserGlobalNumberHelper(expression, sourceFile, na
|
|
|
11277
12081
|
}
|
|
11278
12082
|
function expressionLooksLikeBrowserGlobalObjectHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11279
12083
|
if (!expression) return false;
|
|
11280
|
-
if (
|
|
12084
|
+
if (ts6.isIdentifier(expression) && expression.text === "Object") {
|
|
11281
12085
|
return true;
|
|
11282
12086
|
}
|
|
11283
12087
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "Object") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11297,7 +12101,7 @@ function expressionLooksLikeBrowserGlobalObjectHelper(expression, sourceFile, na
|
|
|
11297
12101
|
)) {
|
|
11298
12102
|
return true;
|
|
11299
12103
|
}
|
|
11300
|
-
if (
|
|
12104
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11301
12105
|
return expressionLooksLikeBrowserGlobalObjectHelper(
|
|
11302
12106
|
expression.expression,
|
|
11303
12107
|
sourceFile,
|
|
@@ -11306,7 +12110,7 @@ function expressionLooksLikeBrowserGlobalObjectHelper(expression, sourceFile, na
|
|
|
11306
12110
|
seenIdentifiers
|
|
11307
12111
|
);
|
|
11308
12112
|
}
|
|
11309
|
-
if (
|
|
12113
|
+
if (ts6.isIdentifier(expression)) {
|
|
11310
12114
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11311
12115
|
const initializer = namedExpressions.get(expression.text);
|
|
11312
12116
|
if (initializer) {
|
|
@@ -11335,7 +12139,7 @@ function expressionLooksLikeBrowserGlobalObjectHelper(expression, sourceFile, na
|
|
|
11335
12139
|
}
|
|
11336
12140
|
function expressionLooksLikeBrowserGlobalStringHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11337
12141
|
if (!expression) return false;
|
|
11338
|
-
if (
|
|
12142
|
+
if (ts6.isIdentifier(expression) && expression.text === "String") {
|
|
11339
12143
|
return true;
|
|
11340
12144
|
}
|
|
11341
12145
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "String") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11355,7 +12159,7 @@ function expressionLooksLikeBrowserGlobalStringHelper(expression, sourceFile, na
|
|
|
11355
12159
|
)) {
|
|
11356
12160
|
return true;
|
|
11357
12161
|
}
|
|
11358
|
-
if (
|
|
12162
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11359
12163
|
return expressionLooksLikeBrowserGlobalStringHelper(
|
|
11360
12164
|
expression.expression,
|
|
11361
12165
|
sourceFile,
|
|
@@ -11364,7 +12168,7 @@ function expressionLooksLikeBrowserGlobalStringHelper(expression, sourceFile, na
|
|
|
11364
12168
|
seenIdentifiers
|
|
11365
12169
|
);
|
|
11366
12170
|
}
|
|
11367
|
-
if (
|
|
12171
|
+
if (ts6.isIdentifier(expression)) {
|
|
11368
12172
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11369
12173
|
const initializer = namedExpressions.get(expression.text);
|
|
11370
12174
|
if (initializer) {
|
|
@@ -11393,7 +12197,7 @@ function expressionLooksLikeBrowserGlobalStringHelper(expression, sourceFile, na
|
|
|
11393
12197
|
}
|
|
11394
12198
|
function expressionLooksLikeBrowserGlobalBase64Helper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11395
12199
|
if (!expression) return false;
|
|
11396
|
-
if (
|
|
12200
|
+
if (ts6.isIdentifier(expression) && ["atob", "btoa"].includes(expression.text)) {
|
|
11397
12201
|
return true;
|
|
11398
12202
|
}
|
|
11399
12203
|
if (isMemberAccessExpression(expression) && isMemberAccessNamed(expression, "atob", "btoa") && expressionLooksLikeWindowObjectSource(
|
|
@@ -11413,7 +12217,7 @@ function expressionLooksLikeBrowserGlobalBase64Helper(expression, sourceFile, na
|
|
|
11413
12217
|
)) {
|
|
11414
12218
|
return true;
|
|
11415
12219
|
}
|
|
11416
|
-
if (
|
|
12220
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11417
12221
|
return expressionLooksLikeBrowserGlobalBase64Helper(
|
|
11418
12222
|
expression.expression,
|
|
11419
12223
|
sourceFile,
|
|
@@ -11422,7 +12226,7 @@ function expressionLooksLikeBrowserGlobalBase64Helper(expression, sourceFile, na
|
|
|
11422
12226
|
seenIdentifiers
|
|
11423
12227
|
);
|
|
11424
12228
|
}
|
|
11425
|
-
if (
|
|
12229
|
+
if (ts6.isIdentifier(expression)) {
|
|
11426
12230
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11427
12231
|
const initializer = namedExpressions.get(expression.text);
|
|
11428
12232
|
if (initializer) {
|
|
@@ -11451,7 +12255,7 @@ function expressionLooksLikeBrowserGlobalBase64Helper(expression, sourceFile, na
|
|
|
11451
12255
|
}
|
|
11452
12256
|
function expressionLooksLikeBrowserGlobalUriCodecHelper(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11453
12257
|
if (!expression) return false;
|
|
11454
|
-
if (
|
|
12258
|
+
if (ts6.isIdentifier(expression) && [
|
|
11455
12259
|
"decodeURI",
|
|
11456
12260
|
"decodeURIComponent",
|
|
11457
12261
|
"encodeURI",
|
|
@@ -11486,7 +12290,7 @@ function expressionLooksLikeBrowserGlobalUriCodecHelper(expression, sourceFile,
|
|
|
11486
12290
|
)) {
|
|
11487
12291
|
return true;
|
|
11488
12292
|
}
|
|
11489
|
-
if (
|
|
12293
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11490
12294
|
return expressionLooksLikeBrowserGlobalUriCodecHelper(
|
|
11491
12295
|
expression.expression,
|
|
11492
12296
|
sourceFile,
|
|
@@ -11495,7 +12299,7 @@ function expressionLooksLikeBrowserGlobalUriCodecHelper(expression, sourceFile,
|
|
|
11495
12299
|
seenIdentifiers
|
|
11496
12300
|
);
|
|
11497
12301
|
}
|
|
11498
|
-
if (
|
|
12302
|
+
if (ts6.isIdentifier(expression)) {
|
|
11499
12303
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11500
12304
|
const initializer = namedExpressions.get(expression.text);
|
|
11501
12305
|
if (initializer) {
|
|
@@ -11534,7 +12338,7 @@ function expressionLooksLikeLocationUrlSource(expression, sourceFile, namedExpre
|
|
|
11534
12338
|
if (LOCATION_URL_SOURCE_REGEX.test(expression.getText(sourceFile))) {
|
|
11535
12339
|
return true;
|
|
11536
12340
|
}
|
|
11537
|
-
if (
|
|
12341
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11538
12342
|
return expressionLooksLikeLocationUrlSource(
|
|
11539
12343
|
expression.expression,
|
|
11540
12344
|
sourceFile,
|
|
@@ -11543,7 +12347,7 @@ function expressionLooksLikeLocationUrlSource(expression, sourceFile, namedExpre
|
|
|
11543
12347
|
seenIdentifiers
|
|
11544
12348
|
);
|
|
11545
12349
|
}
|
|
11546
|
-
if (
|
|
12350
|
+
if (ts6.isNewExpression(expression) && ts6.isIdentifier(expression.expression) && expression.expression.text === "URL") {
|
|
11547
12351
|
return expressionLooksLikeLocationUrlInput(
|
|
11548
12352
|
expression.arguments?.[0],
|
|
11549
12353
|
sourceFile,
|
|
@@ -11552,7 +12356,7 @@ function expressionLooksLikeLocationUrlSource(expression, sourceFile, namedExpre
|
|
|
11552
12356
|
seenIdentifiers
|
|
11553
12357
|
);
|
|
11554
12358
|
}
|
|
11555
|
-
if (
|
|
12359
|
+
if (ts6.isIdentifier(expression)) {
|
|
11556
12360
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11557
12361
|
const initializer = namedExpressions.get(expression.text);
|
|
11558
12362
|
if (!initializer) return false;
|
|
@@ -11574,7 +12378,7 @@ function expressionLooksLikeLocationUrlInput(expression, sourceFile, namedExpres
|
|
|
11574
12378
|
if (LOCATION_URL_INPUT_REGEX.test(expression.getText(sourceFile))) {
|
|
11575
12379
|
return true;
|
|
11576
12380
|
}
|
|
11577
|
-
if (
|
|
12381
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11578
12382
|
return expressionLooksLikeLocationUrlInput(
|
|
11579
12383
|
expression.expression,
|
|
11580
12384
|
sourceFile,
|
|
@@ -11592,7 +12396,7 @@ function expressionLooksLikeLocationUrlInput(expression, sourceFile, namedExpres
|
|
|
11592
12396
|
)) {
|
|
11593
12397
|
return true;
|
|
11594
12398
|
}
|
|
11595
|
-
if (isCallLikeExpression(expression) &&
|
|
12399
|
+
if (isCallLikeExpression(expression) && ts6.isIdentifier(expression.expression) && expression.expression.text === "String" && expression.arguments.length > 0 && (expressionLooksLikeLocationObjectSource(
|
|
11596
12400
|
expression.arguments[0],
|
|
11597
12401
|
sourceFile,
|
|
11598
12402
|
namedExpressions,
|
|
@@ -11645,7 +12449,7 @@ function expressionLooksLikeLocationUrlInput(expression, sourceFile, namedExpres
|
|
|
11645
12449
|
)) {
|
|
11646
12450
|
return true;
|
|
11647
12451
|
}
|
|
11648
|
-
if (
|
|
12452
|
+
if (ts6.isIdentifier(expression)) {
|
|
11649
12453
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11650
12454
|
const initializer = namedExpressions.get(expression.text);
|
|
11651
12455
|
if (initializer) {
|
|
@@ -11692,7 +12496,7 @@ function expressionLooksLikeRequestObjectSource(expression, sourceFile, namedExp
|
|
|
11692
12496
|
if (REQUEST_OBJECT_SOURCE_REGEX.test(expression.getText(sourceFile))) {
|
|
11693
12497
|
return true;
|
|
11694
12498
|
}
|
|
11695
|
-
if (
|
|
12499
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11696
12500
|
return expressionLooksLikeRequestObjectSource(
|
|
11697
12501
|
expression.expression,
|
|
11698
12502
|
sourceFile,
|
|
@@ -11700,7 +12504,7 @@ function expressionLooksLikeRequestObjectSource(expression, sourceFile, namedExp
|
|
|
11700
12504
|
seenIdentifiers
|
|
11701
12505
|
);
|
|
11702
12506
|
}
|
|
11703
|
-
if (
|
|
12507
|
+
if (ts6.isIdentifier(expression)) {
|
|
11704
12508
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11705
12509
|
const initializer = namedExpressions.get(expression.text);
|
|
11706
12510
|
if (!initializer) return false;
|
|
@@ -11721,7 +12525,7 @@ function expressionLooksLikeNextUrlSource(expression, sourceFile, namedExpressio
|
|
|
11721
12525
|
if (NEXT_URL_SOURCE_REGEX.test(expression.getText(sourceFile))) {
|
|
11722
12526
|
return true;
|
|
11723
12527
|
}
|
|
11724
|
-
if (
|
|
12528
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11725
12529
|
return expressionLooksLikeNextUrlSource(
|
|
11726
12530
|
expression.expression,
|
|
11727
12531
|
sourceFile,
|
|
@@ -11747,7 +12551,7 @@ function expressionLooksLikeNextUrlSource(expression, sourceFile, namedExpressio
|
|
|
11747
12551
|
seenIdentifiers
|
|
11748
12552
|
);
|
|
11749
12553
|
}
|
|
11750
|
-
if (
|
|
12554
|
+
if (ts6.isIdentifier(expression)) {
|
|
11751
12555
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11752
12556
|
const initializer = namedExpressions.get(expression.text);
|
|
11753
12557
|
if (initializer) {
|
|
@@ -11781,7 +12585,7 @@ function expressionLooksLikeOpenRedirectSearchParamsCarrier(expression, sourceFi
|
|
|
11781
12585
|
if (/\b(?:searchParams|(?:request|req)\.nextUrl\.searchParams|url\.searchParams)\b/i.test(text)) {
|
|
11782
12586
|
return true;
|
|
11783
12587
|
}
|
|
11784
|
-
if (
|
|
12588
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11785
12589
|
return expressionLooksLikeOpenRedirectSearchParamsCarrier(
|
|
11786
12590
|
expression.expression,
|
|
11787
12591
|
sourceFile,
|
|
@@ -11790,7 +12594,7 @@ function expressionLooksLikeOpenRedirectSearchParamsCarrier(expression, sourceFi
|
|
|
11790
12594
|
seenIdentifiers
|
|
11791
12595
|
);
|
|
11792
12596
|
}
|
|
11793
|
-
if (
|
|
12597
|
+
if (ts6.isNewExpression(expression) && ts6.isIdentifier(expression.expression) && expression.expression.text === "URLSearchParams") {
|
|
11794
12598
|
return expressionLooksLikeLocationQuerySource(
|
|
11795
12599
|
expression.arguments?.[0],
|
|
11796
12600
|
sourceFile,
|
|
@@ -11799,7 +12603,7 @@ function expressionLooksLikeOpenRedirectSearchParamsCarrier(expression, sourceFi
|
|
|
11799
12603
|
seenIdentifiers
|
|
11800
12604
|
);
|
|
11801
12605
|
}
|
|
11802
|
-
if (isCallLikeExpression(expression) && (
|
|
12606
|
+
if (isCallLikeExpression(expression) && (ts6.isIdentifier(expression.expression) && expression.expression.text === "useSearchParams" || isMemberAccessExpression(expression.expression) && isMemberAccessNamed(expression.expression, "useSearchParams"))) {
|
|
11803
12607
|
return true;
|
|
11804
12608
|
}
|
|
11805
12609
|
if (isPropertyLikeAccessExpression(expression) && isPropertyNamed(expression.name, "searchParams")) {
|
|
@@ -11817,7 +12621,7 @@ function expressionLooksLikeOpenRedirectSearchParamsCarrier(expression, sourceFi
|
|
|
11817
12621
|
seenIdentifiers
|
|
11818
12622
|
);
|
|
11819
12623
|
}
|
|
11820
|
-
if (
|
|
12624
|
+
if (ts6.isIdentifier(expression)) {
|
|
11821
12625
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11822
12626
|
const initializer = namedExpressions.get(expression.text);
|
|
11823
12627
|
if (initializer) {
|
|
@@ -11857,7 +12661,7 @@ function expressionLooksLikeLocationAssignmentTarget(expression, sourceFile, nam
|
|
|
11857
12661
|
if (isLocationAssignmentTarget(expression)) {
|
|
11858
12662
|
return true;
|
|
11859
12663
|
}
|
|
11860
|
-
if (
|
|
12664
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11861
12665
|
return expressionLooksLikeLocationAssignmentTarget(
|
|
11862
12666
|
expression.expression,
|
|
11863
12667
|
sourceFile,
|
|
@@ -11879,7 +12683,7 @@ function expressionLooksLikeLocationAssignmentTarget(expression, sourceFile, nam
|
|
|
11879
12683
|
}
|
|
11880
12684
|
function expressionLooksLikeLocationMutationCall(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11881
12685
|
if (!expression) return false;
|
|
11882
|
-
if (
|
|
12686
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11883
12687
|
return expressionLooksLikeLocationMutationCall(
|
|
11884
12688
|
expression.expression,
|
|
11885
12689
|
sourceFile,
|
|
@@ -11906,7 +12710,7 @@ function expressionLooksLikeLocationMutationCall(expression, sourceFile, namedEx
|
|
|
11906
12710
|
seenIdentifiers
|
|
11907
12711
|
);
|
|
11908
12712
|
}
|
|
11909
|
-
if (
|
|
12713
|
+
if (ts6.isIdentifier(expression)) {
|
|
11910
12714
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11911
12715
|
const initializer = namedExpressions.get(expression.text);
|
|
11912
12716
|
if (initializer) {
|
|
@@ -11945,7 +12749,7 @@ function expressionLooksLikeLocationMutationCall(expression, sourceFile, namedEx
|
|
|
11945
12749
|
}
|
|
11946
12750
|
function expressionLooksLikeWindowOpenCall(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
11947
12751
|
if (!expression) return false;
|
|
11948
|
-
if (
|
|
12752
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
11949
12753
|
return expressionLooksLikeWindowOpenCall(
|
|
11950
12754
|
expression.expression,
|
|
11951
12755
|
sourceFile,
|
|
@@ -11963,10 +12767,10 @@ function expressionLooksLikeWindowOpenCall(expression, sourceFile, namedExpressi
|
|
|
11963
12767
|
seenIdentifiers
|
|
11964
12768
|
);
|
|
11965
12769
|
}
|
|
11966
|
-
if (
|
|
12770
|
+
if (ts6.isIdentifier(expression) && expression.text === "open") {
|
|
11967
12771
|
return true;
|
|
11968
12772
|
}
|
|
11969
|
-
if (
|
|
12773
|
+
if (ts6.isIdentifier(expression)) {
|
|
11970
12774
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
11971
12775
|
const initializer = namedExpressions.get(expression.text);
|
|
11972
12776
|
if (initializer) {
|
|
@@ -12002,7 +12806,7 @@ function expressionLooksLikeWindowOpenCall(expression, sourceFile, namedExpressi
|
|
|
12002
12806
|
}
|
|
12003
12807
|
function expressionLooksLikeHistoryMutationCall(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
12004
12808
|
if (!expression) return false;
|
|
12005
|
-
if (
|
|
12809
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
12006
12810
|
return expressionLooksLikeHistoryMutationCall(
|
|
12007
12811
|
expression.expression,
|
|
12008
12812
|
sourceFile,
|
|
@@ -12029,7 +12833,7 @@ function expressionLooksLikeHistoryMutationCall(expression, sourceFile, namedExp
|
|
|
12029
12833
|
seenIdentifiers
|
|
12030
12834
|
);
|
|
12031
12835
|
}
|
|
12032
|
-
if (
|
|
12836
|
+
if (ts6.isIdentifier(expression)) {
|
|
12033
12837
|
if (seenIdentifiers.has(expression.text)) return false;
|
|
12034
12838
|
const initializer = namedExpressions.get(expression.text);
|
|
12035
12839
|
if (initializer) {
|
|
@@ -12068,7 +12872,7 @@ function expressionLooksLikeHistoryMutationCall(expression, sourceFile, namedExp
|
|
|
12068
12872
|
}
|
|
12069
12873
|
function expressionLooksLikeRouteTransitionCall(expression, sourceFile, namedExpressions, namedPropertyAliases, seenIdentifiers) {
|
|
12070
12874
|
if (!expression) return false;
|
|
12071
|
-
if (
|
|
12875
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
12072
12876
|
return expressionLooksLikeRouteTransitionCall(
|
|
12073
12877
|
expression.expression,
|
|
12074
12878
|
sourceFile,
|
|
@@ -12095,7 +12899,7 @@ function expressionLooksLikeRouteTransitionCall(expression, sourceFile, namedExp
|
|
|
12095
12899
|
seenIdentifiers
|
|
12096
12900
|
);
|
|
12097
12901
|
}
|
|
12098
|
-
if (
|
|
12902
|
+
if (ts6.isIdentifier(expression)) {
|
|
12099
12903
|
if (["redirect", "navigate"].includes(expression.text)) {
|
|
12100
12904
|
return true;
|
|
12101
12905
|
}
|
|
@@ -12141,7 +12945,7 @@ function expressionLooksLikeRouteTransitionCall(expression, sourceFile, namedExp
|
|
|
12141
12945
|
);
|
|
12142
12946
|
}
|
|
12143
12947
|
function getRouteTransitionTargetExpression(node, sourceFile, namedExpressions, namedPropertyAliases) {
|
|
12144
|
-
if (isMemberAccessExpression(node.expression) &&
|
|
12948
|
+
if (isMemberAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "Reflect" && isMemberAccessNamed(node.expression, "apply") && expressionLooksLikeRouteTransitionCall(
|
|
12145
12949
|
node.arguments[0],
|
|
12146
12950
|
sourceFile,
|
|
12147
12951
|
namedExpressions,
|
|
@@ -12186,7 +12990,7 @@ function getRouteTransitionTargetExpression(node, sourceFile, namedExpressions,
|
|
|
12186
12990
|
)) {
|
|
12187
12991
|
return getAliasedApplyArgumentExpression(node.arguments[1], 2, namedExpressions, /* @__PURE__ */ new Set());
|
|
12188
12992
|
}
|
|
12189
|
-
if (isMemberAccessExpression(node.expression) &&
|
|
12993
|
+
if (isMemberAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "Reflect" && isMemberAccessNamed(node.expression, "apply") && expressionLooksLikeHistoryMutationCall(
|
|
12190
12994
|
node.arguments[0],
|
|
12191
12995
|
sourceFile,
|
|
12192
12996
|
namedExpressions,
|
|
@@ -12217,7 +13021,7 @@ function getRouteTransitionTargetExpression(node, sourceFile, namedExpressions,
|
|
|
12217
13021
|
}
|
|
12218
13022
|
function getAliasedApplyArgumentExpression(expression, index, namedExpressions, seenIdentifiers) {
|
|
12219
13023
|
if (!expression) return void 0;
|
|
12220
|
-
if (
|
|
13024
|
+
if (ts6.isParenthesizedExpression(expression) || ts6.isAsExpression(expression) || ts6.isTypeAssertionExpression(expression) || ts6.isNonNullExpression(expression)) {
|
|
12221
13025
|
return getAliasedApplyArgumentExpression(
|
|
12222
13026
|
expression.expression,
|
|
12223
13027
|
index,
|
|
@@ -12225,7 +13029,7 @@ function getAliasedApplyArgumentExpression(expression, index, namedExpressions,
|
|
|
12225
13029
|
seenIdentifiers
|
|
12226
13030
|
);
|
|
12227
13031
|
}
|
|
12228
|
-
if (
|
|
13032
|
+
if (ts6.isIdentifier(expression)) {
|
|
12229
13033
|
if (seenIdentifiers.has(expression.text)) return void 0;
|
|
12230
13034
|
const initializer = namedExpressions.get(expression.text);
|
|
12231
13035
|
if (!initializer) return void 0;
|
|
@@ -12239,12 +13043,12 @@ function getAliasedApplyArgumentExpression(expression, index, namedExpressions,
|
|
|
12239
13043
|
seenIdentifiers.delete(expression.text);
|
|
12240
13044
|
return result;
|
|
12241
13045
|
}
|
|
12242
|
-
if (!
|
|
13046
|
+
if (!ts6.isArrayLiteralExpression(expression)) return void 0;
|
|
12243
13047
|
const argument = expression.elements[index];
|
|
12244
|
-
return
|
|
13048
|
+
return ts6.isExpression(argument) ? argument : void 0;
|
|
12245
13049
|
}
|
|
12246
13050
|
function getLocationMutationTargetExpression(node, sourceFile, namedExpressions, namedPropertyAliases) {
|
|
12247
|
-
if (isMemberAccessExpression(node.expression) &&
|
|
13051
|
+
if (isMemberAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "Reflect" && isMemberAccessNamed(node.expression, "apply") && expressionLooksLikeLocationMutationCall(
|
|
12248
13052
|
node.arguments[0],
|
|
12249
13053
|
sourceFile,
|
|
12250
13054
|
namedExpressions,
|
|
@@ -12283,7 +13087,7 @@ function getLocationMutationTargetExpression(node, sourceFile, namedExpressions,
|
|
|
12283
13087
|
return void 0;
|
|
12284
13088
|
}
|
|
12285
13089
|
function getWindowOpenTargetExpression(node, sourceFile, namedExpressions, namedPropertyAliases) {
|
|
12286
|
-
if (isMemberAccessExpression(node.expression) &&
|
|
13090
|
+
if (isMemberAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "Reflect" && isMemberAccessNamed(node.expression, "apply") && expressionLooksLikeWindowOpenCall(
|
|
12287
13091
|
node.arguments[0],
|
|
12288
13092
|
sourceFile,
|
|
12289
13093
|
namedExpressions,
|
|
@@ -12422,28 +13226,28 @@ var DYNAMIC_GEOMETRY_STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
|
12422
13226
|
"y"
|
|
12423
13227
|
]);
|
|
12424
13228
|
function getJsxAttributeExpression(initializer) {
|
|
12425
|
-
if (!initializer || !
|
|
13229
|
+
if (!initializer || !ts6.isJsxExpression(initializer)) return null;
|
|
12426
13230
|
return initializer.expression ?? null;
|
|
12427
13231
|
}
|
|
12428
13232
|
function getStylePropertyName(name) {
|
|
12429
|
-
if (
|
|
13233
|
+
if (ts6.isIdentifier(name) || ts6.isStringLiteral(name) || ts6.isNumericLiteral(name)) {
|
|
12430
13234
|
return name.text;
|
|
12431
13235
|
}
|
|
12432
|
-
if (
|
|
13236
|
+
if (ts6.isComputedPropertyName(name)) {
|
|
12433
13237
|
return getExpressionLiteralValue(name.expression);
|
|
12434
13238
|
}
|
|
12435
13239
|
return null;
|
|
12436
13240
|
}
|
|
12437
13241
|
function unwrapStyleExpression(expression) {
|
|
12438
13242
|
let current = expression;
|
|
12439
|
-
while (
|
|
13243
|
+
while (ts6.isParenthesizedExpression(current) || ts6.isAsExpression(current) || ts6.isTypeAssertionExpression(current) || ts6.isNonNullExpression(current) || ts6.isSatisfiesExpression(current)) {
|
|
12440
13244
|
current = current.expression;
|
|
12441
13245
|
}
|
|
12442
13246
|
return current;
|
|
12443
13247
|
}
|
|
12444
13248
|
function isDynamicStyleValue(expression) {
|
|
12445
13249
|
const unwrapped = unwrapStyleExpression(expression);
|
|
12446
|
-
if (
|
|
13250
|
+
if (ts6.isStringLiteral(unwrapped) || ts6.isNoSubstitutionTemplateLiteral(unwrapped) || ts6.isNumericLiteral(unwrapped) || unwrapped.kind === ts6.SyntaxKind.TrueKeyword || unwrapped.kind === ts6.SyntaxKind.FalseKeyword || unwrapped.kind === ts6.SyntaxKind.NullKeyword) {
|
|
12447
13251
|
return false;
|
|
12448
13252
|
}
|
|
12449
13253
|
return true;
|
|
@@ -12452,7 +13256,7 @@ function isAllowedInlineStyleObject(objectLiteral) {
|
|
|
12452
13256
|
let sawGeometryProperty = false;
|
|
12453
13257
|
let sawDynamicGeometryValue = false;
|
|
12454
13258
|
for (const property of objectLiteral.properties) {
|
|
12455
|
-
if (!
|
|
13259
|
+
if (!ts6.isPropertyAssignment(property)) return false;
|
|
12456
13260
|
const propertyName2 = getStylePropertyName(property.name);
|
|
12457
13261
|
if (!propertyName2) return false;
|
|
12458
13262
|
if (propertyName2.startsWith("--d-")) {
|
|
@@ -12481,10 +13285,10 @@ function isAllowedInlineStyleAttribute(attribute, sourceFile, namedExpressions,
|
|
|
12481
13285
|
return resolved ? isAllowedInlineStyleObject(resolved.objectLiteral) : false;
|
|
12482
13286
|
}
|
|
12483
13287
|
function analyzeAstSignals(filePath, code) {
|
|
12484
|
-
const sourceFile =
|
|
13288
|
+
const sourceFile = ts6.createSourceFile(
|
|
12485
13289
|
filePath,
|
|
12486
13290
|
code,
|
|
12487
|
-
|
|
13291
|
+
ts6.ScriptTarget.Latest,
|
|
12488
13292
|
true,
|
|
12489
13293
|
getScriptKind(filePath)
|
|
12490
13294
|
);
|
|
@@ -12566,10 +13370,11 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12566
13370
|
const namedExpressionInitializers = collectNamedExpressionInitializers(sourceFile);
|
|
12567
13371
|
const namedPropertyAliases = collectNamedPropertyAliases(sourceFile);
|
|
12568
13372
|
const labelForIds = collectLabelForIds(sourceFile);
|
|
13373
|
+
const elementIds = collectElementIds(sourceFile);
|
|
12569
13374
|
let navigationLandmarkCount = 0;
|
|
12570
13375
|
let unlabeledNavigationLandmarkCount = 0;
|
|
12571
13376
|
const walk = (node) => {
|
|
12572
|
-
if (
|
|
13377
|
+
if (ts6.isJsxAttribute(node)) {
|
|
12573
13378
|
if (isPropertyNamed(node.name, "style") && node.initializer) {
|
|
12574
13379
|
if (!isAllowedInlineStyleAttribute(
|
|
12575
13380
|
node,
|
|
@@ -12583,7 +13388,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12583
13388
|
if (isPropertyNamed(node.name, "dangerouslySetInnerHTML") && !isSafeJsonLdDangerouslySetInnerHtml(node)) {
|
|
12584
13389
|
signals.dangerousHtmlCount += 1;
|
|
12585
13390
|
}
|
|
12586
|
-
if (isPropertyNamed(node.name, "href", "to") && node.initializer &&
|
|
13391
|
+
if (isPropertyNamed(node.name, "href", "to") && node.initializer && ts6.isJsxExpression(node.initializer) && expressionContainsOpenRedirectSource(
|
|
12587
13392
|
node.initializer.expression,
|
|
12588
13393
|
sourceFile,
|
|
12589
13394
|
namedExpressionInitializers,
|
|
@@ -12601,10 +13406,10 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12601
13406
|
signals.authProviderNonceMissingCount += 1;
|
|
12602
13407
|
}
|
|
12603
13408
|
}
|
|
12604
|
-
if (
|
|
13409
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && ts6.isPropertyAccessExpression(node.left) && isPropertyNamed(node.left.name, "innerHTML", "outerHTML")) {
|
|
12605
13410
|
signals.rawHtmlInjectionCount += 1;
|
|
12606
13411
|
}
|
|
12607
|
-
if (
|
|
13412
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && expressionLooksLikeLocationAssignmentTarget(
|
|
12608
13413
|
node.left,
|
|
12609
13414
|
sourceFile,
|
|
12610
13415
|
namedExpressionInitializers,
|
|
@@ -12618,7 +13423,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12618
13423
|
)) {
|
|
12619
13424
|
signals.authOpenRedirectSignalCount += 1;
|
|
12620
13425
|
}
|
|
12621
|
-
if (
|
|
13426
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && expressionLooksLikeLocationAssignmentTarget(
|
|
12622
13427
|
node.left,
|
|
12623
13428
|
sourceFile,
|
|
12624
13429
|
namedExpressionInitializers,
|
|
@@ -12627,7 +13432,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12627
13432
|
) && isInsecureTransportUrl(getExpressionLiteralValue(node.right))) {
|
|
12628
13433
|
signals.insecureTransportEndpointCount += 1;
|
|
12629
13434
|
}
|
|
12630
|
-
if (
|
|
13435
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && expressionLooksLikeLocationAssignmentTarget(
|
|
12631
13436
|
node.left,
|
|
12632
13437
|
sourceFile,
|
|
12633
13438
|
namedExpressionInitializers,
|
|
@@ -12645,7 +13450,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12645
13450
|
signals.authProviderNonceMissingCount += 1;
|
|
12646
13451
|
}
|
|
12647
13452
|
}
|
|
12648
|
-
if (
|
|
13453
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && expressionLooksLikeLocationAssignmentTarget(
|
|
12649
13454
|
node.left,
|
|
12650
13455
|
sourceFile,
|
|
12651
13456
|
namedExpressionInitializers,
|
|
@@ -12659,36 +13464,36 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12659
13464
|
)) {
|
|
12660
13465
|
signals.authOpenRedirectSignalCount += 1;
|
|
12661
13466
|
}
|
|
12662
|
-
if (
|
|
13467
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && ts6.isPropertyAccessExpression(node.left) && isPropertyNamed(node.left.name, "onmessage")) {
|
|
12663
13468
|
const handler = resolveFunctionLikeHandler(node.right, namedFunctionDeclarations);
|
|
12664
13469
|
if (handler && !functionLikeReferencesOrigin(handler)) {
|
|
12665
13470
|
signals.messageListenerWithoutOriginCheckCount += 1;
|
|
12666
13471
|
}
|
|
12667
13472
|
}
|
|
12668
|
-
if (
|
|
13473
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && ts6.isPropertyAccessExpression(node.left) && isBrowserStorageObject(node.left.expression) && /(?:token|auth|jwt|session)/i.test(node.left.name.text)) {
|
|
12669
13474
|
signals.authStorageWriteCount += 1;
|
|
12670
13475
|
}
|
|
12671
|
-
if (
|
|
13476
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && ts6.isElementAccessExpression(node.left) && isBrowserStorageObject(node.left.expression) && isAuthStorageKeyLiteral(node.left.argumentExpression)) {
|
|
12672
13477
|
signals.authStorageWriteCount += 1;
|
|
12673
13478
|
}
|
|
12674
|
-
if (
|
|
13479
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && isCookiePropertyAccess(node.left) && hasAuthCredentialText(node.right, sourceFile)) {
|
|
12675
13480
|
signals.authCookieWriteCount += 1;
|
|
12676
13481
|
}
|
|
12677
|
-
if (
|
|
13482
|
+
if (ts6.isBinaryExpression(node) && node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && isAuthorizationHeaderAccess(node.left)) {
|
|
12678
13483
|
if (isHeaderClearValue(node.right)) {
|
|
12679
13484
|
signals.authHeaderClearCount += 1;
|
|
12680
13485
|
} else {
|
|
12681
13486
|
signals.authHeaderWriteCount += 1;
|
|
12682
13487
|
}
|
|
12683
13488
|
}
|
|
12684
|
-
if (
|
|
13489
|
+
if (ts6.isPropertyAssignment(node) && isAuthorizationHeaderName(node.name)) {
|
|
12685
13490
|
if (isHeaderClearValue(node.initializer)) {
|
|
12686
13491
|
signals.authHeaderClearCount += 1;
|
|
12687
13492
|
} else {
|
|
12688
13493
|
signals.authHeaderWriteCount += 1;
|
|
12689
13494
|
}
|
|
12690
13495
|
}
|
|
12691
|
-
if (
|
|
13496
|
+
if (ts6.isDeleteExpression(node) && isAuthorizationHeaderAccess(node.expression)) {
|
|
12692
13497
|
signals.authHeaderClearCount += 1;
|
|
12693
13498
|
}
|
|
12694
13499
|
if (isCallLikeExpression(node)) {
|
|
@@ -12719,10 +13524,10 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12719
13524
|
namedPropertyAliases
|
|
12720
13525
|
);
|
|
12721
13526
|
const windowOpenTargetLiteral = getExpressionLiteralValue(windowOpenTargetExpression);
|
|
12722
|
-
if (
|
|
13527
|
+
if (ts6.isIdentifier(node.expression) && node.expression.text === "eval") {
|
|
12723
13528
|
signals.dynamicEvalCount += 1;
|
|
12724
13529
|
}
|
|
12725
|
-
if ((
|
|
13530
|
+
if ((ts6.isIdentifier(node.expression) && ["setTimeout", "setInterval"].includes(node.expression.text) || ts6.isPropertyAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "window" && isPropertyNamed(node.expression.name, "setTimeout", "setInterval")) && typeof firstArgumentLiteral === "string") {
|
|
12726
13531
|
signals.dynamicEvalCount += 1;
|
|
12727
13532
|
}
|
|
12728
13533
|
if ((isFetchLikeCall(node) || isAxiosLikeCall(node)) && isInsecureTransportUrl(firstArgumentLiteral)) {
|
|
@@ -12804,7 +13609,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12804
13609
|
signals.authProviderNonceMissingCount += 1;
|
|
12805
13610
|
}
|
|
12806
13611
|
}
|
|
12807
|
-
if (
|
|
13612
|
+
if (ts6.isPropertyAccessExpression(node.expression) && isPropertyNamed(node.expression.name, "postMessage") && secondArgumentLiteral === "*") {
|
|
12808
13613
|
signals.wildcardPostMessageCount += 1;
|
|
12809
13614
|
}
|
|
12810
13615
|
if (isAddEventListenerCall(node) && firstArgumentLiteral === "message") {
|
|
@@ -12813,7 +13618,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12813
13618
|
signals.messageListenerWithoutOriginCheckCount += 1;
|
|
12814
13619
|
}
|
|
12815
13620
|
}
|
|
12816
|
-
if (
|
|
13621
|
+
if (ts6.isPropertyAccessExpression(node.expression) && isPropertyNamed(node.expression.name, "setHeader", "append", "set") && isSetCookieHeaderName(node.arguments[0])) {
|
|
12817
13622
|
const cookieStrings = collectCookieHeaderStrings(node.arguments[1]);
|
|
12818
13623
|
const authCookieStrings = cookieStrings.filter(cookieHeaderStringLooksAuthLike);
|
|
12819
13624
|
if (authCookieStrings.length > 0) {
|
|
@@ -12831,13 +13636,13 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12831
13636
|
}
|
|
12832
13637
|
}
|
|
12833
13638
|
}
|
|
12834
|
-
if ((
|
|
13639
|
+
if ((ts6.isIdentifier(node.expression) && node.expression.text === "open" || ts6.isPropertyAccessExpression(node.expression) && ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "window" && isPropertyNamed(node.expression.name, "open")) && secondArgumentLiteral === "_blank") {
|
|
12835
13640
|
const featureLiteral = getExpressionLiteralValue(node.arguments[2])?.toLowerCase() ?? "";
|
|
12836
13641
|
if (!featureLiteral.includes("noopener") || !featureLiteral.includes("noreferrer")) {
|
|
12837
13642
|
signals.windowOpenWithoutNoopenerCount += 1;
|
|
12838
13643
|
}
|
|
12839
13644
|
}
|
|
12840
|
-
if (
|
|
13645
|
+
if (ts6.isPropertyAccessExpression(node.expression)) {
|
|
12841
13646
|
if (isPropertyNamed(node.expression.name, "insertAdjacentHTML")) {
|
|
12842
13647
|
signals.rawHtmlInjectionCount += 1;
|
|
12843
13648
|
}
|
|
@@ -12846,7 +13651,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12846
13651
|
}
|
|
12847
13652
|
if (isCookieMutationSetCall(node)) {
|
|
12848
13653
|
const firstArgument = node.arguments[0];
|
|
12849
|
-
const isObjectConfigCall =
|
|
13654
|
+
const isObjectConfigCall = ts6.isObjectLiteralExpression(firstArgument);
|
|
12850
13655
|
const isAuthCookieWrite = isObjectConfigCall ? objectLiteralLooksLikeAuthCookieConfig(firstArgument, sourceFile) : expressionLooksLikeAuthCookieName(firstArgument, sourceFile);
|
|
12851
13656
|
if (isAuthCookieWrite) {
|
|
12852
13657
|
signals.authCookieWriteCount += 1;
|
|
@@ -12866,7 +13671,7 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12866
13671
|
signals.authHeaderWriteCount += 1;
|
|
12867
13672
|
}
|
|
12868
13673
|
}
|
|
12869
|
-
if (
|
|
13674
|
+
if (ts6.isIdentifier(node.expression.expression) && node.expression.expression.text === "document" && isPropertyNamed(node.expression.name, "write")) {
|
|
12870
13675
|
signals.rawHtmlInjectionCount += 1;
|
|
12871
13676
|
}
|
|
12872
13677
|
if (isPropertyNamed(node.expression.name, "eval")) {
|
|
@@ -12874,16 +13679,16 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12874
13679
|
}
|
|
12875
13680
|
}
|
|
12876
13681
|
}
|
|
12877
|
-
if (
|
|
13682
|
+
if (ts6.isNewExpression(node) && isRealtimeTransportConstructor(node) && isInsecureTransportUrl(getExpressionLiteralValue(node.arguments?.[0]))) {
|
|
12878
13683
|
signals.insecureTransportEndpointCount += 1;
|
|
12879
13684
|
}
|
|
12880
|
-
if (
|
|
13685
|
+
if (ts6.isNewExpression(node) && ts6.isIdentifier(node.expression) && node.expression.text === "Function") {
|
|
12881
13686
|
signals.dynamicEvalCount += 1;
|
|
12882
13687
|
}
|
|
12883
|
-
if (
|
|
13688
|
+
if (ts6.isNewExpression(node) && ts6.isIdentifier(node.expression) && ["WebSocket", "EventSource"].includes(node.expression.text) && isInsecureTransportUrl(getExpressionLiteralValue(node.arguments?.[0]))) {
|
|
12884
13689
|
signals.insecureTransportEndpointCount += 1;
|
|
12885
13690
|
}
|
|
12886
|
-
if (
|
|
13691
|
+
if (ts6.isJsxSelfClosingElement(node)) {
|
|
12887
13692
|
const tagName = getJsxTagName(node);
|
|
12888
13693
|
if (hasMainLandmarkSignal(node.attributes, tagName)) {
|
|
12889
13694
|
signals.mainLandmarkCount += 1;
|
|
@@ -12972,11 +13777,11 @@ function analyzeAstSignals(filePath, code) {
|
|
|
12972
13777
|
signals.authInputWithoutNameCount += 1;
|
|
12973
13778
|
}
|
|
12974
13779
|
}
|
|
12975
|
-
if (!hasFormControlLabel(node, tagName, node.attributes, labelForIds, "")) {
|
|
13780
|
+
if (!hasFormControlLabel(node, tagName, node.attributes, labelForIds, elementIds, "")) {
|
|
12976
13781
|
signals.formControlWithoutLabelCount += 1;
|
|
12977
13782
|
}
|
|
12978
13783
|
}
|
|
12979
|
-
if (
|
|
13784
|
+
if (ts6.isJsxElement(node)) {
|
|
12980
13785
|
const tagName = getJsxTagName(node.openingElement);
|
|
12981
13786
|
const textContent = getJsxTextContent(node).replace(/\s+/g, " ").trim();
|
|
12982
13787
|
if (hasMainLandmarkSignal(node.openingElement.attributes, tagName)) {
|
|
@@ -13087,12 +13892,13 @@ function analyzeAstSignals(filePath, code) {
|
|
|
13087
13892
|
tagName,
|
|
13088
13893
|
node.openingElement.attributes,
|
|
13089
13894
|
labelForIds,
|
|
13895
|
+
elementIds,
|
|
13090
13896
|
textContent
|
|
13091
13897
|
)) {
|
|
13092
13898
|
signals.formControlWithoutLabelCount += 1;
|
|
13093
13899
|
}
|
|
13094
13900
|
}
|
|
13095
|
-
|
|
13901
|
+
ts6.forEachChild(node, walk);
|
|
13096
13902
|
};
|
|
13097
13903
|
walk(sourceFile);
|
|
13098
13904
|
signals.unlabeledNavigationLandmarkCount = navigationLandmarkCount > 1 ? unlabeledNavigationLandmarkCount : 0;
|
|
@@ -14846,11 +15652,11 @@ function critiqueSource({
|
|
|
14846
15652
|
};
|
|
14847
15653
|
}
|
|
14848
15654
|
function resolveProjectFilePath(projectRoot, filePath) {
|
|
14849
|
-
const root =
|
|
14850
|
-
const candidatePath =
|
|
14851
|
-
const resolvedPath =
|
|
14852
|
-
const relativePath =
|
|
14853
|
-
if (relativePath.startsWith("..") ||
|
|
15655
|
+
const root = existsSync6(projectRoot) ? realpathSync2.native(projectRoot) : resolve3(projectRoot);
|
|
15656
|
+
const candidatePath = isAbsolute4(filePath) ? resolve3(filePath) : resolve3(root, filePath);
|
|
15657
|
+
const resolvedPath = existsSync6(candidatePath) ? realpathSync2.native(candidatePath) : candidatePath;
|
|
15658
|
+
const relativePath = relative6(root, resolvedPath);
|
|
15659
|
+
if (relativePath.startsWith("..") || isAbsolute4(relativePath)) {
|
|
14854
15660
|
throw new Error(`Path escapes the project root: ${filePath}`);
|
|
14855
15661
|
}
|
|
14856
15662
|
return resolvedPath;
|
|
@@ -14858,7 +15664,7 @@ function resolveProjectFilePath(projectRoot, filePath) {
|
|
|
14858
15664
|
async function critiqueFile(filePath, projectRoot) {
|
|
14859
15665
|
const resolvedPath = resolveProjectFilePath(projectRoot, filePath);
|
|
14860
15666
|
const code = await readFile(resolvedPath, "utf-8");
|
|
14861
|
-
const treatmentsCss = readTextIfExists(
|
|
15667
|
+
const treatmentsCss = readTextIfExists(join6(projectRoot, "src", "styles", "treatments.css"));
|
|
14862
15668
|
const reviewPack = loadReviewPack(projectRoot);
|
|
14863
15669
|
const packManifest = loadPackManifest(projectRoot);
|
|
14864
15670
|
const adoptionMode = readProjectAdoptionMode(projectRoot);
|
|
@@ -14888,19 +15694,33 @@ export {
|
|
|
14888
15694
|
buildProjectHealthRepairPlan,
|
|
14889
15695
|
collectMissingPackManifestFiles,
|
|
14890
15696
|
collectProjectSourceFiles,
|
|
15697
|
+
collectSourceImports,
|
|
14891
15698
|
createContractAssertions,
|
|
14892
15699
|
createEvidenceBundle,
|
|
15700
|
+
createProjectSourceProgram,
|
|
15701
|
+
createSourceInventory,
|
|
14893
15702
|
createUnavailableScanReport,
|
|
14894
15703
|
critiqueFile,
|
|
14895
15704
|
critiqueSource,
|
|
14896
15705
|
deriveVerificationDiagnostic,
|
|
14897
15706
|
emptyRuntimeAudit,
|
|
14898
15707
|
extractRouteHintsFromEssence,
|
|
15708
|
+
extractSourceStringLiterals,
|
|
15709
|
+
getProjectSourceFile,
|
|
15710
|
+
isPathInsideProject,
|
|
15711
|
+
isSupportedSourceExtension,
|
|
14899
15712
|
listKnownInteractions,
|
|
15713
|
+
normalizeSourcePath,
|
|
14900
15714
|
probePublishedSite,
|
|
14901
15715
|
resolveGitHubScanInput,
|
|
14902
15716
|
resolveGraphAnchorForFinding,
|
|
15717
|
+
resolveSourceImport,
|
|
15718
|
+
resolveSourceSymbolOrigin,
|
|
14903
15719
|
scanProject,
|
|
15720
|
+
sourceKindFromPath,
|
|
15721
|
+
sourceLanguageFromPath,
|
|
15722
|
+
sourceLocationForNode,
|
|
15723
|
+
sourceScriptKindFromPath,
|
|
14904
15724
|
verifyInteractionsInSource
|
|
14905
15725
|
};
|
|
14906
15726
|
//# sourceMappingURL=index.js.map
|