@drskillissue/ganko 0.1.22 → 0.1.24
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 +1 -1
- package/dist/{chunk-5IOPY65Q.js → chunk-64TMAKYI.js} +975 -754
- package/dist/chunk-64TMAKYI.js.map +1 -0
- package/dist/{chunk-IF3V4IQF.js → chunk-KVZ56NZ5.js} +7 -6
- package/dist/chunk-KVZ56NZ5.js.map +1 -0
- package/dist/eslint-plugin.cjs +901 -680
- package/dist/eslint-plugin.cjs.map +1 -1
- package/dist/eslint-plugin.js +1 -1
- package/dist/index.cjs +907 -685
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -55
- package/dist/index.d.ts +112 -55
- package/dist/index.js +2 -2
- package/dist/rules-manifest.cjs +6 -5
- package/dist/rules-manifest.cjs.map +1 -1
- package/dist/rules-manifest.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5IOPY65Q.js.map +0 -1
- package/dist/chunk-IF3V4IQF.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -8919,7 +8919,7 @@ function resolveMessage(template, data) {
|
|
|
8919
8919
|
}
|
|
8920
8920
|
return result;
|
|
8921
8921
|
}
|
|
8922
|
-
function createDiagnosticFromLoc(file, loc, rule, messageId, message, severity, fix) {
|
|
8922
|
+
function createDiagnosticFromLoc(file, loc, rule, messageId, message, severity, fix, suggest) {
|
|
8923
8923
|
const result = {
|
|
8924
8924
|
file,
|
|
8925
8925
|
rule,
|
|
@@ -8929,13 +8929,14 @@ function createDiagnosticFromLoc(file, loc, rule, messageId, message, severity,
|
|
|
8929
8929
|
loc: firstLine(loc)
|
|
8930
8930
|
};
|
|
8931
8931
|
if (fix !== void 0) result.fix = fix;
|
|
8932
|
+
if (suggest !== void 0 && suggest.length > 0) result.suggest = suggest;
|
|
8932
8933
|
return result;
|
|
8933
8934
|
}
|
|
8934
|
-
function createDiagnosticFromComment(file, comment, rule, messageId, message, severity, fix) {
|
|
8935
|
-
return createDiagnosticFromLoc(file, comment.loc, rule, messageId, message, severity, fix);
|
|
8935
|
+
function createDiagnosticFromComment(file, comment, rule, messageId, message, severity, fix, suggest) {
|
|
8936
|
+
return createDiagnosticFromLoc(file, comment.loc, rule, messageId, message, severity, fix, suggest);
|
|
8936
8937
|
}
|
|
8937
|
-
function createDiagnostic(file, node, rule, messageId, message, severity, fix) {
|
|
8938
|
-
return createDiagnosticFromLoc(file, node.loc, rule, messageId, message, severity, fix);
|
|
8938
|
+
function createDiagnostic(file, node, rule, messageId, message, severity, fix, suggest) {
|
|
8939
|
+
return createDiagnosticFromLoc(file, node.loc, rule, messageId, message, severity, fix, suggest);
|
|
8939
8940
|
}
|
|
8940
8941
|
|
|
8941
8942
|
// src/solid/rule.ts
|
|
@@ -12091,8 +12092,9 @@ var CONDITIONAL_MOUNT_TAGS = /* @__PURE__ */ new Set([
|
|
|
12091
12092
|
"TabPanel"
|
|
12092
12093
|
]);
|
|
12093
12094
|
var messages16 = {
|
|
12094
|
-
loadingMismatch: "createResource '{{name}}' has no initialValue but uses
|
|
12095
|
-
conditionalSuspense: "createResource '{{name}}'
|
|
12095
|
+
loadingMismatch: "createResource '{{name}}' has no initialValue but uses {{name}}.loading for manual loading UI. Suspense intercepts before your loading UI renders \u2014 the component is unmounted before the <Show>/<Switch> evaluates. Replace createResource with onMount + createSignal to decouple from Suspense entirely.",
|
|
12096
|
+
conditionalSuspense: "createResource '{{name}}' is inside a conditional mount point ({{mountTag}}) with a distant Suspense boundary. The SuspenseContext increment fires when the fetcher's Promise is pending and unmounts the entire page subtree \u2014 initialValue does NOT prevent this. Replace createResource with onMount + createSignal to avoid Suspense interaction.",
|
|
12097
|
+
missingErrorBoundary: "createResource '{{name}}' has no <ErrorBoundary> between its component and the nearest <Suspense>. When the fetcher throws (network error, 401/403/503, timeout), the error propagates to Suspense which has no error handling \u2014 the boundary breaks permanently. Wrap the component in <ErrorBoundary> or replace createResource with onMount + createSignal and catch errors in the fetcher."
|
|
12096
12098
|
};
|
|
12097
12099
|
var options16 = {};
|
|
12098
12100
|
function hasInitialValue(call) {
|
|
@@ -12135,35 +12137,95 @@ function hasLoadingRead(resourceVariable) {
|
|
|
12135
12137
|
}
|
|
12136
12138
|
return false;
|
|
12137
12139
|
}
|
|
12138
|
-
function
|
|
12140
|
+
function resolveFetcherFunction(graph, call) {
|
|
12141
|
+
const args = call.node.arguments;
|
|
12142
|
+
if (args.length === 0) return null;
|
|
12143
|
+
let fetcherNode;
|
|
12144
|
+
if (args.length === 1) {
|
|
12145
|
+
fetcherNode = args[0];
|
|
12146
|
+
} else if (args.length === 2) {
|
|
12147
|
+
const lastArg = args[1];
|
|
12148
|
+
fetcherNode = lastArg && lastArg.type === "ObjectExpression" ? args[0] : args[1];
|
|
12149
|
+
} else {
|
|
12150
|
+
fetcherNode = args[1];
|
|
12151
|
+
}
|
|
12152
|
+
if (!fetcherNode) return null;
|
|
12153
|
+
if (fetcherNode.type === "ArrowFunctionExpression" || fetcherNode.type === "FunctionExpression") {
|
|
12154
|
+
return graph.functionsByNode.get(fetcherNode) ?? null;
|
|
12155
|
+
}
|
|
12156
|
+
if (fetcherNode.type === "Identifier") {
|
|
12157
|
+
const fns = graph.functionsByName.get(fetcherNode.name);
|
|
12158
|
+
if (fns && fns.length > 0) {
|
|
12159
|
+
const fn = fns[0];
|
|
12160
|
+
if (fn) return fn;
|
|
12161
|
+
}
|
|
12162
|
+
}
|
|
12163
|
+
return null;
|
|
12164
|
+
}
|
|
12165
|
+
function fetcherCanThrow(graph, fn, visited) {
|
|
12166
|
+
if (visited.has(fn.id)) return false;
|
|
12167
|
+
visited.add(fn.id);
|
|
12168
|
+
if (fn.async && fn.awaitRanges.length > 0) return true;
|
|
12169
|
+
if (fn.hasThrowStatement) return true;
|
|
12170
|
+
const callSites = fn.callSites;
|
|
12171
|
+
for (let i = 0, len = callSites.length; i < len; i++) {
|
|
12172
|
+
const callSite = callSites[i];
|
|
12173
|
+
if (!callSite) continue;
|
|
12174
|
+
if (!callSite.resolvedTarget) return true;
|
|
12175
|
+
if (fetcherCanThrow(graph, callSite.resolvedTarget, visited)) return true;
|
|
12176
|
+
}
|
|
12177
|
+
return false;
|
|
12178
|
+
}
|
|
12179
|
+
function analyzeComponentBoundaries(graph, componentName) {
|
|
12180
|
+
const result = {
|
|
12181
|
+
conditionalMountTag: null,
|
|
12182
|
+
suspenseDistance: 0,
|
|
12183
|
+
lacksErrorBoundary: false,
|
|
12184
|
+
usagesLackingErrorBoundary: []
|
|
12185
|
+
};
|
|
12139
12186
|
const usages = graph.jsxByTag.get(componentName) ?? [];
|
|
12187
|
+
if (usages.length === 0) return result;
|
|
12140
12188
|
for (let i = 0, len = usages.length; i < len; i++) {
|
|
12141
12189
|
const usage = usages[i];
|
|
12142
12190
|
if (!usage) continue;
|
|
12143
12191
|
let current = usage.parent;
|
|
12144
12192
|
let conditionalTag = null;
|
|
12145
12193
|
let componentLevels = 0;
|
|
12194
|
+
let foundErrorBoundary = false;
|
|
12195
|
+
let foundSuspense = false;
|
|
12146
12196
|
while (current) {
|
|
12147
12197
|
const tag = current.tag;
|
|
12148
12198
|
if (tag && !current.isDomElement) {
|
|
12149
12199
|
componentLevels++;
|
|
12150
|
-
if (tag === "
|
|
12200
|
+
if (tag === "ErrorBoundary") {
|
|
12201
|
+
foundErrorBoundary = true;
|
|
12202
|
+
} else if (tag === "Suspense") {
|
|
12203
|
+
foundSuspense = true;
|
|
12204
|
+
if (!foundErrorBoundary) {
|
|
12205
|
+
result.lacksErrorBoundary = true;
|
|
12206
|
+
result.usagesLackingErrorBoundary.push(usage);
|
|
12207
|
+
}
|
|
12151
12208
|
if (conditionalTag !== null && componentLevels > 1) {
|
|
12152
|
-
|
|
12209
|
+
result.conditionalMountTag = conditionalTag;
|
|
12210
|
+
result.suspenseDistance = componentLevels;
|
|
12153
12211
|
}
|
|
12154
|
-
|
|
12155
|
-
}
|
|
12156
|
-
if (conditionalTag === null && CONDITIONAL_MOUNT_TAGS.has(tag)) {
|
|
12212
|
+
break;
|
|
12213
|
+
} else if (conditionalTag === null && CONDITIONAL_MOUNT_TAGS.has(tag)) {
|
|
12157
12214
|
conditionalTag = tag;
|
|
12158
12215
|
}
|
|
12159
12216
|
}
|
|
12160
12217
|
current = current.parent;
|
|
12161
12218
|
}
|
|
12162
|
-
if (
|
|
12163
|
-
|
|
12219
|
+
if (!foundSuspense && !foundErrorBoundary) {
|
|
12220
|
+
result.lacksErrorBoundary = true;
|
|
12221
|
+
result.usagesLackingErrorBoundary.push(usage);
|
|
12222
|
+
if (conditionalTag !== null) {
|
|
12223
|
+
result.conditionalMountTag = conditionalTag;
|
|
12224
|
+
result.suspenseDistance = componentLevels;
|
|
12225
|
+
}
|
|
12164
12226
|
}
|
|
12165
12227
|
}
|
|
12166
|
-
return
|
|
12228
|
+
return result;
|
|
12167
12229
|
}
|
|
12168
12230
|
function getContainingComponentName(graph, call) {
|
|
12169
12231
|
const selfComponent = graph.componentScopes.get(call.scope);
|
|
@@ -12180,43 +12242,65 @@ function findResourceVariable(graph, name) {
|
|
|
12180
12242
|
}
|
|
12181
12243
|
return null;
|
|
12182
12244
|
}
|
|
12245
|
+
function buildErrorBoundaryFix(usages, graph) {
|
|
12246
|
+
if (usages.length === 0) return null;
|
|
12247
|
+
const usage = usages[0];
|
|
12248
|
+
if (!usage) return null;
|
|
12249
|
+
const jsxNode = usage.node;
|
|
12250
|
+
const startPos = jsxNode.range[0];
|
|
12251
|
+
const endPos = jsxNode.range[1];
|
|
12252
|
+
const ops = [
|
|
12253
|
+
{ range: [startPos, startPos], text: "<ErrorBoundary fallback={<div>Error</div>}>" },
|
|
12254
|
+
{ range: [endPos, endPos], text: "</ErrorBoundary>" }
|
|
12255
|
+
];
|
|
12256
|
+
const importFix = buildSolidImportFix(graph, "ErrorBoundary");
|
|
12257
|
+
if (importFix) ops.unshift(importFix);
|
|
12258
|
+
return ops;
|
|
12259
|
+
}
|
|
12183
12260
|
var resourceImplicitSuspense = defineSolidRule({
|
|
12184
12261
|
id: "resource-implicit-suspense",
|
|
12185
12262
|
severity: "warn",
|
|
12186
12263
|
messages: messages16,
|
|
12187
12264
|
meta: {
|
|
12188
|
-
description: "Detect createResource
|
|
12189
|
-
fixable:
|
|
12265
|
+
description: "Detect createResource that implicitly triggers or permanently breaks Suspense boundaries.",
|
|
12266
|
+
fixable: true,
|
|
12190
12267
|
category: "reactivity"
|
|
12191
12268
|
},
|
|
12192
12269
|
options: options16,
|
|
12193
12270
|
check(graph, emit) {
|
|
12194
12271
|
const resourceCalls = getCallsByPrimitive(graph, "createResource");
|
|
12195
12272
|
if (resourceCalls.length === 0) return;
|
|
12273
|
+
const throwVisited = /* @__PURE__ */ new Set();
|
|
12274
|
+
const boundaryCache = /* @__PURE__ */ new Map();
|
|
12196
12275
|
for (let i = 0, len = resourceCalls.length; i < len; i++) {
|
|
12197
12276
|
const call = resourceCalls[i];
|
|
12198
12277
|
if (!call) continue;
|
|
12199
|
-
if (hasInitialValue(call)) continue;
|
|
12200
12278
|
const resourceName = getResourceVariableName(call);
|
|
12201
12279
|
if (!resourceName) continue;
|
|
12202
|
-
const
|
|
12203
|
-
if (resourceVariable && hasLoadingRead(resourceVariable)) {
|
|
12204
|
-
emit(
|
|
12205
|
-
createDiagnostic(
|
|
12206
|
-
graph.file,
|
|
12207
|
-
call.node,
|
|
12208
|
-
"resource-implicit-suspense",
|
|
12209
|
-
"loadingMismatch",
|
|
12210
|
-
resolveMessage(messages16.loadingMismatch, { name: resourceName }),
|
|
12211
|
-
"warn"
|
|
12212
|
-
)
|
|
12213
|
-
);
|
|
12214
|
-
continue;
|
|
12215
|
-
}
|
|
12280
|
+
const hasInitial = hasInitialValue(call);
|
|
12216
12281
|
const componentName = getContainingComponentName(graph, call);
|
|
12282
|
+
if (!hasInitial) {
|
|
12283
|
+
const resourceVariable = findResourceVariable(graph, resourceName);
|
|
12284
|
+
if (resourceVariable && hasLoadingRead(resourceVariable)) {
|
|
12285
|
+
emit(
|
|
12286
|
+
createDiagnostic(
|
|
12287
|
+
graph.file,
|
|
12288
|
+
call.node,
|
|
12289
|
+
"resource-implicit-suspense",
|
|
12290
|
+
"loadingMismatch",
|
|
12291
|
+
resolveMessage(messages16.loadingMismatch, { name: resourceName }),
|
|
12292
|
+
"warn"
|
|
12293
|
+
)
|
|
12294
|
+
);
|
|
12295
|
+
}
|
|
12296
|
+
}
|
|
12217
12297
|
if (!componentName) continue;
|
|
12218
|
-
|
|
12219
|
-
if (
|
|
12298
|
+
let analysis = boundaryCache.get(componentName);
|
|
12299
|
+
if (!analysis) {
|
|
12300
|
+
analysis = analyzeComponentBoundaries(graph, componentName);
|
|
12301
|
+
boundaryCache.set(componentName, analysis);
|
|
12302
|
+
}
|
|
12303
|
+
if (analysis.conditionalMountTag) {
|
|
12220
12304
|
emit(
|
|
12221
12305
|
createDiagnostic(
|
|
12222
12306
|
graph.file,
|
|
@@ -12225,12 +12309,32 @@ var resourceImplicitSuspense = defineSolidRule({
|
|
|
12225
12309
|
"conditionalSuspense",
|
|
12226
12310
|
resolveMessage(messages16.conditionalSuspense, {
|
|
12227
12311
|
name: resourceName,
|
|
12228
|
-
mountTag:
|
|
12312
|
+
mountTag: analysis.conditionalMountTag
|
|
12229
12313
|
}),
|
|
12230
12314
|
"error"
|
|
12231
12315
|
)
|
|
12232
12316
|
);
|
|
12233
12317
|
}
|
|
12318
|
+
if (analysis.lacksErrorBoundary) {
|
|
12319
|
+
const fetcherFn = resolveFetcherFunction(graph, call);
|
|
12320
|
+
if (fetcherFn && fetcherCanThrow(graph, fetcherFn, throwVisited)) {
|
|
12321
|
+
const errorBoundaryFix = buildErrorBoundaryFix(
|
|
12322
|
+
analysis.usagesLackingErrorBoundary,
|
|
12323
|
+
graph
|
|
12324
|
+
);
|
|
12325
|
+
emit(
|
|
12326
|
+
createDiagnostic(
|
|
12327
|
+
graph.file,
|
|
12328
|
+
call.node,
|
|
12329
|
+
"resource-implicit-suspense",
|
|
12330
|
+
"missingErrorBoundary",
|
|
12331
|
+
resolveMessage(messages16.missingErrorBoundary, { name: resourceName }),
|
|
12332
|
+
"error",
|
|
12333
|
+
errorBoundaryFix ?? void 0
|
|
12334
|
+
)
|
|
12335
|
+
);
|
|
12336
|
+
}
|
|
12337
|
+
}
|
|
12234
12338
|
}
|
|
12235
12339
|
}
|
|
12236
12340
|
});
|
|
@@ -30163,6 +30267,11 @@ function toLayoutElementKey(solidFile, elementId) {
|
|
|
30163
30267
|
return `${solidFile}::${elementId}`;
|
|
30164
30268
|
}
|
|
30165
30269
|
|
|
30270
|
+
// src/cross-file/layout/context-model.ts
|
|
30271
|
+
function deriveAlignmentContext(base, overrides) {
|
|
30272
|
+
return { ...base, ...overrides };
|
|
30273
|
+
}
|
|
30274
|
+
|
|
30166
30275
|
// src/cross-file/layout/signal-model.ts
|
|
30167
30276
|
var layoutSignalNames = [
|
|
30168
30277
|
"line-height",
|
|
@@ -30191,6 +30300,8 @@ var layoutSignalNames = [
|
|
|
30191
30300
|
"justify-items",
|
|
30192
30301
|
"place-items",
|
|
30193
30302
|
"place-self",
|
|
30303
|
+
"flex-direction",
|
|
30304
|
+
"grid-auto-flow",
|
|
30194
30305
|
"appearance",
|
|
30195
30306
|
"box-sizing",
|
|
30196
30307
|
"padding-top",
|
|
@@ -30309,13 +30420,44 @@ function expandShorthand(property, value2) {
|
|
|
30309
30420
|
{ name: blockTarget[1], value: parsed.end }
|
|
30310
30421
|
];
|
|
30311
30422
|
}
|
|
30423
|
+
if (property === "flex-flow") {
|
|
30424
|
+
return expandFlexFlow(value2);
|
|
30425
|
+
}
|
|
30312
30426
|
return void 0;
|
|
30313
30427
|
}
|
|
30428
|
+
var FLEX_DIRECTION_VALUES = /* @__PURE__ */ new Set(["row", "row-reverse", "column", "column-reverse"]);
|
|
30429
|
+
function expandFlexFlow(value2) {
|
|
30430
|
+
const tokens = splitWhitespaceTokens(value2.trim().toLowerCase());
|
|
30431
|
+
if (tokens.length === 0) return null;
|
|
30432
|
+
if (tokens.length > 2) return null;
|
|
30433
|
+
let direction = null;
|
|
30434
|
+
let wrap = null;
|
|
30435
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
30436
|
+
const token = tokens[i];
|
|
30437
|
+
if (!token) continue;
|
|
30438
|
+
if (FLEX_DIRECTION_VALUES.has(token)) {
|
|
30439
|
+
if (direction !== null) return null;
|
|
30440
|
+
direction = token;
|
|
30441
|
+
} else {
|
|
30442
|
+
if (wrap !== null) return null;
|
|
30443
|
+
wrap = token;
|
|
30444
|
+
}
|
|
30445
|
+
}
|
|
30446
|
+
const out = [];
|
|
30447
|
+
if (direction !== null) {
|
|
30448
|
+
out.push({ name: "flex-direction", value: direction });
|
|
30449
|
+
}
|
|
30450
|
+
if (wrap !== null) {
|
|
30451
|
+
out.push({ name: "flex-wrap", value: wrap });
|
|
30452
|
+
}
|
|
30453
|
+
return out.length > 0 ? out : null;
|
|
30454
|
+
}
|
|
30314
30455
|
function getShorthandLonghandNames(property) {
|
|
30315
30456
|
const quad = QUAD_EXPANSIONS.get(property);
|
|
30316
30457
|
if (quad !== void 0) return [...quad];
|
|
30317
30458
|
const block = BLOCK_EXPANSIONS.get(property);
|
|
30318
30459
|
if (block !== void 0) return [...block];
|
|
30460
|
+
if (property === "flex-flow") return ["flex-direction", "flex-wrap"];
|
|
30319
30461
|
return null;
|
|
30320
30462
|
}
|
|
30321
30463
|
|
|
@@ -30326,27 +30468,90 @@ var CONTROL_ELEMENT_TAGS = /* @__PURE__ */ new Set([
|
|
|
30326
30468
|
"textarea",
|
|
30327
30469
|
"button"
|
|
30328
30470
|
]);
|
|
30471
|
+
var INTRINSIC_REPLACED_TAGS = /* @__PURE__ */ new Set([
|
|
30472
|
+
"img",
|
|
30473
|
+
"svg",
|
|
30474
|
+
"video",
|
|
30475
|
+
"canvas",
|
|
30476
|
+
"iframe",
|
|
30477
|
+
"object",
|
|
30478
|
+
"embed"
|
|
30479
|
+
]);
|
|
30480
|
+
var WHITESPACE_RE3 = /\s+/;
|
|
30329
30481
|
function clamp(value2, min, max) {
|
|
30330
30482
|
if (value2 < min) return min;
|
|
30331
30483
|
if (value2 > max) return max;
|
|
30332
30484
|
return value2;
|
|
30333
30485
|
}
|
|
30334
|
-
function kindRank(kind) {
|
|
30335
|
-
if (kind === "exact") return 0;
|
|
30336
|
-
if (kind === "interval") return 1;
|
|
30337
|
-
if (kind === "conditional") return 2;
|
|
30338
|
-
return 3;
|
|
30339
|
-
}
|
|
30340
30486
|
function mergeEvidenceKind(left, right) {
|
|
30341
|
-
|
|
30342
|
-
|
|
30487
|
+
return left > right ? left : right;
|
|
30488
|
+
}
|
|
30489
|
+
function selectKth(values, targetIndex) {
|
|
30490
|
+
let left = 0;
|
|
30491
|
+
let right = values.length - 1;
|
|
30492
|
+
while (left <= right) {
|
|
30493
|
+
if (left === right) {
|
|
30494
|
+
const result = values[left];
|
|
30495
|
+
if (result === void 0) return 0;
|
|
30496
|
+
return result;
|
|
30497
|
+
}
|
|
30498
|
+
const pivotIndex = choosePivotIndex(values, left, right);
|
|
30499
|
+
const partitionIndex = partitionAroundPivot(values, left, right, pivotIndex);
|
|
30500
|
+
if (partitionIndex === targetIndex) {
|
|
30501
|
+
const result = values[partitionIndex];
|
|
30502
|
+
if (result === void 0) return 0;
|
|
30503
|
+
return result;
|
|
30504
|
+
}
|
|
30505
|
+
if (partitionIndex < targetIndex) {
|
|
30506
|
+
left = partitionIndex + 1;
|
|
30507
|
+
continue;
|
|
30508
|
+
}
|
|
30509
|
+
right = partitionIndex - 1;
|
|
30510
|
+
}
|
|
30511
|
+
const fallback = values[targetIndex];
|
|
30512
|
+
if (fallback === void 0) return 0;
|
|
30513
|
+
return fallback;
|
|
30514
|
+
}
|
|
30515
|
+
function choosePivotIndex(values, left, right) {
|
|
30516
|
+
const middle = Math.floor((left + right) / 2);
|
|
30517
|
+
const leftValue = values[left] ?? 0;
|
|
30518
|
+
const middleValue = values[middle] ?? 0;
|
|
30519
|
+
const rightValue = values[right] ?? 0;
|
|
30520
|
+
if (leftValue < middleValue) {
|
|
30521
|
+
if (middleValue < rightValue) return middle;
|
|
30522
|
+
if (leftValue < rightValue) return right;
|
|
30523
|
+
return left;
|
|
30524
|
+
}
|
|
30525
|
+
if (leftValue < rightValue) return left;
|
|
30526
|
+
if (middleValue < rightValue) return right;
|
|
30527
|
+
return middle;
|
|
30528
|
+
}
|
|
30529
|
+
function partitionAroundPivot(values, left, right, pivotIndex) {
|
|
30530
|
+
const pivotValue = values[pivotIndex] ?? 0;
|
|
30531
|
+
swap(values, pivotIndex, right);
|
|
30532
|
+
let storeIndex = left;
|
|
30533
|
+
for (let i = left; i < right; i++) {
|
|
30534
|
+
const current = values[i];
|
|
30535
|
+
if (current === void 0 || current > pivotValue) continue;
|
|
30536
|
+
swap(values, storeIndex, i);
|
|
30537
|
+
storeIndex++;
|
|
30538
|
+
}
|
|
30539
|
+
swap(values, storeIndex, right);
|
|
30540
|
+
return storeIndex;
|
|
30541
|
+
}
|
|
30542
|
+
function swap(values, left, right) {
|
|
30543
|
+
if (left === right) return;
|
|
30544
|
+
const leftValue = values[left] ?? 0;
|
|
30545
|
+
const rightValue = values[right] ?? 0;
|
|
30546
|
+
values[left] = rightValue;
|
|
30547
|
+
values[right] = leftValue;
|
|
30343
30548
|
}
|
|
30344
30549
|
function toComparableExactValue(value2) {
|
|
30345
30550
|
if (value2.value !== null) {
|
|
30346
|
-
if (value2.kind !==
|
|
30551
|
+
if (value2.kind !== 0 /* Exact */) return null;
|
|
30347
30552
|
return value2.value;
|
|
30348
30553
|
}
|
|
30349
|
-
if (value2.kind ===
|
|
30554
|
+
if (value2.kind === 0 /* Exact */) return 0;
|
|
30350
30555
|
return null;
|
|
30351
30556
|
}
|
|
30352
30557
|
|
|
@@ -30360,7 +30565,8 @@ var MONITORED_SHORTHAND_SET = /* @__PURE__ */ new Set([
|
|
|
30360
30565
|
"border-width",
|
|
30361
30566
|
"margin-block",
|
|
30362
30567
|
"padding-block",
|
|
30363
|
-
"inset-block"
|
|
30568
|
+
"inset-block",
|
|
30569
|
+
"flex-flow"
|
|
30364
30570
|
]);
|
|
30365
30571
|
var LENGTH_SIGNAL_SET = /* @__PURE__ */ new Set([
|
|
30366
30572
|
"font-size",
|
|
@@ -30402,13 +30608,22 @@ var KEYWORD_SIGNAL_SET = /* @__PURE__ */ new Set([
|
|
|
30402
30608
|
"justify-items",
|
|
30403
30609
|
"place-items",
|
|
30404
30610
|
"place-self",
|
|
30611
|
+
"flex-direction",
|
|
30612
|
+
"grid-auto-flow",
|
|
30405
30613
|
"appearance",
|
|
30406
30614
|
"box-sizing",
|
|
30407
30615
|
"position",
|
|
30408
30616
|
"writing-mode",
|
|
30409
30617
|
"direction"
|
|
30410
30618
|
]);
|
|
30411
|
-
var
|
|
30619
|
+
var REPLACED_ELEMENT_TAGS = /* @__PURE__ */ new Set([
|
|
30620
|
+
...CONTROL_ELEMENT_TAGS,
|
|
30621
|
+
"img",
|
|
30622
|
+
"video",
|
|
30623
|
+
"canvas",
|
|
30624
|
+
"svg",
|
|
30625
|
+
"iframe"
|
|
30626
|
+
]);
|
|
30412
30627
|
function isMonitoredSignal(property) {
|
|
30413
30628
|
if (MONITORED_SIGNAL_SET.has(property)) return true;
|
|
30414
30629
|
return MONITORED_SHORTHAND_SET.has(property);
|
|
@@ -30419,7 +30634,7 @@ function isControlTag(tag) {
|
|
|
30419
30634
|
}
|
|
30420
30635
|
function isReplacedTag(tag) {
|
|
30421
30636
|
if (tag === null) return false;
|
|
30422
|
-
return
|
|
30637
|
+
return REPLACED_ELEMENT_TAGS.has(tag.toLowerCase());
|
|
30423
30638
|
}
|
|
30424
30639
|
function normalizeSignalMapWithCounts(values) {
|
|
30425
30640
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -30430,12 +30645,11 @@ function normalizeSignalMapWithCounts(values) {
|
|
|
30430
30645
|
"font-size",
|
|
30431
30646
|
fontSizeEntry.value,
|
|
30432
30647
|
fontSizeEntry.source,
|
|
30433
|
-
fontSizeEntry.guard,
|
|
30434
30648
|
fontSizeEntry.guardProvenance,
|
|
30435
30649
|
null
|
|
30436
30650
|
);
|
|
30437
30651
|
out.set("font-size", parsedFontSize);
|
|
30438
|
-
if (parsedFontSize.kind === "known" && parsedFontSize.guard ===
|
|
30652
|
+
if (parsedFontSize.kind === "known" && parsedFontSize.guard.kind === 0 /* Unconditional */) {
|
|
30439
30653
|
fontSizePx = parsedFontSize.px;
|
|
30440
30654
|
}
|
|
30441
30655
|
}
|
|
@@ -30451,7 +30665,6 @@ function normalizeSignalMapWithCounts(values) {
|
|
|
30451
30665
|
name,
|
|
30452
30666
|
declaration.value,
|
|
30453
30667
|
declaration.source,
|
|
30454
|
-
declaration.guard,
|
|
30455
30668
|
declaration.guardProvenance,
|
|
30456
30669
|
fontSizePx
|
|
30457
30670
|
);
|
|
@@ -30461,7 +30674,7 @@ function normalizeSignalMapWithCounts(values) {
|
|
|
30461
30674
|
let unknownSignalCount = 0;
|
|
30462
30675
|
let conditionalSignalCount = 0;
|
|
30463
30676
|
for (const value2 of out.values()) {
|
|
30464
|
-
if (value2.guard ===
|
|
30677
|
+
if (value2.guard.kind === 1 /* Conditional */) {
|
|
30465
30678
|
conditionalSignalCount++;
|
|
30466
30679
|
continue;
|
|
30467
30680
|
}
|
|
@@ -30489,7 +30702,7 @@ function applyExpandedShorthand(out, property, declaration, fontSizePx) {
|
|
|
30489
30702
|
if (!longhand) continue;
|
|
30490
30703
|
const name = MONITORED_SIGNAL_NAME_MAP.get(longhand);
|
|
30491
30704
|
if (name === void 0) continue;
|
|
30492
|
-
out.set(name, createUnknown(name, declaration.
|
|
30705
|
+
out.set(name, createUnknown(name, declaration.source, declaration.guardProvenance, reason));
|
|
30493
30706
|
}
|
|
30494
30707
|
return;
|
|
30495
30708
|
}
|
|
@@ -30499,127 +30712,139 @@ function applyExpandedShorthand(out, property, declaration, fontSizePx) {
|
|
|
30499
30712
|
if (!entry) continue;
|
|
30500
30713
|
const name = MONITORED_SIGNAL_NAME_MAP.get(entry.name);
|
|
30501
30714
|
if (name === void 0) continue;
|
|
30502
|
-
out.set(name, normalizeSignal(name, entry.value, declaration.source, declaration.
|
|
30715
|
+
out.set(name, normalizeSignal(name, entry.value, declaration.source, declaration.guardProvenance, fontSizePx));
|
|
30503
30716
|
}
|
|
30504
30717
|
}
|
|
30505
30718
|
function toMonitoredSignalName(property) {
|
|
30506
30719
|
return MONITORED_SIGNAL_NAME_MAP.get(property) ?? null;
|
|
30507
30720
|
}
|
|
30508
|
-
function normalizeSignal(name, raw, source, guard,
|
|
30721
|
+
function normalizeSignal(name, raw, source, guard, fontSizePx) {
|
|
30509
30722
|
switch (name) {
|
|
30510
30723
|
case "line-height":
|
|
30511
|
-
return parseLineHeight(name, raw, source, guard,
|
|
30724
|
+
return parseLineHeight(name, raw, source, guard, fontSizePx);
|
|
30512
30725
|
case "aspect-ratio":
|
|
30513
|
-
return parseAspectRatio(name, raw, source, guard
|
|
30726
|
+
return parseAspectRatio(name, raw, source, guard);
|
|
30514
30727
|
case "contain-intrinsic-size":
|
|
30515
|
-
return parseContainIntrinsicSize(name, raw, source, guard
|
|
30728
|
+
return parseContainIntrinsicSize(name, raw, source, guard);
|
|
30516
30729
|
case "transform":
|
|
30517
|
-
return parseTransform(name, raw, source, guard
|
|
30730
|
+
return parseTransform(name, raw, source, guard);
|
|
30518
30731
|
case "translate":
|
|
30519
|
-
return parseTranslateProperty(name, raw, source, guard
|
|
30732
|
+
return parseTranslateProperty(name, raw, source, guard);
|
|
30520
30733
|
default:
|
|
30521
30734
|
break;
|
|
30522
30735
|
}
|
|
30523
|
-
if (LENGTH_SIGNAL_SET.has(name)) return parseLength(name, raw, source, guard
|
|
30524
|
-
if (KEYWORD_SIGNAL_SET.has(name)) return parseKeyword(name, raw, source, guard
|
|
30525
|
-
return createUnknown(name,
|
|
30736
|
+
if (LENGTH_SIGNAL_SET.has(name)) return parseLength(name, raw, source, guard);
|
|
30737
|
+
if (KEYWORD_SIGNAL_SET.has(name)) return parseKeyword(name, raw, source, guard);
|
|
30738
|
+
return createUnknown(name, source, guard, "unsupported signal");
|
|
30526
30739
|
}
|
|
30527
|
-
function parseAspectRatio(name, raw, source, guard
|
|
30740
|
+
function parseAspectRatio(name, raw, source, guard) {
|
|
30528
30741
|
const trimmed = raw.trim().toLowerCase();
|
|
30529
30742
|
if (trimmed.length === 0) {
|
|
30530
|
-
return createUnknown(name,
|
|
30743
|
+
return createUnknown(name, source, guard, "aspect-ratio value is empty");
|
|
30531
30744
|
}
|
|
30532
30745
|
if (hasDynamicExpression(trimmed)) {
|
|
30533
|
-
return createUnknown(name,
|
|
30746
|
+
return createUnknown(name, source, guard, "aspect-ratio uses runtime-dependent function");
|
|
30534
30747
|
}
|
|
30535
30748
|
if (trimmed === "auto") {
|
|
30536
|
-
return createUnknown(name,
|
|
30749
|
+
return createUnknown(name, source, guard, "aspect-ratio auto does not reserve ratio");
|
|
30537
30750
|
}
|
|
30538
30751
|
const slash = trimmed.indexOf("/");
|
|
30539
30752
|
if (slash !== -1) {
|
|
30540
30753
|
const left = Number(trimmed.slice(0, slash).trim());
|
|
30541
30754
|
const right = Number(trimmed.slice(slash + 1).trim());
|
|
30542
30755
|
if (!Number.isFinite(left) || !Number.isFinite(right) || left <= 0 || right <= 0) {
|
|
30543
|
-
return createUnknown(name,
|
|
30756
|
+
return createUnknown(name, source, guard, "aspect-ratio ratio is invalid");
|
|
30544
30757
|
}
|
|
30545
|
-
return createKnown(name, raw, source, guard,
|
|
30758
|
+
return createKnown(name, raw, source, guard, null, 1 /* Unitless */, "exact");
|
|
30546
30759
|
}
|
|
30547
30760
|
const ratio = Number(trimmed);
|
|
30548
30761
|
if (!Number.isFinite(ratio) || ratio <= 0) {
|
|
30549
|
-
return createUnknown(name,
|
|
30762
|
+
return createUnknown(name, source, guard, "aspect-ratio is not statically parseable");
|
|
30550
30763
|
}
|
|
30551
|
-
return createKnown(name, raw, source, guard,
|
|
30764
|
+
return createKnown(name, raw, source, guard, null, 1 /* Unitless */, "exact");
|
|
30552
30765
|
}
|
|
30553
|
-
function parseContainIntrinsicSize(name, raw, source, guard
|
|
30766
|
+
function parseContainIntrinsicSize(name, raw, source, guard) {
|
|
30554
30767
|
const trimmed = raw.trim().toLowerCase();
|
|
30555
30768
|
if (trimmed.length === 0) {
|
|
30556
|
-
return createUnknown(name,
|
|
30769
|
+
return createUnknown(name, source, guard, "contain-intrinsic-size value is empty");
|
|
30557
30770
|
}
|
|
30558
30771
|
if (hasDynamicExpression(trimmed)) {
|
|
30559
|
-
return createUnknown(name,
|
|
30772
|
+
return createUnknown(name, source, guard, "contain-intrinsic-size uses runtime-dependent function");
|
|
30560
30773
|
}
|
|
30561
30774
|
if (trimmed === "none" || trimmed === "auto") {
|
|
30562
|
-
return createUnknown(name,
|
|
30775
|
+
return createUnknown(name, source, guard, "contain-intrinsic-size does not reserve space");
|
|
30563
30776
|
}
|
|
30564
30777
|
const parts = splitWhitespaceTokens(trimmed);
|
|
30565
30778
|
for (let i = 0; i < parts.length; i++) {
|
|
30566
30779
|
const part = parts[i];
|
|
30567
30780
|
if (!part) continue;
|
|
30568
30781
|
const px = parseSignedPxValue(part);
|
|
30569
|
-
if (px !== null) return createKnown(name, raw, source, guard,
|
|
30782
|
+
if (px !== null) return createKnown(name, raw, source, guard, px, 0 /* Px */, "exact");
|
|
30570
30783
|
}
|
|
30571
|
-
return createUnknown(name,
|
|
30784
|
+
return createUnknown(name, source, guard, "contain-intrinsic-size is not statically parseable in px");
|
|
30572
30785
|
}
|
|
30573
|
-
function parseLineHeight(name, raw, source, guard,
|
|
30786
|
+
function parseLineHeight(name, raw, source, guard, fontSizePx) {
|
|
30574
30787
|
const unitless = parseUnitlessValue(raw);
|
|
30575
30788
|
if (unitless !== null) {
|
|
30576
30789
|
const base = fontSizePx === null ? 16 : fontSizePx;
|
|
30577
|
-
return createKnown(name, raw, source, guard,
|
|
30790
|
+
return createKnown(name, raw, source, guard, unitless * base, 1 /* Unitless */, "estimated");
|
|
30578
30791
|
}
|
|
30579
30792
|
const px = parseSignedPxValue(raw);
|
|
30580
|
-
if (px !== null) return createKnown(name, raw, source, guard,
|
|
30581
|
-
return createUnknown(name,
|
|
30793
|
+
if (px !== null) return createKnown(name, raw, source, guard, px, 0 /* Px */, "exact");
|
|
30794
|
+
return createUnknown(name, source, guard, "line-height is not statically parseable");
|
|
30582
30795
|
}
|
|
30583
|
-
|
|
30796
|
+
var DIMENSION_KEYWORD_SET = /* @__PURE__ */ new Set([
|
|
30797
|
+
"auto",
|
|
30798
|
+
"none",
|
|
30799
|
+
"fit-content",
|
|
30800
|
+
"min-content",
|
|
30801
|
+
"max-content",
|
|
30802
|
+
"stretch"
|
|
30803
|
+
]);
|
|
30804
|
+
function parseLength(name, raw, source, guard) {
|
|
30584
30805
|
const px = parseSignedPxValue(raw);
|
|
30585
|
-
if (px
|
|
30586
|
-
return
|
|
30806
|
+
if (px !== null) {
|
|
30807
|
+
return createKnown(name, raw, source, guard, px, 0 /* Px */, "exact");
|
|
30587
30808
|
}
|
|
30588
|
-
|
|
30809
|
+
const normalized = raw.trim().toLowerCase();
|
|
30810
|
+
if (DIMENSION_KEYWORD_SET.has(normalized) || normalized.startsWith("fit-content(")) {
|
|
30811
|
+
return createKnown(name, raw, source, guard, null, 2 /* Keyword */, "exact");
|
|
30812
|
+
}
|
|
30813
|
+
return createUnknown(name, source, guard, "length is not statically parseable in px");
|
|
30589
30814
|
}
|
|
30590
|
-
function parseKeyword(name, raw, source, guard
|
|
30815
|
+
function parseKeyword(name, raw, source, guard) {
|
|
30591
30816
|
const normalized = raw.trim().toLowerCase();
|
|
30592
30817
|
if (normalized.length === 0) {
|
|
30593
|
-
return createUnknown(name,
|
|
30818
|
+
return createUnknown(name, source, guard, "keyword value is empty");
|
|
30594
30819
|
}
|
|
30595
30820
|
if (hasDynamicExpression(normalized)) {
|
|
30596
|
-
return createUnknown(name,
|
|
30821
|
+
return createUnknown(name, source, guard, "keyword uses runtime-dependent function");
|
|
30597
30822
|
}
|
|
30598
|
-
return createKnown(name, raw, source, guard,
|
|
30823
|
+
return createKnown(name, raw, source, guard, null, 2 /* Keyword */, "exact");
|
|
30599
30824
|
}
|
|
30600
|
-
function parseTransform(name, raw, source, guard
|
|
30825
|
+
function parseTransform(name, raw, source, guard) {
|
|
30601
30826
|
const normalized = raw.trim().toLowerCase();
|
|
30602
30827
|
if (normalized.length === 0) {
|
|
30603
|
-
return createUnknown(name,
|
|
30828
|
+
return createUnknown(name, source, guard, "transform value is empty");
|
|
30604
30829
|
}
|
|
30605
30830
|
if (hasDynamicExpression(normalized)) {
|
|
30606
|
-
return createUnknown(name,
|
|
30831
|
+
return createUnknown(name, source, guard, "transform uses runtime-dependent function");
|
|
30607
30832
|
}
|
|
30608
30833
|
const y = extractTransformYPx(normalized);
|
|
30609
|
-
if (y !== null) return createKnown(name, raw, source, guard,
|
|
30610
|
-
return createUnknown(name,
|
|
30834
|
+
if (y !== null) return createKnown(name, raw, source, guard, y, 0 /* Px */, "exact");
|
|
30835
|
+
return createUnknown(name, source, guard, "transform has non-translational or non-px functions");
|
|
30611
30836
|
}
|
|
30612
|
-
function parseTranslateProperty(name, raw, source, guard
|
|
30837
|
+
function parseTranslateProperty(name, raw, source, guard) {
|
|
30613
30838
|
const trimmed = raw.trim().toLowerCase();
|
|
30614
30839
|
if (trimmed.length === 0) {
|
|
30615
|
-
return createUnknown(name,
|
|
30840
|
+
return createUnknown(name, source, guard, "translate value is empty");
|
|
30616
30841
|
}
|
|
30617
30842
|
if (hasDynamicExpression(trimmed)) {
|
|
30618
|
-
return createUnknown(name,
|
|
30843
|
+
return createUnknown(name, source, guard, "translate uses runtime-dependent function");
|
|
30619
30844
|
}
|
|
30620
30845
|
const y = extractTranslatePropertyYPx(trimmed);
|
|
30621
|
-
if (y !== null) return createKnown(name, raw, source, guard,
|
|
30622
|
-
return createUnknown(name,
|
|
30846
|
+
if (y !== null) return createKnown(name, raw, source, guard, y, 0 /* Px */, "exact");
|
|
30847
|
+
return createUnknown(name, source, guard, "translate property vertical component is not px");
|
|
30623
30848
|
}
|
|
30624
30849
|
function hasDynamicExpression(raw) {
|
|
30625
30850
|
if (raw.includes("var(")) return true;
|
|
@@ -30631,28 +30856,24 @@ function hasDynamicExpression(raw) {
|
|
|
30631
30856
|
if (raw.includes("clamp(")) return true;
|
|
30632
30857
|
return false;
|
|
30633
30858
|
}
|
|
30634
|
-
function createKnown(name, raw, source, guard,
|
|
30859
|
+
function createKnown(name, raw, source, guard, px, unit, quality) {
|
|
30635
30860
|
return {
|
|
30636
30861
|
kind: "known",
|
|
30637
30862
|
name,
|
|
30638
|
-
raw,
|
|
30639
30863
|
normalized: raw.trim().toLowerCase(),
|
|
30640
30864
|
source,
|
|
30641
30865
|
guard,
|
|
30642
|
-
guardProvenance,
|
|
30643
30866
|
unit,
|
|
30644
30867
|
px,
|
|
30645
30868
|
quality
|
|
30646
30869
|
};
|
|
30647
30870
|
}
|
|
30648
|
-
function createUnknown(name,
|
|
30871
|
+
function createUnknown(name, source, guard, reason) {
|
|
30649
30872
|
return {
|
|
30650
30873
|
kind: "unknown",
|
|
30651
30874
|
name,
|
|
30652
|
-
raw,
|
|
30653
30875
|
source,
|
|
30654
30876
|
guard,
|
|
30655
|
-
guardProvenance,
|
|
30656
30877
|
reason
|
|
30657
30878
|
};
|
|
30658
30879
|
}
|
|
@@ -30699,13 +30920,7 @@ function buildSnapshotForNode(node, cascadeByElementNode, snapshotByElementNode,
|
|
|
30699
30920
|
const unknownSignalCount = normalized.unknownSignalCount + inherited.unknownDelta;
|
|
30700
30921
|
const conditionalSignalCount = normalized.conditionalSignalCount + inherited.conditionalDelta;
|
|
30701
30922
|
const snapshot = {
|
|
30702
|
-
|
|
30703
|
-
elementId: node.elementId,
|
|
30704
|
-
elementKey: node.key,
|
|
30705
|
-
tag: node.tag,
|
|
30706
|
-
textualContent: node.textualContent,
|
|
30707
|
-
isControl: node.isControl,
|
|
30708
|
-
isReplaced: node.isReplaced,
|
|
30923
|
+
node,
|
|
30709
30924
|
signals: inherited.signals,
|
|
30710
30925
|
knownSignalCount,
|
|
30711
30926
|
unknownSignalCount,
|
|
@@ -30736,7 +30951,7 @@ function inheritSignalsFromParent(parentSnapshot, local) {
|
|
|
30736
30951
|
if (!inheritedValue) continue;
|
|
30737
30952
|
if (out === null) out = new Map(local);
|
|
30738
30953
|
out.set(signal, inheritedValue);
|
|
30739
|
-
if (inheritedValue.guard ===
|
|
30954
|
+
if (inheritedValue.guard.kind === 1 /* Conditional */) {
|
|
30740
30955
|
conditionalDelta++;
|
|
30741
30956
|
continue;
|
|
30742
30957
|
}
|
|
@@ -30780,7 +30995,7 @@ var EMPTY_LAYOUT_RESERVED_SPACE_FACT = Object.freeze({
|
|
|
30780
30995
|
});
|
|
30781
30996
|
var EMPTY_LAYOUT_SCROLL_CONTAINER_FACT = Object.freeze({
|
|
30782
30997
|
isScrollContainer: false,
|
|
30783
|
-
axis:
|
|
30998
|
+
axis: 0 /* None */,
|
|
30784
30999
|
overflow: null,
|
|
30785
31000
|
overflowY: null,
|
|
30786
31001
|
hasConditionalScroll: false,
|
|
@@ -30813,53 +31028,28 @@ function readKnownSignalWithGuard(snapshot, name) {
|
|
|
30813
31028
|
return value2;
|
|
30814
31029
|
}
|
|
30815
31030
|
function toEvidenceKind(value2) {
|
|
30816
|
-
if (value2.guard ===
|
|
30817
|
-
if (value2.quality === "estimated") return
|
|
30818
|
-
return
|
|
30819
|
-
}
|
|
30820
|
-
function readNumericSignalEvidence(snapshot, name) {
|
|
30821
|
-
const value2 = snapshot.signals.get(name);
|
|
30822
|
-
if (!value2) {
|
|
30823
|
-
return {
|
|
30824
|
-
value: null,
|
|
30825
|
-
kind: "unknown"
|
|
30826
|
-
};
|
|
30827
|
-
}
|
|
30828
|
-
if (value2.kind !== "known") {
|
|
30829
|
-
if (value2.guard === "conditional") {
|
|
30830
|
-
return {
|
|
30831
|
-
value: null,
|
|
30832
|
-
kind: "conditional"
|
|
30833
|
-
};
|
|
30834
|
-
}
|
|
30835
|
-
return {
|
|
30836
|
-
value: null,
|
|
30837
|
-
kind: "unknown"
|
|
30838
|
-
};
|
|
30839
|
-
}
|
|
30840
|
-
return {
|
|
30841
|
-
value: value2.px,
|
|
30842
|
-
kind: toEvidenceKind(value2)
|
|
30843
|
-
};
|
|
31031
|
+
if (value2.guard.kind === 1 /* Conditional */) return 2 /* Conditional */;
|
|
31032
|
+
if (value2.quality === "estimated") return 1 /* Interval */;
|
|
31033
|
+
return 0 /* Exact */;
|
|
30844
31034
|
}
|
|
30845
31035
|
function readNormalizedSignalEvidence(snapshot, name) {
|
|
30846
31036
|
const value2 = snapshot.signals.get(name);
|
|
30847
31037
|
if (!value2) {
|
|
30848
31038
|
return {
|
|
30849
31039
|
value: null,
|
|
30850
|
-
kind:
|
|
31040
|
+
kind: 3 /* Unknown */
|
|
30851
31041
|
};
|
|
30852
31042
|
}
|
|
30853
31043
|
if (value2.kind !== "known") {
|
|
30854
|
-
if (value2.guard ===
|
|
31044
|
+
if (value2.guard.kind === 1 /* Conditional */) {
|
|
30855
31045
|
return {
|
|
30856
31046
|
value: null,
|
|
30857
|
-
kind:
|
|
31047
|
+
kind: 2 /* Conditional */
|
|
30858
31048
|
};
|
|
30859
31049
|
}
|
|
30860
31050
|
return {
|
|
30861
31051
|
value: null,
|
|
30862
|
-
kind:
|
|
31052
|
+
kind: 3 /* Unknown */
|
|
30863
31053
|
};
|
|
30864
31054
|
}
|
|
30865
31055
|
return {
|
|
@@ -30870,7 +31060,7 @@ function readNormalizedSignalEvidence(snapshot, name) {
|
|
|
30870
31060
|
function readKnownSignal(snapshot, name) {
|
|
30871
31061
|
const value2 = readKnownSignalWithGuard(snapshot, name);
|
|
30872
31062
|
if (!value2) return null;
|
|
30873
|
-
if (value2.guard !==
|
|
31063
|
+
if (value2.guard.kind !== 0 /* Unconditional */) return null;
|
|
30874
31064
|
return value2;
|
|
30875
31065
|
}
|
|
30876
31066
|
function readKnownPx(snapshot, name) {
|
|
@@ -30904,19 +31094,19 @@ function hasEffectivePosition(snapshot) {
|
|
|
30904
31094
|
return position !== "static";
|
|
30905
31095
|
}
|
|
30906
31096
|
function readReservedSpaceFact(graph, node) {
|
|
30907
|
-
return graph.
|
|
31097
|
+
return graph.reservedSpaceFactsByNode.get(node) ?? EMPTY_LAYOUT_RESERVED_SPACE_FACT;
|
|
30908
31098
|
}
|
|
30909
31099
|
function readScrollContainerFact(graph, node) {
|
|
30910
|
-
return graph.
|
|
31100
|
+
return graph.scrollContainerFactsByNode.get(node) ?? EMPTY_LAYOUT_SCROLL_CONTAINER_FACT;
|
|
30911
31101
|
}
|
|
30912
31102
|
function readFlowParticipationFact(graph, node) {
|
|
30913
|
-
return graph.
|
|
31103
|
+
return graph.flowParticipationFactsByNode.get(node) ?? EMPTY_LAYOUT_FLOW_PARTICIPATION_FACT;
|
|
30914
31104
|
}
|
|
30915
31105
|
function readContainingBlockFact(graph, node) {
|
|
30916
|
-
return graph.
|
|
31106
|
+
return graph.containingBlockFactsByNode.get(node) ?? EMPTY_LAYOUT_CONTAINING_BLOCK_FACT;
|
|
30917
31107
|
}
|
|
30918
31108
|
function readConditionalSignalDeltaFact(graph, node, name) {
|
|
30919
|
-
const byProperty = graph.
|
|
31109
|
+
const byProperty = graph.conditionalSignalDeltaFactsByNode.get(node);
|
|
30920
31110
|
if (!byProperty) return EMPTY_LAYOUT_CONDITIONAL_DELTA_FACT;
|
|
30921
31111
|
return byProperty.get(name) ?? EMPTY_LAYOUT_CONDITIONAL_DELTA_FACT;
|
|
30922
31112
|
}
|
|
@@ -30944,7 +31134,7 @@ function readScrollContainerElements(graph) {
|
|
|
30944
31134
|
return graph.scrollContainerElements;
|
|
30945
31135
|
}
|
|
30946
31136
|
function readBaselineOffsetFacts(graph, node) {
|
|
30947
|
-
return graph.
|
|
31137
|
+
return graph.baselineOffsetFactsByNode.get(node) ?? EMPTY_BASELINE_FACTS;
|
|
30948
31138
|
}
|
|
30949
31139
|
function readElementRef(graph, node) {
|
|
30950
31140
|
return readElementRefById(graph, node.solidFile, node.elementId);
|
|
@@ -30966,7 +31156,6 @@ function readStatefulBaseValueIndex(graph) {
|
|
|
30966
31156
|
}
|
|
30967
31157
|
|
|
30968
31158
|
// src/cross-file/layout/context-classification.ts
|
|
30969
|
-
var WHITESPACE_RE3 = /\s+/;
|
|
30970
31159
|
var TABLE_SEMANTIC_TAGS = /* @__PURE__ */ new Set(["table", "thead", "tbody", "tfoot", "tr", "td", "th"]);
|
|
30971
31160
|
var TABLE_DISPLAY_VALUES = /* @__PURE__ */ new Set([
|
|
30972
31161
|
"table",
|
|
@@ -30983,7 +31172,6 @@ var TABLE_DISPLAY_VALUES = /* @__PURE__ */ new Set([
|
|
|
30983
31172
|
var FLEX_DISPLAY_VALUES = /* @__PURE__ */ new Set(["flex", "inline-flex"]);
|
|
30984
31173
|
var GRID_DISPLAY_VALUES = /* @__PURE__ */ new Set(["grid", "inline-grid"]);
|
|
30985
31174
|
var INLINE_DISPLAY_VALUES = /* @__PURE__ */ new Set(["inline", "inline-block", "inline-list-item"]);
|
|
30986
|
-
var DISPLAY_TOKEN_SPLIT_RE = /\s+/;
|
|
30987
31175
|
function createAlignmentContextForParent(parent, snapshot) {
|
|
30988
31176
|
const axis = resolveAxis(snapshot);
|
|
30989
31177
|
const inlineDirection = resolveInlineDirection(snapshot);
|
|
@@ -31006,6 +31194,7 @@ function createAlignmentContextForParent(parent, snapshot) {
|
|
|
31006
31194
|
const contextCertainty = combineCertainty(classified.certainty, axis.certainty);
|
|
31007
31195
|
const certainty = combineCertainty(contextCertainty, inlineDirection.certainty);
|
|
31008
31196
|
const baselineRelevance = computeBaselineRelevance(classified.kind, parentAlignItems, parentPlaceItems);
|
|
31197
|
+
const crossAxisInfo = resolveCrossAxisIsBlockAxis(classified.kind, snapshot, axis.value);
|
|
31009
31198
|
const out = {
|
|
31010
31199
|
kind: classified.kind,
|
|
31011
31200
|
certainty,
|
|
@@ -31021,6 +31210,8 @@ function createAlignmentContextForParent(parent, snapshot) {
|
|
|
31021
31210
|
parentAlignItems,
|
|
31022
31211
|
parentPlaceItems,
|
|
31023
31212
|
hasPositionedOffset: positionedOffset.hasPositionedOffset,
|
|
31213
|
+
crossAxisIsBlockAxis: crossAxisInfo.value,
|
|
31214
|
+
crossAxisIsBlockAxisCertainty: crossAxisInfo.certainty,
|
|
31024
31215
|
baselineRelevance,
|
|
31025
31216
|
evidence
|
|
31026
31217
|
};
|
|
@@ -31030,7 +31221,7 @@ function classifyKind(evidence) {
|
|
|
31030
31221
|
if (evidence.hasTableSemantics) {
|
|
31031
31222
|
return {
|
|
31032
31223
|
kind: "table-cell",
|
|
31033
|
-
certainty:
|
|
31224
|
+
certainty: 0 /* Resolved */
|
|
31034
31225
|
};
|
|
31035
31226
|
}
|
|
31036
31227
|
if (evidence.containerKind === "table") {
|
|
@@ -31117,7 +31308,7 @@ function resolveContainerKind(parentDisplay, certainty) {
|
|
|
31117
31308
|
certainty
|
|
31118
31309
|
};
|
|
31119
31310
|
}
|
|
31120
|
-
const tokens = display.split(
|
|
31311
|
+
const tokens = display.split(WHITESPACE_RE3);
|
|
31121
31312
|
if (tokens.length === 2) {
|
|
31122
31313
|
const outside = tokens[0];
|
|
31123
31314
|
const inside = tokens[1];
|
|
@@ -31167,7 +31358,7 @@ function resolveAxis(snapshot) {
|
|
|
31167
31358
|
if (!snapshot.signals.has("writing-mode")) {
|
|
31168
31359
|
return {
|
|
31169
31360
|
value: "horizontal-tb",
|
|
31170
|
-
certainty:
|
|
31361
|
+
certainty: 0 /* Resolved */
|
|
31171
31362
|
};
|
|
31172
31363
|
}
|
|
31173
31364
|
const writingMode = readNormalizedSignalEvidence(snapshot, "writing-mode");
|
|
@@ -31192,7 +31383,7 @@ function resolveInlineDirection(snapshot) {
|
|
|
31192
31383
|
if (!snapshot.signals.has("direction")) {
|
|
31193
31384
|
return {
|
|
31194
31385
|
value: "ltr",
|
|
31195
|
-
certainty:
|
|
31386
|
+
certainty: 0 /* Resolved */
|
|
31196
31387
|
};
|
|
31197
31388
|
}
|
|
31198
31389
|
const direction = readNormalizedSignalEvidence(snapshot, "direction");
|
|
@@ -31208,16 +31399,16 @@ function resolveInlineDirection(snapshot) {
|
|
|
31208
31399
|
};
|
|
31209
31400
|
}
|
|
31210
31401
|
function toContextCertainty(kind) {
|
|
31211
|
-
if (kind ===
|
|
31212
|
-
if (kind ===
|
|
31213
|
-
return
|
|
31402
|
+
if (kind === 0 /* Exact */) return 0 /* Resolved */;
|
|
31403
|
+
if (kind === 1 /* Interval */ || kind === 2 /* Conditional */) return 1 /* Conditional */;
|
|
31404
|
+
return 2 /* Unknown */;
|
|
31214
31405
|
}
|
|
31215
31406
|
function resolvePositionedOffset(snapshot) {
|
|
31216
31407
|
const position = readKnownSignalWithGuard(snapshot, "position");
|
|
31217
31408
|
if (!position) {
|
|
31218
31409
|
return {
|
|
31219
31410
|
hasPositionedOffset: false,
|
|
31220
|
-
certainty:
|
|
31411
|
+
certainty: 2 /* Unknown */
|
|
31221
31412
|
};
|
|
31222
31413
|
}
|
|
31223
31414
|
const certainty = resolveSignalCertainty(position);
|
|
@@ -31232,15 +31423,33 @@ function resolvePositionedOffset(snapshot) {
|
|
|
31232
31423
|
certainty
|
|
31233
31424
|
};
|
|
31234
31425
|
}
|
|
31426
|
+
var FLEX_ROW_VALUES = /* @__PURE__ */ new Set(["row", "row-reverse"]);
|
|
31427
|
+
function resolveCrossAxisIsBlockAxis(kind, snapshot, _axis) {
|
|
31428
|
+
if (kind !== "flex-cross-axis" && kind !== "grid-cross-axis") {
|
|
31429
|
+
return { value: true, certainty: 0 /* Resolved */ };
|
|
31430
|
+
}
|
|
31431
|
+
if (kind === "flex-cross-axis") {
|
|
31432
|
+
const signal2 = readKnownSignalWithGuard(snapshot, "flex-direction");
|
|
31433
|
+
if (!signal2) {
|
|
31434
|
+
return { value: true, certainty: 0 /* Resolved */ };
|
|
31435
|
+
}
|
|
31436
|
+
const certainty2 = resolveSignalCertainty(signal2);
|
|
31437
|
+
return { value: FLEX_ROW_VALUES.has(signal2.normalized), certainty: certainty2 };
|
|
31438
|
+
}
|
|
31439
|
+
const signal = readKnownSignalWithGuard(snapshot, "grid-auto-flow");
|
|
31440
|
+
if (!signal) {
|
|
31441
|
+
return { value: true, certainty: 0 /* Resolved */ };
|
|
31442
|
+
}
|
|
31443
|
+
const certainty = resolveSignalCertainty(signal);
|
|
31444
|
+
return { value: !signal.normalized.startsWith("column"), certainty };
|
|
31445
|
+
}
|
|
31235
31446
|
function resolveSignalCertainty(value2) {
|
|
31236
|
-
if (!value2) return
|
|
31237
|
-
if (value2.guard ===
|
|
31238
|
-
return
|
|
31447
|
+
if (!value2) return 2 /* Unknown */;
|
|
31448
|
+
if (value2.guard.kind === 1 /* Conditional */) return 1 /* Conditional */;
|
|
31449
|
+
return 0 /* Resolved */;
|
|
31239
31450
|
}
|
|
31240
31451
|
function combineCertainty(left, right) {
|
|
31241
|
-
|
|
31242
|
-
if (left === "conditional" || right === "conditional") return "conditional";
|
|
31243
|
-
return "resolved";
|
|
31452
|
+
return left > right ? left : right;
|
|
31244
31453
|
}
|
|
31245
31454
|
var FLEX_GRID_GEOMETRIC_ALIGN_ITEMS = /* @__PURE__ */ new Set([
|
|
31246
31455
|
"center",
|
|
@@ -31279,24 +31488,7 @@ function finalizeTableCellBaselineRelevance(contextByParentNode, cohortVerticalA
|
|
|
31279
31488
|
if (context.kind !== "table-cell") continue;
|
|
31280
31489
|
if (consensusValue === null) continue;
|
|
31281
31490
|
if (!TABLE_CELL_GEOMETRIC_VERTICAL_ALIGN.has(consensusValue)) continue;
|
|
31282
|
-
contextByParentNode.set(parent, {
|
|
31283
|
-
kind: context.kind,
|
|
31284
|
-
certainty: context.certainty,
|
|
31285
|
-
parentSolidFile: context.parentSolidFile,
|
|
31286
|
-
parentElementId: context.parentElementId,
|
|
31287
|
-
parentElementKey: context.parentElementKey,
|
|
31288
|
-
parentTag: context.parentTag,
|
|
31289
|
-
axis: context.axis,
|
|
31290
|
-
axisCertainty: context.axisCertainty,
|
|
31291
|
-
inlineDirection: context.inlineDirection,
|
|
31292
|
-
inlineDirectionCertainty: context.inlineDirectionCertainty,
|
|
31293
|
-
parentDisplay: context.parentDisplay,
|
|
31294
|
-
parentAlignItems: context.parentAlignItems,
|
|
31295
|
-
parentPlaceItems: context.parentPlaceItems,
|
|
31296
|
-
hasPositionedOffset: context.hasPositionedOffset,
|
|
31297
|
-
baselineRelevance: "irrelevant",
|
|
31298
|
-
evidence: context.evidence
|
|
31299
|
-
});
|
|
31491
|
+
contextByParentNode.set(parent, deriveAlignmentContext(context, { baselineRelevance: "irrelevant" }));
|
|
31300
31492
|
}
|
|
31301
31493
|
}
|
|
31302
31494
|
|
|
@@ -31843,6 +32035,20 @@ function collectTransitiveCSSScope(entryPath, resolver, cssFilesByNormalizedPath
|
|
|
31843
32035
|
}
|
|
31844
32036
|
|
|
31845
32037
|
// src/cross-file/layout/perf.ts
|
|
32038
|
+
function createReservoir(capacity) {
|
|
32039
|
+
return { buffer: [], count: 0, capacity };
|
|
32040
|
+
}
|
|
32041
|
+
function reservoirPush(r, value2) {
|
|
32042
|
+
r.count++;
|
|
32043
|
+
if (r.buffer.length < r.capacity) {
|
|
32044
|
+
r.buffer.push(value2);
|
|
32045
|
+
return;
|
|
32046
|
+
}
|
|
32047
|
+
const j = Math.floor(Math.random() * r.count);
|
|
32048
|
+
if (j < r.capacity) {
|
|
32049
|
+
r.buffer[j] = value2;
|
|
32050
|
+
}
|
|
32051
|
+
}
|
|
31846
32052
|
var EMPTY_STATS = {
|
|
31847
32053
|
elementsScanned: 0,
|
|
31848
32054
|
selectorCandidatesChecked: 0,
|
|
@@ -31899,7 +32105,7 @@ function createLayoutPerfStats() {
|
|
|
31899
32105
|
cohortUnimodalFalse: 0,
|
|
31900
32106
|
factorCoverageSum: 0,
|
|
31901
32107
|
factorCoverageCount: 0,
|
|
31902
|
-
posteriorWidths:
|
|
32108
|
+
posteriorWidths: createReservoir(200),
|
|
31903
32109
|
uncertaintyEscalations: 0,
|
|
31904
32110
|
signalSnapshotsBuilt: 0,
|
|
31905
32111
|
signalSnapshotCacheHits: 0,
|
|
@@ -31964,14 +32170,12 @@ function maybeLogLayoutPerf(stats, log) {
|
|
|
31964
32170
|
`[layout] elements=${view.elementsScanned} candidates=${view.selectorCandidatesChecked} compiledSelectors=${view.compiledSelectorCount} unsupportedSelectors=${view.selectorsRejectedUnsupported} conditionalSelectors=${view.selectorsGuardedConditional} ancestryChecks=${view.ancestryChecks} edges=${view.matchEdgesCreated} collected=${view.casesCollected} cases=${view.casesScored} rejectLowEvidence=${view.casesRejectedLowEvidence} rejectThreshold=${view.casesRejectedThreshold} rejectUndecidable=${view.casesRejectedUndecidable} rejectIdentifiability=${view.casesRejectedIdentifiability} undecidableInterval=${view.undecidableInterval} conditionalSignalRatio=${Math.round(view.conditionalSignalRatio * 1e3) / 1e3} conditionalSignals=${view.conditionalSignals} totalSignals=${view.totalSignals} cohortUnimodalFalse=${view.cohortUnimodalFalse} factorCoverageMean=${Math.round(view.factorCoverageMean * 1e3) / 1e3} posteriorWidthP95=${Math.round(view.posteriorWidthP95 * 1e3) / 1e3} uncertaintyEscalations=${view.uncertaintyEscalations} snapshots=${view.signalSnapshotsBuilt} snapshotHits=${view.signalSnapshotCacheHits} measurementIndexHits=${view.measurementIndexHits} contexts=${view.contextsClassified} diagnostics=${view.diagnosticsEmitted} selectorIndexMs=${Math.round(view.selectorIndexMs * 100) / 100} selectorMatchMs=${Math.round(view.selectorMatchMs * 100) / 100} cascadeBuildMs=${Math.round(view.cascadeBuildMs * 100) / 100} caseBuildMs=${Math.round(view.caseBuildMs * 100) / 100} scoringMs=${Math.round(view.scoringMs * 100) / 100} elapsedMs=${Math.round(view.elapsedMs * 100) / 100}`
|
|
31965
32171
|
);
|
|
31966
32172
|
}
|
|
31967
|
-
function computeP95(
|
|
31968
|
-
if (
|
|
31969
|
-
const
|
|
31970
|
-
|
|
31971
|
-
const
|
|
31972
|
-
|
|
31973
|
-
if (index >= sorted.length) return sorted[sorted.length - 1] ?? 0;
|
|
31974
|
-
return sorted[index] ?? 0;
|
|
32173
|
+
function computeP95(sampler) {
|
|
32174
|
+
if (sampler.buffer.length === 0) return 0;
|
|
32175
|
+
const scratch = [...sampler.buffer];
|
|
32176
|
+
const index = Math.ceil(scratch.length * 0.95) - 1;
|
|
32177
|
+
const clamped = index <= 0 ? 0 : index >= scratch.length ? scratch.length - 1 : index;
|
|
32178
|
+
return selectKth(scratch, clamped);
|
|
31975
32179
|
}
|
|
31976
32180
|
|
|
31977
32181
|
// src/cross-file/layout/component-host.ts
|
|
@@ -33941,16 +34145,16 @@ function includesAttributeWord(value2, word) {
|
|
|
33941
34145
|
|
|
33942
34146
|
// src/cross-file/layout/guard-model.ts
|
|
33943
34147
|
var UNCONDITIONAL_GUARD = {
|
|
33944
|
-
kind:
|
|
34148
|
+
kind: 0 /* Unconditional */,
|
|
33945
34149
|
conditions: [],
|
|
33946
34150
|
key: "always"
|
|
33947
34151
|
};
|
|
33948
|
-
var
|
|
34152
|
+
var WHITESPACE_RE_GLOBAL = /\s+/g;
|
|
33949
34153
|
function resolveRuleGuard(rule) {
|
|
33950
34154
|
const conditions = collectRuleConditions(rule);
|
|
33951
34155
|
if (conditions.length === 0) return UNCONDITIONAL_GUARD;
|
|
33952
34156
|
return {
|
|
33953
|
-
kind:
|
|
34157
|
+
kind: 1 /* Conditional */,
|
|
33954
34158
|
conditions,
|
|
33955
34159
|
key: conditions.map((condition) => condition.key).join("&")
|
|
33956
34160
|
};
|
|
@@ -34004,7 +34208,7 @@ function buildCondition(kind, query) {
|
|
|
34004
34208
|
}
|
|
34005
34209
|
function normalizeQuery(query) {
|
|
34006
34210
|
if (query === null) return null;
|
|
34007
|
-
const normalized = query.trim().toLowerCase().replace(
|
|
34211
|
+
const normalized = query.trim().toLowerCase().replace(WHITESPACE_RE_GLOBAL, " ");
|
|
34008
34212
|
if (normalized.length === 0) return null;
|
|
34009
34213
|
return normalized;
|
|
34010
34214
|
}
|
|
@@ -34074,7 +34278,7 @@ function summarizeSignalFacts(snapshots) {
|
|
|
34074
34278
|
}
|
|
34075
34279
|
function accumulateSnapshotFacts(snapshot, sink) {
|
|
34076
34280
|
for (const value2 of snapshot.signals.values()) {
|
|
34077
|
-
if (value2.guard ===
|
|
34281
|
+
if (value2.guard.kind === 1 /* Conditional */) {
|
|
34078
34282
|
sink.addConditional();
|
|
34079
34283
|
continue;
|
|
34080
34284
|
}
|
|
@@ -34268,15 +34472,6 @@ function assertUnitInterval(name, value2) {
|
|
|
34268
34472
|
}
|
|
34269
34473
|
|
|
34270
34474
|
// src/cross-file/layout/content-composition.ts
|
|
34271
|
-
var INTRINSIC_REPLACED_TAGS = /* @__PURE__ */ new Set([
|
|
34272
|
-
"img",
|
|
34273
|
-
"svg",
|
|
34274
|
-
"video",
|
|
34275
|
-
"canvas",
|
|
34276
|
-
"iframe",
|
|
34277
|
-
"object",
|
|
34278
|
-
"embed"
|
|
34279
|
-
]);
|
|
34280
34475
|
var BLOCK_FORMATTING_CONTEXT_DISPLAYS = /* @__PURE__ */ new Set([
|
|
34281
34476
|
"block",
|
|
34282
34477
|
"flex",
|
|
@@ -34310,7 +34505,7 @@ var VERTICAL_ALIGN_MITIGATIONS = /* @__PURE__ */ new Set([
|
|
|
34310
34505
|
"text-top",
|
|
34311
34506
|
"text-bottom"
|
|
34312
34507
|
]);
|
|
34313
|
-
function computeContentCompositionFingerprint(elementNode, childrenByParentNode, snapshotByElementNode,
|
|
34508
|
+
function computeContentCompositionFingerprint(elementNode, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode) {
|
|
34314
34509
|
const state = {
|
|
34315
34510
|
hasTextContent: false,
|
|
34316
34511
|
hasInlineReplaced: false,
|
|
@@ -34324,10 +34519,10 @@ function computeContentCompositionFingerprint(elementNode, childrenByParentNode,
|
|
|
34324
34519
|
blockChildCount: 0,
|
|
34325
34520
|
inlineChildCount: 0
|
|
34326
34521
|
};
|
|
34327
|
-
if (elementNode.textualContent ===
|
|
34522
|
+
if (elementNode.textualContent === 0 /* Yes */ || elementNode.textualContent === 3 /* DynamicText */) {
|
|
34328
34523
|
state.hasTextContent = true;
|
|
34329
34524
|
}
|
|
34330
|
-
const elementHotSignals =
|
|
34525
|
+
const elementHotSignals = snapshotHotSignalsByNode.get(elementNode);
|
|
34331
34526
|
const elementDisplay = elementHotSignals?.display.value ?? null;
|
|
34332
34527
|
if (elementDisplay !== null && establishesFormattingContext(elementDisplay)) {
|
|
34333
34528
|
return {
|
|
@@ -34338,7 +34533,7 @@ function computeContentCompositionFingerprint(elementNode, childrenByParentNode,
|
|
|
34338
34533
|
wrappingContextMitigates: false,
|
|
34339
34534
|
hasVerticalAlignMitigation: false,
|
|
34340
34535
|
mixedContentDepth: 0,
|
|
34341
|
-
classification:
|
|
34536
|
+
classification: 4 /* BlockSegmented */,
|
|
34342
34537
|
analyzableChildCount: 0,
|
|
34343
34538
|
totalChildCount: 0,
|
|
34344
34539
|
hasOnlyBlockChildren: false
|
|
@@ -34348,7 +34543,7 @@ function computeContentCompositionFingerprint(elementNode, childrenByParentNode,
|
|
|
34348
34543
|
elementNode,
|
|
34349
34544
|
childrenByParentNode,
|
|
34350
34545
|
snapshotByElementNode,
|
|
34351
|
-
|
|
34546
|
+
snapshotHotSignalsByNode,
|
|
34352
34547
|
state,
|
|
34353
34548
|
0
|
|
34354
34549
|
);
|
|
@@ -34368,7 +34563,7 @@ function computeContentCompositionFingerprint(elementNode, childrenByParentNode,
|
|
|
34368
34563
|
hasOnlyBlockChildren
|
|
34369
34564
|
};
|
|
34370
34565
|
}
|
|
34371
|
-
function walkInlineDescendants(node, childrenByParentNode, snapshotByElementNode,
|
|
34566
|
+
function walkInlineDescendants(node, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode, state, depth) {
|
|
34372
34567
|
const children = childrenByParentNode.get(node);
|
|
34373
34568
|
if (!children) return;
|
|
34374
34569
|
for (let i = 0; i < children.length; i++) {
|
|
@@ -34379,7 +34574,7 @@ function walkInlineDescendants(node, childrenByParentNode, snapshotByElementNode
|
|
|
34379
34574
|
if (!snapshot) continue;
|
|
34380
34575
|
if (depth === 0) state.analyzableChildCount++;
|
|
34381
34576
|
const childTag = child.tagName?.toLowerCase() ?? null;
|
|
34382
|
-
const hotSignals =
|
|
34577
|
+
const hotSignals = snapshotHotSignalsByNode.get(child);
|
|
34383
34578
|
const childDisplay = hotSignals?.display.value ?? null;
|
|
34384
34579
|
if (childTag !== null && (isIntrinsicReplacedTag(childTag) || isControlReplacedTag(childTag))) {
|
|
34385
34580
|
state.hasInlineReplaced = true;
|
|
@@ -34401,16 +34596,16 @@ function walkInlineDescendants(node, childrenByParentNode, snapshotByElementNode
|
|
|
34401
34596
|
checkVerticalAlignMitigation(snapshot, state);
|
|
34402
34597
|
updateMixedContentDepth(state, depth);
|
|
34403
34598
|
if (depth === 0) state.inlineChildCount++;
|
|
34404
|
-
const parentHotSignals =
|
|
34599
|
+
const parentHotSignals = snapshotHotSignalsByNode.get(node);
|
|
34405
34600
|
const parentDisplay = parentHotSignals?.display.value ?? null;
|
|
34406
34601
|
if (parentDisplay !== null && isAlignmentContextWithNonBaselineAlignment(parentDisplay, parentHotSignals)) {
|
|
34407
34602
|
state.wrappingContextMitigates = true;
|
|
34408
|
-
} else if (isAlignmentContextWithNonBaselineAlignment(childDisplay, hotSignals) && containsMixedContent(child, childrenByParentNode, snapshotByElementNode,
|
|
34603
|
+
} else if (isAlignmentContextWithNonBaselineAlignment(childDisplay, hotSignals) && containsMixedContent(child, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode)) {
|
|
34409
34604
|
state.wrappingContextMitigates = true;
|
|
34410
34605
|
}
|
|
34411
34606
|
continue;
|
|
34412
34607
|
}
|
|
34413
|
-
if (child.textualContent ===
|
|
34608
|
+
if (child.textualContent === 0 /* Yes */ || child.textualContent === 3 /* DynamicText */) {
|
|
34414
34609
|
state.hasTextContent = true;
|
|
34415
34610
|
}
|
|
34416
34611
|
checkHeightContributions(snapshot, state);
|
|
@@ -34420,7 +34615,7 @@ function walkInlineDescendants(node, childrenByParentNode, snapshotByElementNode
|
|
|
34420
34615
|
child,
|
|
34421
34616
|
childrenByParentNode,
|
|
34422
34617
|
snapshotByElementNode,
|
|
34423
|
-
|
|
34618
|
+
snapshotHotSignalsByNode,
|
|
34424
34619
|
state,
|
|
34425
34620
|
depth + 1
|
|
34426
34621
|
);
|
|
@@ -34455,19 +34650,19 @@ function isAlignmentContextWithNonBaselineAlignment(display, hotSignals) {
|
|
|
34455
34650
|
if (alignItems === null) return false;
|
|
34456
34651
|
return alignItems !== "baseline";
|
|
34457
34652
|
}
|
|
34458
|
-
function containsMixedContent(node, childrenByParentNode, snapshotByElementNode,
|
|
34459
|
-
const hasText = node.textualContent ===
|
|
34653
|
+
function containsMixedContent(node, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode) {
|
|
34654
|
+
const hasText = node.textualContent === 0 /* Yes */ || node.textualContent === 3 /* DynamicText */;
|
|
34460
34655
|
const hasReplaced = false;
|
|
34461
|
-
return scanMixedContent(node, childrenByParentNode, snapshotByElementNode,
|
|
34656
|
+
return scanMixedContent(node, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode, { hasText, hasReplaced });
|
|
34462
34657
|
}
|
|
34463
|
-
function scanMixedContent(node, childrenByParentNode, snapshotByElementNode,
|
|
34658
|
+
function scanMixedContent(node, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode, found) {
|
|
34464
34659
|
const children = childrenByParentNode.get(node);
|
|
34465
34660
|
if (!children) return false;
|
|
34466
34661
|
for (let i = 0; i < children.length; i++) {
|
|
34467
34662
|
const child = children[i];
|
|
34468
34663
|
if (!child) continue;
|
|
34469
34664
|
const childTag = child.tagName?.toLowerCase() ?? null;
|
|
34470
|
-
const hotSignals =
|
|
34665
|
+
const hotSignals = snapshotHotSignalsByNode.get(child);
|
|
34471
34666
|
const childDisplay = hotSignals?.display.value ?? null;
|
|
34472
34667
|
if (childTag !== null && (isIntrinsicReplacedTag(childTag) || isControlReplacedTag(childTag))) {
|
|
34473
34668
|
found.hasReplaced = true;
|
|
@@ -34482,12 +34677,12 @@ function scanMixedContent(node, childrenByParentNode, snapshotByElementNode, sna
|
|
|
34482
34677
|
if (found.hasText) return true;
|
|
34483
34678
|
continue;
|
|
34484
34679
|
}
|
|
34485
|
-
if (child.textualContent ===
|
|
34680
|
+
if (child.textualContent === 0 /* Yes */ || child.textualContent === 3 /* DynamicText */) {
|
|
34486
34681
|
found.hasText = true;
|
|
34487
34682
|
if (found.hasReplaced) return true;
|
|
34488
34683
|
}
|
|
34489
34684
|
if (childDisplay === null || isInlineContinuationDisplay(childDisplay)) {
|
|
34490
|
-
if (scanMixedContent(child, childrenByParentNode, snapshotByElementNode,
|
|
34685
|
+
if (scanMixedContent(child, childrenByParentNode, snapshotByElementNode, snapshotHotSignalsByNode, found)) {
|
|
34491
34686
|
return true;
|
|
34492
34687
|
}
|
|
34493
34688
|
}
|
|
@@ -34510,30 +34705,30 @@ function updateMixedContentDepth(state, depth) {
|
|
|
34510
34705
|
}
|
|
34511
34706
|
function classifyFromState(state, elementNode, hasOnlyBlockChildren) {
|
|
34512
34707
|
if (hasOnlyBlockChildren) {
|
|
34513
|
-
return
|
|
34708
|
+
return 4 /* BlockSegmented */;
|
|
34514
34709
|
}
|
|
34515
34710
|
if (state.totalChildCount === 0 && !state.hasTextContent) {
|
|
34516
|
-
if (elementNode.textualContent ===
|
|
34517
|
-
if (elementNode.textualContent ===
|
|
34518
|
-
return
|
|
34711
|
+
if (elementNode.textualContent === 2 /* Unknown */) return 5 /* Unknown */;
|
|
34712
|
+
if (elementNode.textualContent === 0 /* Yes */ || elementNode.textualContent === 3 /* DynamicText */) {
|
|
34713
|
+
return 0 /* TextOnly */;
|
|
34519
34714
|
}
|
|
34520
|
-
return
|
|
34715
|
+
return 5 /* Unknown */;
|
|
34521
34716
|
}
|
|
34522
34717
|
if (state.analyzableChildCount === 0 && state.totalChildCount > 0) {
|
|
34523
|
-
return
|
|
34718
|
+
return 5 /* Unknown */;
|
|
34524
34719
|
}
|
|
34525
34720
|
if (state.hasTextContent && state.hasInlineReplaced) {
|
|
34526
|
-
if (state.wrappingContextMitigates) return
|
|
34527
|
-
if (state.hasVerticalAlignMitigation) return
|
|
34528
|
-
return
|
|
34721
|
+
if (state.wrappingContextMitigates) return 3 /* MixedMitigated */;
|
|
34722
|
+
if (state.hasVerticalAlignMitigation) return 3 /* MixedMitigated */;
|
|
34723
|
+
return 2 /* MixedUnmitigated */;
|
|
34529
34724
|
}
|
|
34530
34725
|
if (!state.hasTextContent && state.hasInlineReplaced) {
|
|
34531
|
-
return
|
|
34726
|
+
return 1 /* ReplacedOnly */;
|
|
34532
34727
|
}
|
|
34533
34728
|
if (state.hasTextContent && !state.hasInlineReplaced) {
|
|
34534
|
-
return
|
|
34729
|
+
return 0 /* TextOnly */;
|
|
34535
34730
|
}
|
|
34536
|
-
return
|
|
34731
|
+
return 5 /* Unknown */;
|
|
34537
34732
|
}
|
|
34538
34733
|
function isIntrinsicReplacedTag(tag) {
|
|
34539
34734
|
return INTRINSIC_REPLACED_TAGS.has(tag);
|
|
@@ -34553,10 +34748,14 @@ function isInlineReplacedDisplay(display) {
|
|
|
34553
34748
|
function isInlineContinuationDisplay(display) {
|
|
34554
34749
|
return INLINE_CONTINUATION_DISPLAYS.has(display);
|
|
34555
34750
|
}
|
|
34556
|
-
|
|
34557
|
-
|
|
34751
|
+
var NO_DIVERGENCE = Object.freeze({
|
|
34752
|
+
strength: 0,
|
|
34753
|
+
majorityClassification: 5 /* Unknown */
|
|
34754
|
+
});
|
|
34755
|
+
function resolveCompositionDivergence(subjectFingerprint, allFingerprints, parentContext) {
|
|
34756
|
+
if (allFingerprints.length < 2) return NO_DIVERGENCE;
|
|
34558
34757
|
if (parentContext !== null && !hasSharedBaselineAlignment(parentContext)) {
|
|
34559
|
-
return
|
|
34758
|
+
return NO_DIVERGENCE;
|
|
34560
34759
|
}
|
|
34561
34760
|
const countByClassification = /* @__PURE__ */ new Map();
|
|
34562
34761
|
for (let i = 0; i < allFingerprints.length; i++) {
|
|
@@ -34568,10 +34767,7 @@ function resolveCompositionDivergenceStrength(subjectFingerprint, allFingerprint
|
|
|
34568
34767
|
}
|
|
34569
34768
|
const subjectNormalized = normalizeClassificationForComparison(subjectFingerprint.classification);
|
|
34570
34769
|
const subjectCount = countByClassification.get(subjectNormalized) ?? 0;
|
|
34571
|
-
|
|
34572
|
-
return resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints);
|
|
34573
|
-
}
|
|
34574
|
-
let majorityClassification = "unknown";
|
|
34770
|
+
let majorityClassification = 5 /* Unknown */;
|
|
34575
34771
|
let majorityCount = 0;
|
|
34576
34772
|
for (const [classification, count] of countByClassification) {
|
|
34577
34773
|
if (count > majorityCount) {
|
|
@@ -34579,35 +34775,38 @@ function resolveCompositionDivergenceStrength(subjectFingerprint, allFingerprint
|
|
|
34579
34775
|
majorityClassification = classification;
|
|
34580
34776
|
}
|
|
34581
34777
|
}
|
|
34778
|
+
if (subjectCount === allFingerprints.length) {
|
|
34779
|
+
return { strength: resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints), majorityClassification };
|
|
34780
|
+
}
|
|
34582
34781
|
if (subjectNormalized === majorityClassification) {
|
|
34583
|
-
return resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints);
|
|
34782
|
+
return { strength: resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints), majorityClassification };
|
|
34584
34783
|
}
|
|
34585
|
-
if (subjectNormalized ===
|
|
34586
|
-
return 0;
|
|
34784
|
+
if (subjectNormalized === 5 /* Unknown */) {
|
|
34785
|
+
return { strength: 0, majorityClassification };
|
|
34587
34786
|
}
|
|
34588
34787
|
const cal = alignmentStrengthCalibration;
|
|
34589
|
-
if (majorityClassification ===
|
|
34590
|
-
return cal.compositionMixedUnmitigatedOutlierStrength;
|
|
34788
|
+
if (majorityClassification === 0 /* TextOnly */ && subjectNormalized === 2 /* MixedUnmitigated */) {
|
|
34789
|
+
return { strength: cal.compositionMixedUnmitigatedOutlierStrength, majorityClassification };
|
|
34591
34790
|
}
|
|
34592
|
-
if (majorityClassification ===
|
|
34593
|
-
return cal.compositionMixedOutlierAmongReplacedStrength;
|
|
34791
|
+
if (majorityClassification === 1 /* ReplacedOnly */ && subjectNormalized === 2 /* MixedUnmitigated */) {
|
|
34792
|
+
return { strength: cal.compositionMixedOutlierAmongReplacedStrength, majorityClassification };
|
|
34594
34793
|
}
|
|
34595
|
-
if (majorityClassification ===
|
|
34596
|
-
return cal.compositionTextOutlierAmongMixedStrength;
|
|
34794
|
+
if (majorityClassification === 2 /* MixedUnmitigated */ && subjectNormalized === 0 /* TextOnly */) {
|
|
34795
|
+
return { strength: cal.compositionTextOutlierAmongMixedStrength, majorityClassification };
|
|
34597
34796
|
}
|
|
34598
|
-
if (majorityClassification ===
|
|
34599
|
-
return cal.compositionTextOutlierAmongMixedStrength;
|
|
34797
|
+
if (majorityClassification === 2 /* MixedUnmitigated */ && subjectNormalized === 1 /* ReplacedOnly */) {
|
|
34798
|
+
return { strength: cal.compositionTextOutlierAmongMixedStrength, majorityClassification };
|
|
34600
34799
|
}
|
|
34601
|
-
if (majorityClassification ===
|
|
34602
|
-
return cal.compositionMixedOutlierAmongReplacedStrength;
|
|
34800
|
+
if (majorityClassification === 0 /* TextOnly */ && subjectNormalized === 1 /* ReplacedOnly */) {
|
|
34801
|
+
return { strength: cal.compositionMixedOutlierAmongReplacedStrength, majorityClassification };
|
|
34603
34802
|
}
|
|
34604
|
-
if (majorityClassification ===
|
|
34605
|
-
return cal.compositionTextOutlierAmongMixedStrength;
|
|
34803
|
+
if (majorityClassification === 1 /* ReplacedOnly */ && subjectNormalized === 0 /* TextOnly */) {
|
|
34804
|
+
return { strength: cal.compositionTextOutlierAmongMixedStrength, majorityClassification };
|
|
34606
34805
|
}
|
|
34607
|
-
if (majorityClassification ===
|
|
34608
|
-
return 0;
|
|
34806
|
+
if (majorityClassification === 5 /* Unknown */) {
|
|
34807
|
+
return { strength: 0, majorityClassification };
|
|
34609
34808
|
}
|
|
34610
|
-
return cal.compositionUnknownPenalty;
|
|
34809
|
+
return { strength: cal.compositionUnknownPenalty, majorityClassification };
|
|
34611
34810
|
}
|
|
34612
34811
|
function resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints) {
|
|
34613
34812
|
if (subjectFingerprint.inlineReplacedKind === null) return 0;
|
|
@@ -34628,28 +34827,9 @@ function resolveInlineReplacedKindDivergence(subjectFingerprint, allFingerprints
|
|
|
34628
34827
|
function hasSharedBaselineAlignment(context) {
|
|
34629
34828
|
return context.baselineRelevance === "relevant";
|
|
34630
34829
|
}
|
|
34631
|
-
function resolveMajorityClassification(allFingerprints) {
|
|
34632
|
-
const countByClassification = /* @__PURE__ */ new Map();
|
|
34633
|
-
for (let i = 0; i < allFingerprints.length; i++) {
|
|
34634
|
-
const fp = allFingerprints[i];
|
|
34635
|
-
if (!fp) continue;
|
|
34636
|
-
const normalized = normalizeClassificationForComparison(fp.classification);
|
|
34637
|
-
const existing = countByClassification.get(normalized) ?? 0;
|
|
34638
|
-
countByClassification.set(normalized, existing + 1);
|
|
34639
|
-
}
|
|
34640
|
-
let majorityClassification = "unknown";
|
|
34641
|
-
let majorityCount = 0;
|
|
34642
|
-
for (const [classification, count] of countByClassification) {
|
|
34643
|
-
if (count > majorityCount) {
|
|
34644
|
-
majorityCount = count;
|
|
34645
|
-
majorityClassification = classification;
|
|
34646
|
-
}
|
|
34647
|
-
}
|
|
34648
|
-
return majorityClassification;
|
|
34649
|
-
}
|
|
34650
34830
|
function normalizeClassificationForComparison(classification) {
|
|
34651
|
-
if (classification ===
|
|
34652
|
-
if (classification ===
|
|
34831
|
+
if (classification === 3 /* MixedMitigated */) return 0 /* TextOnly */;
|
|
34832
|
+
if (classification === 4 /* BlockSegmented */) return 0 /* TextOnly */;
|
|
34653
34833
|
return classification;
|
|
34654
34834
|
}
|
|
34655
34835
|
function resolveCompositionCoverage(subjectFingerprint, allFingerprints) {
|
|
@@ -34657,12 +34837,12 @@ function resolveCompositionCoverage(subjectFingerprint, allFingerprints) {
|
|
|
34657
34837
|
let analyzableCount = 0;
|
|
34658
34838
|
for (let i = 0; i < allFingerprints.length; i++) {
|
|
34659
34839
|
const fp = allFingerprints[i];
|
|
34660
|
-
if (fp && fp.classification !==
|
|
34840
|
+
if (fp && fp.classification !== 5 /* Unknown */) {
|
|
34661
34841
|
analyzableCount++;
|
|
34662
34842
|
}
|
|
34663
34843
|
}
|
|
34664
34844
|
const analyzableShare = analyzableCount / allFingerprints.length;
|
|
34665
|
-
if (subjectFingerprint.classification ===
|
|
34845
|
+
if (subjectFingerprint.classification === 5 /* Unknown */) {
|
|
34666
34846
|
return analyzableShare * 0.3;
|
|
34667
34847
|
}
|
|
34668
34848
|
if (subjectFingerprint.totalChildCount > 0 && subjectFingerprint.analyzableChildCount === 0) {
|
|
@@ -34670,24 +34850,19 @@ function resolveCompositionCoverage(subjectFingerprint, allFingerprints) {
|
|
|
34670
34850
|
}
|
|
34671
34851
|
return analyzableShare;
|
|
34672
34852
|
}
|
|
34853
|
+
var COMPOSITION_LABELS = {
|
|
34854
|
+
[0 /* TextOnly */]: "text-only",
|
|
34855
|
+
[1 /* ReplacedOnly */]: "inline-replaced-only",
|
|
34856
|
+
[2 /* MixedUnmitigated */]: "mixed text + inline-replaced",
|
|
34857
|
+
[3 /* MixedMitigated */]: "mixed (alignment mitigated)",
|
|
34858
|
+
[4 /* BlockSegmented */]: "block-segmented",
|
|
34859
|
+
[5 /* Unknown */]: "unknown"
|
|
34860
|
+
};
|
|
34673
34861
|
function formatCompositionClassification(classification) {
|
|
34674
|
-
|
|
34675
|
-
case "text-only":
|
|
34676
|
-
return "text-only";
|
|
34677
|
-
case "replaced-only":
|
|
34678
|
-
return "inline-replaced-only";
|
|
34679
|
-
case "mixed-unmitigated":
|
|
34680
|
-
return "mixed text + inline-replaced";
|
|
34681
|
-
case "mixed-mitigated":
|
|
34682
|
-
return "mixed (alignment mitigated)";
|
|
34683
|
-
case "block-segmented":
|
|
34684
|
-
return "block-segmented";
|
|
34685
|
-
case "unknown":
|
|
34686
|
-
return "unknown";
|
|
34687
|
-
}
|
|
34862
|
+
return COMPOSITION_LABELS[classification];
|
|
34688
34863
|
}
|
|
34689
34864
|
function formatCompositionFixSuggestion(subjectFingerprint) {
|
|
34690
|
-
if (subjectFingerprint.classification ===
|
|
34865
|
+
if (subjectFingerprint.classification === 2 /* MixedUnmitigated */) {
|
|
34691
34866
|
if (subjectFingerprint.hasVerticalAlignMitigation) {
|
|
34692
34867
|
return "verify vertical-align resolves the baseline shift";
|
|
34693
34868
|
}
|
|
@@ -34722,12 +34897,12 @@ function estimateBlockOffsetWithDeclaredFromHotSignals(hot, axis) {
|
|
|
34722
34897
|
function estimateBlockOffsetWithDeclaredFromSources(axis, position, readNumeric) {
|
|
34723
34898
|
let declaredTotal = 0;
|
|
34724
34899
|
let declaredCount = 0;
|
|
34725
|
-
let declaredKind =
|
|
34726
|
-
let declaredMissingKind =
|
|
34900
|
+
let declaredKind = 0 /* Exact */;
|
|
34901
|
+
let declaredMissingKind = 0 /* Exact */;
|
|
34727
34902
|
let effectiveTotal = 0;
|
|
34728
34903
|
let effectiveCount = 0;
|
|
34729
|
-
let effectiveKind =
|
|
34730
|
-
let effectiveMissingKind =
|
|
34904
|
+
let effectiveKind = 0 /* Exact */;
|
|
34905
|
+
let effectiveMissingKind = 0 /* Exact */;
|
|
34731
34906
|
const positioned = position.value !== null && position.value !== "static";
|
|
34732
34907
|
const add = (name, sign, requiresPositioning) => {
|
|
34733
34908
|
const v = readNumeric(name);
|
|
@@ -34798,7 +34973,7 @@ function buildCohortIndex(input) {
|
|
|
34798
34973
|
axisCertainty: context.axisCertainty,
|
|
34799
34974
|
measurementNodeByRootKey: input.measurementNodeByRootKey,
|
|
34800
34975
|
snapshotByElementNode: input.snapshotByElementNode,
|
|
34801
|
-
|
|
34976
|
+
snapshotHotSignalsByNode: input.snapshotHotSignalsByNode
|
|
34802
34977
|
});
|
|
34803
34978
|
measurementIndexHits += cohortMetricsResult.measurementHits;
|
|
34804
34979
|
const metrics = cohortMetricsResult.metrics;
|
|
@@ -34832,7 +35007,7 @@ function buildCohortIndex(input) {
|
|
|
34832
35007
|
subjectMetrics.rootNode,
|
|
34833
35008
|
input.childrenByParentNode,
|
|
34834
35009
|
input.snapshotByElementNode,
|
|
34835
|
-
input.
|
|
35010
|
+
input.snapshotHotSignalsByNode
|
|
34836
35011
|
);
|
|
34837
35012
|
subjectsByElementKey.set(subjectMetrics.key, {
|
|
34838
35013
|
element: subjectMetrics.element,
|
|
@@ -34898,7 +35073,7 @@ function collectCohortMetrics(input) {
|
|
|
34898
35073
|
if (!snapshot) {
|
|
34899
35074
|
throw new Error(`missing snapshot for measurement node ${measurementNode.key}`);
|
|
34900
35075
|
}
|
|
34901
|
-
const hotSignals = input.
|
|
35076
|
+
const hotSignals = input.snapshotHotSignalsByNode.get(measurementNode);
|
|
34902
35077
|
if (!hotSignals) {
|
|
34903
35078
|
throw new Error(`missing hot signals for measurement node ${measurementNode.key}`);
|
|
34904
35079
|
}
|
|
@@ -35223,9 +35398,9 @@ function buildCohortSignalIndex(metrics) {
|
|
|
35223
35398
|
const verticalAlignCounts = /* @__PURE__ */ new Map();
|
|
35224
35399
|
const alignSelfCounts = /* @__PURE__ */ new Map();
|
|
35225
35400
|
const placeSelfCounts = /* @__PURE__ */ new Map();
|
|
35226
|
-
let verticalAlignMergedKind =
|
|
35227
|
-
let alignSelfMergedKind =
|
|
35228
|
-
let placeSelfMergedKind =
|
|
35401
|
+
let verticalAlignMergedKind = 0 /* Exact */;
|
|
35402
|
+
let alignSelfMergedKind = 0 /* Exact */;
|
|
35403
|
+
let placeSelfMergedKind = 0 /* Exact */;
|
|
35229
35404
|
let verticalAlignComparableCount = 0;
|
|
35230
35405
|
let alignSelfComparableCount = 0;
|
|
35231
35406
|
let placeSelfComparableCount = 0;
|
|
@@ -35239,12 +35414,12 @@ function buildCohortSignalIndex(metrics) {
|
|
|
35239
35414
|
const snapshot = metric.element.snapshot;
|
|
35240
35415
|
const alignSelf = metric.hotSignals.alignSelf;
|
|
35241
35416
|
const placeSelf = metric.hotSignals.placeSelf;
|
|
35242
|
-
const isControlOrReplaced = snapshot.isControl || snapshot.isReplaced;
|
|
35417
|
+
const isControlOrReplaced = snapshot.node.isControl || snapshot.node.isReplaced;
|
|
35243
35418
|
const verticalAlign = resolveComparableVerticalAlign(metric.hotSignals.verticalAlign, isControlOrReplaced);
|
|
35244
35419
|
if (isControlOrReplaced) controlOrReplacedCount++;
|
|
35245
|
-
if (snapshot.textualContent ===
|
|
35246
|
-
if (snapshot.textualContent ===
|
|
35247
|
-
if (snapshot.textualContent ===
|
|
35420
|
+
if (snapshot.node.textualContent === 0 /* Yes */ || snapshot.node.textualContent === 3 /* DynamicText */) textYesCount++;
|
|
35421
|
+
if (snapshot.node.textualContent === 1 /* No */) textNoCount++;
|
|
35422
|
+
if (snapshot.node.textualContent === 2 /* Unknown */) textUnknownCount++;
|
|
35248
35423
|
if (verticalAlign.value !== null) {
|
|
35249
35424
|
verticalAlignMergedKind = mergeEvidenceKind(verticalAlignMergedKind, verticalAlign.kind);
|
|
35250
35425
|
verticalAlignComparableCount++;
|
|
@@ -35264,24 +35439,24 @@ function buildCohortSignalIndex(metrics) {
|
|
|
35264
35439
|
verticalAlign,
|
|
35265
35440
|
alignSelf,
|
|
35266
35441
|
placeSelf,
|
|
35267
|
-
textualContent: snapshot.textualContent,
|
|
35442
|
+
textualContent: snapshot.node.textualContent,
|
|
35268
35443
|
isControlOrReplaced
|
|
35269
35444
|
});
|
|
35270
35445
|
}
|
|
35271
35446
|
return {
|
|
35272
35447
|
byKey,
|
|
35273
35448
|
verticalAlign: {
|
|
35274
|
-
mergedKind: verticalAlignComparableCount === 0 ?
|
|
35449
|
+
mergedKind: verticalAlignComparableCount === 0 ? 3 /* Unknown */ : verticalAlignMergedKind,
|
|
35275
35450
|
comparableCount: verticalAlignComparableCount,
|
|
35276
35451
|
countsByValue: verticalAlignCounts
|
|
35277
35452
|
},
|
|
35278
35453
|
alignSelf: {
|
|
35279
|
-
mergedKind: alignSelfComparableCount === 0 ?
|
|
35454
|
+
mergedKind: alignSelfComparableCount === 0 ? 3 /* Unknown */ : alignSelfMergedKind,
|
|
35280
35455
|
comparableCount: alignSelfComparableCount,
|
|
35281
35456
|
countsByValue: alignSelfCounts
|
|
35282
35457
|
},
|
|
35283
35458
|
placeSelf: {
|
|
35284
|
-
mergedKind: placeSelfComparableCount === 0 ?
|
|
35459
|
+
mergedKind: placeSelfComparableCount === 0 ? 3 /* Unknown */ : placeSelfMergedKind,
|
|
35285
35460
|
comparableCount: placeSelfComparableCount,
|
|
35286
35461
|
countsByValue: placeSelfCounts
|
|
35287
35462
|
},
|
|
@@ -35318,9 +35493,9 @@ function collectSubjectCohortSignals(index, subjectMetrics, context) {
|
|
|
35318
35493
|
sawComparableVerticalAlign,
|
|
35319
35494
|
sawVerticalAlignConflict
|
|
35320
35495
|
);
|
|
35321
|
-
const tableCellControlFallback = context.kind === "table-cell" && subject.isControlOrReplaced && verticalAlign.value ===
|
|
35496
|
+
const tableCellControlFallback = context.kind === "table-cell" && subject.isControlOrReplaced && verticalAlign.value === 2 /* Unknown */ && index.byKey.size > index.controlOrReplacedCount;
|
|
35322
35497
|
const normalizedVerticalAlign = tableCellControlFallback ? {
|
|
35323
|
-
value:
|
|
35498
|
+
value: 0 /* Conflict */,
|
|
35324
35499
|
kind: verticalAlignKind
|
|
35325
35500
|
} : verticalAlign;
|
|
35326
35501
|
const textContrastWithPeers = resolveIndexedTextContrastWithPeers(
|
|
@@ -35353,7 +35528,7 @@ function resolveComparableVerticalAlign(verticalAlign, isControlOrReplaced) {
|
|
|
35353
35528
|
return {
|
|
35354
35529
|
present: verticalAlign.present,
|
|
35355
35530
|
value: "baseline",
|
|
35356
|
-
kind:
|
|
35531
|
+
kind: 0 /* Exact */
|
|
35357
35532
|
};
|
|
35358
35533
|
}
|
|
35359
35534
|
function hasComparablePeer(aggregate, subjectValue) {
|
|
@@ -35370,37 +35545,37 @@ function hasConflictPeer(aggregate, subjectValue) {
|
|
|
35370
35545
|
function finalizeConflictEvidence(subjectValue, kind, sawComparablePeer, sawConflict) {
|
|
35371
35546
|
if (subjectValue === null) {
|
|
35372
35547
|
return {
|
|
35373
|
-
value:
|
|
35548
|
+
value: 2 /* Unknown */,
|
|
35374
35549
|
kind
|
|
35375
35550
|
};
|
|
35376
35551
|
}
|
|
35377
35552
|
if (!sawComparablePeer) {
|
|
35378
35553
|
return {
|
|
35379
|
-
value:
|
|
35554
|
+
value: 2 /* Unknown */,
|
|
35380
35555
|
kind
|
|
35381
35556
|
};
|
|
35382
35557
|
}
|
|
35383
35558
|
return {
|
|
35384
|
-
value: sawConflict ?
|
|
35559
|
+
value: sawConflict ? 0 /* Conflict */ : 1 /* Aligned */,
|
|
35385
35560
|
kind
|
|
35386
35561
|
};
|
|
35387
35562
|
}
|
|
35388
35563
|
function resolveIndexedTextContrastWithPeers(index, subjectTextualContent, subjectIsControlOrReplaced, tableCellControlFallback) {
|
|
35389
|
-
if (subjectTextualContent ===
|
|
35564
|
+
if (subjectTextualContent === 2 /* Unknown */) return 2 /* Unknown */;
|
|
35390
35565
|
const unknownPeers = index.textUnknownCount;
|
|
35391
35566
|
const cohortSize = index.byKey.size;
|
|
35392
|
-
if (subjectTextualContent ===
|
|
35393
|
-
if (index.textNoCount > 0) return
|
|
35394
|
-
if (unknownPeers > 0) return
|
|
35395
|
-
return
|
|
35567
|
+
if (subjectTextualContent === 0 /* Yes */ || subjectTextualContent === 3 /* DynamicText */) {
|
|
35568
|
+
if (index.textNoCount > 0) return 0 /* Different */;
|
|
35569
|
+
if (unknownPeers > 0) return 2 /* Unknown */;
|
|
35570
|
+
return 1 /* Same */;
|
|
35396
35571
|
}
|
|
35397
|
-
if (index.textYesCount > 0) return
|
|
35398
|
-
if (tableCellControlFallback) return
|
|
35572
|
+
if (index.textYesCount > 0) return 0 /* Different */;
|
|
35573
|
+
if (tableCellControlFallback) return 0 /* Different */;
|
|
35399
35574
|
if (subjectIsControlOrReplaced && index.controlOrReplacedCount === 1 && cohortSize >= 3 && unknownPeers > 0) {
|
|
35400
|
-
return
|
|
35575
|
+
return 0 /* Different */;
|
|
35401
35576
|
}
|
|
35402
|
-
if (unknownPeers > 0) return
|
|
35403
|
-
return
|
|
35577
|
+
if (unknownPeers > 0) return 2 /* Unknown */;
|
|
35578
|
+
return 1 /* Same */;
|
|
35404
35579
|
}
|
|
35405
35580
|
function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineProfile, clusterSummary, signalIndex, cohortKind, cohortSize) {
|
|
35406
35581
|
const subjectClusterKey = toComparableClusterKey(subjectMetrics);
|
|
@@ -35416,7 +35591,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35416
35591
|
return {
|
|
35417
35592
|
dominantShare: profile.dominantClusterShare,
|
|
35418
35593
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35419
|
-
subjectMembership:
|
|
35594
|
+
subjectMembership: 3 /* Insufficient */,
|
|
35420
35595
|
ambiguous: true,
|
|
35421
35596
|
kind
|
|
35422
35597
|
};
|
|
@@ -35425,7 +35600,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35425
35600
|
return {
|
|
35426
35601
|
dominantShare: profile.dominantClusterShare,
|
|
35427
35602
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35428
|
-
subjectMembership:
|
|
35603
|
+
subjectMembership: 0 /* Dominant */,
|
|
35429
35604
|
ambiguous: false,
|
|
35430
35605
|
kind
|
|
35431
35606
|
};
|
|
@@ -35434,7 +35609,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35434
35609
|
return {
|
|
35435
35610
|
dominantShare: profile.dominantClusterShare,
|
|
35436
35611
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35437
|
-
subjectMembership:
|
|
35612
|
+
subjectMembership: 3 /* Insufficient */,
|
|
35438
35613
|
ambiguous: true,
|
|
35439
35614
|
kind
|
|
35440
35615
|
};
|
|
@@ -35444,7 +35619,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35444
35619
|
return {
|
|
35445
35620
|
dominantShare: profile.dominantClusterShare,
|
|
35446
35621
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35447
|
-
subjectMembership:
|
|
35622
|
+
subjectMembership: 3 /* Insufficient */,
|
|
35448
35623
|
ambiguous: true,
|
|
35449
35624
|
kind
|
|
35450
35625
|
};
|
|
@@ -35454,7 +35629,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35454
35629
|
return {
|
|
35455
35630
|
dominantShare: profile.dominantClusterShare,
|
|
35456
35631
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35457
|
-
subjectMembership:
|
|
35632
|
+
subjectMembership: 2 /* Ambiguous */,
|
|
35458
35633
|
ambiguous: true,
|
|
35459
35634
|
kind
|
|
35460
35635
|
};
|
|
@@ -35463,7 +35638,7 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35463
35638
|
return {
|
|
35464
35639
|
dominantShare: profile.dominantClusterShare,
|
|
35465
35640
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35466
|
-
subjectMembership:
|
|
35641
|
+
subjectMembership: 0 /* Dominant */,
|
|
35467
35642
|
ambiguous: false,
|
|
35468
35643
|
kind
|
|
35469
35644
|
};
|
|
@@ -35471,13 +35646,13 @@ function resolveSubjectIdentifiability(subjectMetrics, profile, subjectBaselineP
|
|
|
35471
35646
|
return {
|
|
35472
35647
|
dominantShare: profile.dominantClusterShare,
|
|
35473
35648
|
subjectExcludedDominantShare: subjectBaselineProfile.dominantClusterShare,
|
|
35474
|
-
subjectMembership:
|
|
35649
|
+
subjectMembership: 1 /* Nondominant */,
|
|
35475
35650
|
ambiguous: false,
|
|
35476
35651
|
kind
|
|
35477
35652
|
};
|
|
35478
35653
|
}
|
|
35479
35654
|
function resolveControlRoleIdentifiability(subjectMetrics, signalIndex, kind, cohortSize) {
|
|
35480
|
-
const subjectIsControlOrReplaced = subjectMetrics.element.snapshot.isControl || subjectMetrics.element.snapshot.isReplaced;
|
|
35655
|
+
const subjectIsControlOrReplaced = subjectMetrics.element.snapshot.node.isControl || subjectMetrics.element.snapshot.node.isReplaced;
|
|
35481
35656
|
const controlCount = signalIndex.controlOrReplacedCount;
|
|
35482
35657
|
const nonControlCount = cohortSize - controlCount;
|
|
35483
35658
|
if (controlCount <= 0 || nonControlCount <= 0) return null;
|
|
@@ -35492,12 +35667,12 @@ function resolveControlRoleIdentifiability(subjectMetrics, signalIndex, kind, co
|
|
|
35492
35667
|
return {
|
|
35493
35668
|
dominantShare,
|
|
35494
35669
|
subjectExcludedDominantShare: excludedDominantShare,
|
|
35495
|
-
subjectMembership: subjectMembership ===
|
|
35670
|
+
subjectMembership: subjectMembership === 2 /* Ambiguous */ ? 0 /* Dominant */ : subjectMembership,
|
|
35496
35671
|
ambiguous: false,
|
|
35497
35672
|
kind
|
|
35498
35673
|
};
|
|
35499
35674
|
}
|
|
35500
|
-
if (subjectMembership ===
|
|
35675
|
+
if (subjectMembership === 2 /* Ambiguous */) {
|
|
35501
35676
|
return {
|
|
35502
35677
|
dominantShare,
|
|
35503
35678
|
subjectExcludedDominantShare: excludedDominantShare,
|
|
@@ -35515,9 +35690,9 @@ function resolveControlRoleIdentifiability(subjectMetrics, signalIndex, kind, co
|
|
|
35515
35690
|
};
|
|
35516
35691
|
}
|
|
35517
35692
|
function resolveRoleMembership(controlCount, nonControlCount, subjectIsControlOrReplaced) {
|
|
35518
|
-
if (controlCount === nonControlCount) return
|
|
35693
|
+
if (controlCount === nonControlCount) return 2 /* Ambiguous */;
|
|
35519
35694
|
const dominantRoleIsControl = controlCount > nonControlCount;
|
|
35520
|
-
return dominantRoleIsControl === subjectIsControlOrReplaced ?
|
|
35695
|
+
return dominantRoleIsControl === subjectIsControlOrReplaced ? 0 /* Dominant */ : 1 /* Nondominant */;
|
|
35521
35696
|
}
|
|
35522
35697
|
function resolveExcludedRoleDominantShare(controlCount, nonControlCount, subjectIsControlOrReplaced) {
|
|
35523
35698
|
const controlAfterExclusion = controlCount - (subjectIsControlOrReplaced ? 1 : 0);
|
|
@@ -35555,8 +35730,8 @@ function collectCohortProvenanceFromSnapshots(snapshots) {
|
|
|
35555
35730
|
const snapshot = snapshots[i];
|
|
35556
35731
|
if (!snapshot) continue;
|
|
35557
35732
|
for (const signal of snapshot.signals.values()) {
|
|
35558
|
-
for (let j = 0; j < signal.
|
|
35559
|
-
const guard = signal.
|
|
35733
|
+
for (let j = 0; j < signal.guard.conditions.length; j++) {
|
|
35734
|
+
const guard = signal.guard.conditions[j];
|
|
35560
35735
|
if (!guard) continue;
|
|
35561
35736
|
if (!byKey.has(guard.key)) byKey.set(guard.key, guard);
|
|
35562
35737
|
}
|
|
@@ -35586,7 +35761,7 @@ function buildGuardKey(guards) {
|
|
|
35586
35761
|
return keys.join("&");
|
|
35587
35762
|
}
|
|
35588
35763
|
function resolveCohortEvidenceKind(metrics) {
|
|
35589
|
-
let kind =
|
|
35764
|
+
let kind = 0 /* Exact */;
|
|
35590
35765
|
for (let i = 0; i < metrics.length; i++) {
|
|
35591
35766
|
const metric = metrics[i];
|
|
35592
35767
|
if (!metric) continue;
|
|
@@ -35603,9 +35778,9 @@ function incrementCount(counts, key) {
|
|
|
35603
35778
|
counts.set(key, existing + 1);
|
|
35604
35779
|
}
|
|
35605
35780
|
function toEvidenceKind2(certainty) {
|
|
35606
|
-
if (certainty ===
|
|
35607
|
-
if (certainty ===
|
|
35608
|
-
return
|
|
35781
|
+
if (certainty === 0 /* Resolved */) return 0 /* Exact */;
|
|
35782
|
+
if (certainty === 1 /* Conditional */) return 2 /* Conditional */;
|
|
35783
|
+
return 3 /* Unknown */;
|
|
35609
35784
|
}
|
|
35610
35785
|
function computeMedian(values) {
|
|
35611
35786
|
if (values.length === 0) return null;
|
|
@@ -35625,66 +35800,6 @@ function computeMedianAbsoluteDeviation(values, median, scratch) {
|
|
|
35625
35800
|
}
|
|
35626
35801
|
return computeMedian(scratch);
|
|
35627
35802
|
}
|
|
35628
|
-
function selectKth(values, targetIndex) {
|
|
35629
|
-
let left = 0;
|
|
35630
|
-
let right = values.length - 1;
|
|
35631
|
-
while (left <= right) {
|
|
35632
|
-
if (left === right) {
|
|
35633
|
-
const result = values[left];
|
|
35634
|
-
if (result === void 0) return 0;
|
|
35635
|
-
return result;
|
|
35636
|
-
}
|
|
35637
|
-
const pivotIndex = choosePivotIndex(values, left, right);
|
|
35638
|
-
const partitionIndex = partitionAroundPivot(values, left, right, pivotIndex);
|
|
35639
|
-
if (partitionIndex === targetIndex) {
|
|
35640
|
-
const result = values[partitionIndex];
|
|
35641
|
-
if (result === void 0) return 0;
|
|
35642
|
-
return result;
|
|
35643
|
-
}
|
|
35644
|
-
if (partitionIndex < targetIndex) {
|
|
35645
|
-
left = partitionIndex + 1;
|
|
35646
|
-
continue;
|
|
35647
|
-
}
|
|
35648
|
-
right = partitionIndex - 1;
|
|
35649
|
-
}
|
|
35650
|
-
const fallback = values[targetIndex];
|
|
35651
|
-
if (fallback === void 0) return 0;
|
|
35652
|
-
return fallback;
|
|
35653
|
-
}
|
|
35654
|
-
function choosePivotIndex(values, left, right) {
|
|
35655
|
-
const middle = Math.floor((left + right) / 2);
|
|
35656
|
-
const leftValue = values[left] ?? 0;
|
|
35657
|
-
const middleValue = values[middle] ?? 0;
|
|
35658
|
-
const rightValue = values[right] ?? 0;
|
|
35659
|
-
if (leftValue < middleValue) {
|
|
35660
|
-
if (middleValue < rightValue) return middle;
|
|
35661
|
-
if (leftValue < rightValue) return right;
|
|
35662
|
-
return left;
|
|
35663
|
-
}
|
|
35664
|
-
if (leftValue < rightValue) return left;
|
|
35665
|
-
if (middleValue < rightValue) return right;
|
|
35666
|
-
return middle;
|
|
35667
|
-
}
|
|
35668
|
-
function partitionAroundPivot(values, left, right, pivotIndex) {
|
|
35669
|
-
const pivotValue = values[pivotIndex] ?? 0;
|
|
35670
|
-
swap(values, pivotIndex, right);
|
|
35671
|
-
let storeIndex = left;
|
|
35672
|
-
for (let i = left; i < right; i++) {
|
|
35673
|
-
const current = values[i];
|
|
35674
|
-
if (current === void 0 || current > pivotValue) continue;
|
|
35675
|
-
swap(values, storeIndex, i);
|
|
35676
|
-
storeIndex++;
|
|
35677
|
-
}
|
|
35678
|
-
swap(values, storeIndex, right);
|
|
35679
|
-
return storeIndex;
|
|
35680
|
-
}
|
|
35681
|
-
function swap(values, left, right) {
|
|
35682
|
-
if (left === right) return;
|
|
35683
|
-
const leftValue = values[left] ?? 0;
|
|
35684
|
-
const rightValue = values[right] ?? 0;
|
|
35685
|
-
values[left] = rightValue;
|
|
35686
|
-
values[right] = leftValue;
|
|
35687
|
-
}
|
|
35688
35803
|
function resolveVerticalAlignConsensus(aggregate) {
|
|
35689
35804
|
if (aggregate.comparableCount === 0) return null;
|
|
35690
35805
|
if (aggregate.countsByValue.size !== 1) return null;
|
|
@@ -35783,7 +35898,7 @@ function resolveMeasurementCandidates(root, childrenByParentNode, snapshotByElem
|
|
|
35783
35898
|
if (firstControlOrReplacedDescendant === null && (child.isControl || child.isReplaced)) {
|
|
35784
35899
|
firstControlOrReplacedDescendant = child;
|
|
35785
35900
|
}
|
|
35786
|
-
if (firstTextualDescendant === null && child.textualContent ===
|
|
35901
|
+
if (firstTextualDescendant === null && child.textualContent === 0 /* Yes */) {
|
|
35787
35902
|
firstTextualDescendant = child;
|
|
35788
35903
|
}
|
|
35789
35904
|
if (firstControlOrReplacedDescendant !== null && firstTextualDescendant !== null) break;
|
|
@@ -35809,7 +35924,7 @@ function resolveMeasurementNode(root, candidates) {
|
|
|
35809
35924
|
if (candidates.firstControlOrReplacedDescendant !== null) return candidates.firstControlOrReplacedDescendant;
|
|
35810
35925
|
if (root.isControl || root.isReplaced) return root;
|
|
35811
35926
|
if (candidates.firstTextualDescendant !== null) return candidates.firstTextualDescendant;
|
|
35812
|
-
if (root.textualContent ===
|
|
35927
|
+
if (root.textualContent === 0 /* Yes */) return root;
|
|
35813
35928
|
return root;
|
|
35814
35929
|
}
|
|
35815
35930
|
|
|
@@ -35856,7 +35971,7 @@ function buildScopedSelectorIndexBySolidFile(cssScopeBySolidFile, css, selectorM
|
|
|
35856
35971
|
seenSelectorIds.add(selector.id);
|
|
35857
35972
|
const metadata = selectorMetadataById.get(selector.id);
|
|
35858
35973
|
if (!metadata) continue;
|
|
35859
|
-
if (metadata.guard.kind ===
|
|
35974
|
+
if (metadata.guard.kind === 1 /* Conditional */) {
|
|
35860
35975
|
if (!conditionalSelectorIds.has(selector.id)) {
|
|
35861
35976
|
conditionalSelectorIds.add(selector.id);
|
|
35862
35977
|
perf.selectorsGuardedConditional++;
|
|
@@ -35898,7 +36013,7 @@ function buildScopedSelectorIndexBySolidFile(cssScopeBySolidFile, css, selectorM
|
|
|
35898
36013
|
}
|
|
35899
36014
|
return out;
|
|
35900
36015
|
}
|
|
35901
|
-
function
|
|
36016
|
+
function buildSelectorCandidatesByNode(elements, scopedSelectorsBySolidFile, perf) {
|
|
35902
36017
|
const out = /* @__PURE__ */ new Map();
|
|
35903
36018
|
for (let i = 0; i < elements.length; i++) {
|
|
35904
36019
|
const node = elements[i];
|
|
@@ -35908,7 +36023,7 @@ function buildSelectorCandidatesByElementKey(elements, scopedSelectorsBySolidFil
|
|
|
35908
36023
|
const byTag = node.tagName !== null ? collectSelectorCandidates(scoped.bySubjectTag.get(node.tagName), node.selectorDispatchKeys) : EMPTY_SELECTOR_LIST;
|
|
35909
36024
|
const withoutTag = collectSelectorCandidates(scoped.withoutSubjectTag, node.selectorDispatchKeys);
|
|
35910
36025
|
const merged = mergeSelectorCandidateIds(byTag, withoutTag);
|
|
35911
|
-
out.set(node
|
|
36026
|
+
out.set(node, merged);
|
|
35912
36027
|
perf.elementsScanned++;
|
|
35913
36028
|
perf.selectorCandidatesChecked += merged.length;
|
|
35914
36029
|
}
|
|
@@ -36367,12 +36482,6 @@ var EMPTY_EXPANSION_RESULT = [];
|
|
|
36367
36482
|
function collectMonitoredDeclarations(selector, layerOrder, guard) {
|
|
36368
36483
|
const out = [];
|
|
36369
36484
|
const declarations = selector.rule.declarations;
|
|
36370
|
-
const signalGuard = guard.kind === "conditional" ? "conditional" : "unconditional";
|
|
36371
|
-
const guardProvenance = {
|
|
36372
|
-
kind: signalGuard,
|
|
36373
|
-
conditions: guard.conditions,
|
|
36374
|
-
key: guard.key
|
|
36375
|
-
};
|
|
36376
36485
|
for (let i = 0; i < declarations.length; i++) {
|
|
36377
36486
|
const declaration = declarations[i];
|
|
36378
36487
|
if (!declaration) continue;
|
|
@@ -36383,8 +36492,7 @@ function collectMonitoredDeclarations(selector, layerOrder, guard) {
|
|
|
36383
36492
|
out.push({
|
|
36384
36493
|
property: monitored,
|
|
36385
36494
|
value: declaration.value,
|
|
36386
|
-
|
|
36387
|
-
guardProvenance,
|
|
36495
|
+
guardProvenance: guard,
|
|
36388
36496
|
position: {
|
|
36389
36497
|
layer: declaration.cascadePosition.layer,
|
|
36390
36498
|
layerOrder,
|
|
@@ -36406,6 +36514,7 @@ function toMonitoredSignalKey(property) {
|
|
|
36406
36514
|
case "margin-block":
|
|
36407
36515
|
case "padding-block":
|
|
36408
36516
|
case "inset-block":
|
|
36517
|
+
case "flex-flow":
|
|
36409
36518
|
return property;
|
|
36410
36519
|
default:
|
|
36411
36520
|
return null;
|
|
@@ -36429,30 +36538,27 @@ function expandMonitoredDeclarationForDelta(declaration) {
|
|
|
36429
36538
|
if (signalName === void 0) return EMPTY_EXPANSION_RESULT;
|
|
36430
36539
|
return [{ name: signalName, value: value2 }];
|
|
36431
36540
|
}
|
|
36432
|
-
function appendMatchingEdgesFromSelectorIds(selectorIds, node,
|
|
36433
|
-
const fileRoots = rootElementsByFile.get(node.solidFile) ?? null;
|
|
36541
|
+
function appendMatchingEdgesFromSelectorIds(ctx, selectorIds, node, applies, appliesByElementNodeMutable) {
|
|
36542
|
+
const fileRoots = ctx.rootElementsByFile.get(node.solidFile) ?? null;
|
|
36434
36543
|
for (let i = 0; i < selectorIds.length; i++) {
|
|
36435
36544
|
const selectorId = selectorIds[i];
|
|
36436
36545
|
if (selectorId === void 0) continue;
|
|
36437
|
-
const metadata = selectorMetadataById.get(selectorId);
|
|
36546
|
+
const metadata = ctx.selectorMetadataById.get(selectorId);
|
|
36438
36547
|
if (!metadata || !metadata.matcher) {
|
|
36439
36548
|
throw new Error(`missing compiled selector matcher for selector ${selectorId}`);
|
|
36440
36549
|
}
|
|
36441
|
-
const selector = selectorsById.get(selectorId);
|
|
36550
|
+
const selector = ctx.selectorsById.get(selectorId);
|
|
36442
36551
|
if (!selector) {
|
|
36443
36552
|
throw new Error(`missing selector ${selectorId}`);
|
|
36444
36553
|
}
|
|
36445
|
-
if (!selectorMatchesLayoutElement(metadata.matcher, node, perf, fileRoots, logger)) continue;
|
|
36554
|
+
if (!selectorMatchesLayoutElement(metadata.matcher, node, ctx.perf, fileRoots, ctx.logger)) continue;
|
|
36446
36555
|
const edge = {
|
|
36447
|
-
solidFile: node.solidFile,
|
|
36448
|
-
elementId: node.elementId,
|
|
36449
|
-
elementKey: node.key,
|
|
36450
36556
|
selectorId: selector.id,
|
|
36451
36557
|
specificityScore: selector.specificityScore,
|
|
36452
36558
|
sourceOrder: selector.rule.sourceOrder
|
|
36453
36559
|
};
|
|
36454
36560
|
applies.push(edge);
|
|
36455
|
-
perf.matchEdgesCreated++;
|
|
36561
|
+
ctx.perf.matchEdgesCreated++;
|
|
36456
36562
|
const existing = appliesByElementNodeMutable.get(node);
|
|
36457
36563
|
if (existing) {
|
|
36458
36564
|
existing.push(edge);
|
|
@@ -36478,7 +36584,7 @@ function augmentCascadeWithTailwind(cascade, node, tailwind) {
|
|
|
36478
36584
|
const classTokens = node.classTokens;
|
|
36479
36585
|
if (classTokens.length === 0) return;
|
|
36480
36586
|
const guardProvenance = {
|
|
36481
|
-
kind:
|
|
36587
|
+
kind: 0 /* Unconditional */,
|
|
36482
36588
|
conditions: [],
|
|
36483
36589
|
key: "always"
|
|
36484
36590
|
};
|
|
@@ -36495,8 +36601,7 @@ function augmentCascadeWithTailwind(cascade, node, tailwind) {
|
|
|
36495
36601
|
if (cascade.has(property)) continue;
|
|
36496
36602
|
cascade.set(property, {
|
|
36497
36603
|
value: value2,
|
|
36498
|
-
source:
|
|
36499
|
-
guard: "unconditional",
|
|
36604
|
+
source: 0 /* Selector */,
|
|
36500
36605
|
guardProvenance
|
|
36501
36606
|
});
|
|
36502
36607
|
}
|
|
@@ -36516,8 +36621,7 @@ function buildCascadeMapForElement(node, edges, monitoredDeclarationsBySelectorI
|
|
|
36516
36621
|
const property = declaration.property;
|
|
36517
36622
|
const newDeclaration = {
|
|
36518
36623
|
value: declaration.value,
|
|
36519
|
-
source:
|
|
36520
|
-
guard: declaration.guard,
|
|
36624
|
+
source: 0 /* Selector */,
|
|
36521
36625
|
guardProvenance: declaration.guardProvenance
|
|
36522
36626
|
};
|
|
36523
36627
|
const existingPosition = positions.get(property);
|
|
@@ -36536,33 +36640,26 @@ function buildCascadeMapForElement(node, edges, monitoredDeclarationsBySelectorI
|
|
|
36536
36640
|
positions.set(property, declaration.position);
|
|
36537
36641
|
}
|
|
36538
36642
|
}
|
|
36539
|
-
const inlinePosition = createInlineCascadePosition();
|
|
36540
|
-
const inlineGuardProvenance = {
|
|
36541
|
-
kind: "unconditional",
|
|
36542
|
-
conditions: [],
|
|
36543
|
-
key: "always"
|
|
36544
|
-
};
|
|
36545
36643
|
for (const [property, value2] of node.inlineStyleValues) {
|
|
36546
36644
|
const newDeclaration = {
|
|
36547
36645
|
value: value2,
|
|
36548
|
-
source:
|
|
36549
|
-
|
|
36550
|
-
guardProvenance: inlineGuardProvenance
|
|
36646
|
+
source: 1 /* InlineStyle */,
|
|
36647
|
+
guardProvenance: INLINE_GUARD_PROVENANCE
|
|
36551
36648
|
};
|
|
36552
36649
|
const existingPosition = positions.get(property);
|
|
36553
36650
|
if (existingPosition === void 0) {
|
|
36554
36651
|
out.set(property, newDeclaration);
|
|
36555
|
-
positions.set(property,
|
|
36652
|
+
positions.set(property, INLINE_CASCADE_POSITION);
|
|
36556
36653
|
continue;
|
|
36557
36654
|
}
|
|
36558
36655
|
const existingDeclaration = out.get(property);
|
|
36559
36656
|
if (existingDeclaration === void 0) continue;
|
|
36560
36657
|
if (!doesCandidateOverride(
|
|
36561
36658
|
{ declaration: existingDeclaration, position: existingPosition },
|
|
36562
|
-
{ declaration: newDeclaration, position:
|
|
36659
|
+
{ declaration: newDeclaration, position: INLINE_CASCADE_POSITION }
|
|
36563
36660
|
)) continue;
|
|
36564
36661
|
out.set(property, newDeclaration);
|
|
36565
|
-
positions.set(property,
|
|
36662
|
+
positions.set(property, INLINE_CASCADE_POSITION);
|
|
36566
36663
|
}
|
|
36567
36664
|
if (tailwind !== null) {
|
|
36568
36665
|
augmentCascadeWithTailwind(out, node, tailwind);
|
|
@@ -36579,7 +36676,7 @@ function doesCandidateOverride(existing, incoming) {
|
|
|
36579
36676
|
const existingSource = existing.declaration.source;
|
|
36580
36677
|
const incomingSource = incoming.declaration.source;
|
|
36581
36678
|
if (existingSource !== incomingSource) {
|
|
36582
|
-
if (incomingSource ===
|
|
36679
|
+
if (incomingSource === 1 /* InlineStyle */) {
|
|
36583
36680
|
if (existing.position.isImportant && !incoming.position.isImportant) return false;
|
|
36584
36681
|
return true;
|
|
36585
36682
|
}
|
|
@@ -36587,16 +36684,19 @@ function doesCandidateOverride(existing, incoming) {
|
|
|
36587
36684
|
}
|
|
36588
36685
|
return compareCascadePositions(incoming.position, existing.position) > 0;
|
|
36589
36686
|
}
|
|
36590
|
-
|
|
36591
|
-
|
|
36592
|
-
|
|
36593
|
-
|
|
36594
|
-
|
|
36595
|
-
|
|
36596
|
-
|
|
36597
|
-
|
|
36598
|
-
|
|
36599
|
-
|
|
36687
|
+
var INLINE_CASCADE_POSITION = Object.freeze({
|
|
36688
|
+
layer: null,
|
|
36689
|
+
layerOrder: Number.MAX_SAFE_INTEGER,
|
|
36690
|
+
sourceOrder: Number.MAX_SAFE_INTEGER,
|
|
36691
|
+
specificity: [1, 0, 0, 0],
|
|
36692
|
+
specificityScore: Number.MAX_SAFE_INTEGER,
|
|
36693
|
+
isImportant: false
|
|
36694
|
+
});
|
|
36695
|
+
var INLINE_GUARD_PROVENANCE = Object.freeze({
|
|
36696
|
+
kind: 0 /* Unconditional */,
|
|
36697
|
+
conditions: [],
|
|
36698
|
+
key: "always"
|
|
36699
|
+
});
|
|
36600
36700
|
function resolveRuleLayerOrder(rule, css) {
|
|
36601
36701
|
const layer = rule.containingLayer;
|
|
36602
36702
|
if (!layer) return 0;
|
|
@@ -36604,14 +36704,14 @@ function resolveRuleLayerOrder(rule, css) {
|
|
|
36604
36704
|
if (!name) return 0;
|
|
36605
36705
|
return css.layerOrder.get(name) ?? 0;
|
|
36606
36706
|
}
|
|
36607
|
-
function buildConditionalDeltaIndex(elements,
|
|
36608
|
-
const
|
|
36707
|
+
function buildConditionalDeltaIndex(elements, appliesByNode, monitoredDeclarationsBySelectorId) {
|
|
36708
|
+
const conditionalSignalDeltaFactsByNode = /* @__PURE__ */ new Map();
|
|
36609
36709
|
const elementsWithConditionalDeltaBySignal = /* @__PURE__ */ new Map();
|
|
36610
|
-
const
|
|
36710
|
+
const baselineOffsetFactsByNode = /* @__PURE__ */ new Map();
|
|
36611
36711
|
for (let i = 0; i < elements.length; i++) {
|
|
36612
36712
|
const node = elements[i];
|
|
36613
36713
|
if (!node) continue;
|
|
36614
|
-
const edges =
|
|
36714
|
+
const edges = appliesByNode.get(node);
|
|
36615
36715
|
let factByProperty = null;
|
|
36616
36716
|
if (edges !== void 0 && edges.length > 0) {
|
|
36617
36717
|
const byProperty = /* @__PURE__ */ new Map();
|
|
@@ -36636,7 +36736,7 @@ function buildConditionalDeltaIndex(elements, appliesByElementKey, monitoredDecl
|
|
|
36636
36736
|
};
|
|
36637
36737
|
byProperty.set(property, bucket);
|
|
36638
36738
|
}
|
|
36639
|
-
if (declaration.
|
|
36739
|
+
if (declaration.guardProvenance.kind === 1 /* Conditional */) {
|
|
36640
36740
|
bucket.conditional.add(expandedEntry.value);
|
|
36641
36741
|
continue;
|
|
36642
36742
|
}
|
|
@@ -36676,7 +36776,7 @@ function buildConditionalDeltaIndex(elements, appliesByElementKey, monitoredDecl
|
|
|
36676
36776
|
}
|
|
36677
36777
|
if (facts.size > 0) {
|
|
36678
36778
|
factByProperty = facts;
|
|
36679
|
-
|
|
36779
|
+
conditionalSignalDeltaFactsByNode.set(node, facts);
|
|
36680
36780
|
for (const [signal, fact] of facts) {
|
|
36681
36781
|
if (!fact.hasConditional) continue;
|
|
36682
36782
|
const existing = elementsWithConditionalDeltaBySignal.get(signal);
|
|
@@ -36713,13 +36813,13 @@ function buildConditionalDeltaIndex(elements, appliesByElementKey, monitoredDecl
|
|
|
36713
36813
|
baselineBySignal.set(signal, [...values]);
|
|
36714
36814
|
}
|
|
36715
36815
|
if (baselineBySignal.size > 0) {
|
|
36716
|
-
|
|
36816
|
+
baselineOffsetFactsByNode.set(node, baselineBySignal);
|
|
36717
36817
|
}
|
|
36718
36818
|
}
|
|
36719
36819
|
return {
|
|
36720
|
-
|
|
36820
|
+
conditionalSignalDeltaFactsByNode,
|
|
36721
36821
|
elementsWithConditionalDeltaBySignal,
|
|
36722
|
-
|
|
36822
|
+
baselineOffsetFactsByNode
|
|
36723
36823
|
};
|
|
36724
36824
|
}
|
|
36725
36825
|
var EMPTY_NODE_LIST2 = [];
|
|
@@ -36846,8 +36946,8 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
36846
36946
|
if (child.kind === "expression") {
|
|
36847
36947
|
if (isStructuralExpression(child.node)) {
|
|
36848
36948
|
if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (structural expression child)`);
|
|
36849
|
-
memo.set(element.id,
|
|
36850
|
-
return
|
|
36949
|
+
memo.set(element.id, 2 /* Unknown */);
|
|
36950
|
+
return 2 /* Unknown */;
|
|
36851
36951
|
}
|
|
36852
36952
|
hasTextOnlyExpression = true;
|
|
36853
36953
|
continue;
|
|
@@ -36855,8 +36955,8 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
36855
36955
|
if (child.kind !== "text") continue;
|
|
36856
36956
|
if (child.node.type !== "JSXText") continue;
|
|
36857
36957
|
if (isBlank(child.node.value)) continue;
|
|
36858
|
-
memo.set(element.id,
|
|
36859
|
-
return
|
|
36958
|
+
memo.set(element.id, 0 /* Yes */);
|
|
36959
|
+
return 0 /* Yes */;
|
|
36860
36960
|
}
|
|
36861
36961
|
let childHasUnknown = false;
|
|
36862
36962
|
let childHasDynamicText = false;
|
|
@@ -36870,31 +36970,31 @@ function getTextualContentState(element, memo, compositionMetaByElementId, logge
|
|
|
36870
36970
|
if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag}#${child.id} resolves to control tag=${childMeta.tagName}, skipping`);
|
|
36871
36971
|
continue;
|
|
36872
36972
|
}
|
|
36873
|
-
if (childState !==
|
|
36973
|
+
if (childState !== 1 /* No */) {
|
|
36874
36974
|
if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id}: non-DOM child ${child.tag ?? child.id}#${child.id} has state=${childState} \u2192 childHasUnknown`);
|
|
36875
36975
|
childHasUnknown = true;
|
|
36876
36976
|
}
|
|
36877
36977
|
continue;
|
|
36878
36978
|
}
|
|
36879
|
-
if (childState ===
|
|
36880
|
-
memo.set(element.id,
|
|
36881
|
-
return
|
|
36979
|
+
if (childState === 0 /* Yes */) {
|
|
36980
|
+
memo.set(element.id, 0 /* Yes */);
|
|
36981
|
+
return 0 /* Yes */;
|
|
36882
36982
|
}
|
|
36883
|
-
if (childState ===
|
|
36884
|
-
if (childState ===
|
|
36983
|
+
if (childState === 2 /* Unknown */) childHasUnknown = true;
|
|
36984
|
+
if (childState === 3 /* DynamicText */) childHasDynamicText = true;
|
|
36885
36985
|
}
|
|
36886
36986
|
if (childHasUnknown) {
|
|
36887
36987
|
if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 unknown (child has unknown)`);
|
|
36888
|
-
memo.set(element.id,
|
|
36889
|
-
return
|
|
36988
|
+
memo.set(element.id, 2 /* Unknown */);
|
|
36989
|
+
return 2 /* Unknown */;
|
|
36890
36990
|
}
|
|
36891
36991
|
if (hasTextOnlyExpression || childHasDynamicText) {
|
|
36892
36992
|
if (logger.enabled) logger.trace(`[textual-content] element=${element.tagName ?? element.tag}#${element.id} \u2192 dynamic-text`);
|
|
36893
|
-
memo.set(element.id,
|
|
36894
|
-
return
|
|
36993
|
+
memo.set(element.id, 3 /* DynamicText */);
|
|
36994
|
+
return 3 /* DynamicText */;
|
|
36895
36995
|
}
|
|
36896
|
-
memo.set(element.id,
|
|
36897
|
-
return
|
|
36996
|
+
memo.set(element.id, 1 /* No */);
|
|
36997
|
+
return 1 /* No */;
|
|
36898
36998
|
}
|
|
36899
36999
|
function isStructuralExpression(node) {
|
|
36900
37000
|
if (node.type !== "JSXExpressionContainer") return false;
|
|
@@ -37193,8 +37293,6 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37193
37293
|
classTokens: record.classTokens,
|
|
37194
37294
|
classTokenSet: record.classTokenSet,
|
|
37195
37295
|
inlineStyleKeys: record.inlineStyleKeys,
|
|
37196
|
-
parentElementId,
|
|
37197
|
-
parentElementKey: parentNode ? parentNode.key : parentElementId === null ? null : toLayoutElementKey(solid.file, parentElementId),
|
|
37198
37296
|
parentElementNode: parentNode,
|
|
37199
37297
|
previousSiblingNode,
|
|
37200
37298
|
siblingIndex,
|
|
@@ -37235,22 +37333,25 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37235
37333
|
logger.debug(`[build] rootElementsByFile file=${file} count=${roots.length}: ${descs.join(", ")}`);
|
|
37236
37334
|
}
|
|
37237
37335
|
}
|
|
37238
|
-
const
|
|
37336
|
+
const selectorCandidatesByNode = buildSelectorCandidatesByNode(elements, scopedSelectorsBySolidFile, perf);
|
|
37337
|
+
const selectorMatchCtx = {
|
|
37338
|
+
selectorMetadataById,
|
|
37339
|
+
selectorsById,
|
|
37340
|
+
rootElementsByFile,
|
|
37341
|
+
perf,
|
|
37342
|
+
logger
|
|
37343
|
+
};
|
|
37239
37344
|
for (let i = 0; i < elements.length; i++) {
|
|
37240
37345
|
const node = elements[i];
|
|
37241
37346
|
if (!node) continue;
|
|
37242
|
-
const selectorIds =
|
|
37347
|
+
const selectorIds = selectorCandidatesByNode.get(node) ?? EMPTY_NUMBER_LIST2;
|
|
37243
37348
|
if (selectorIds.length === 0) continue;
|
|
37244
37349
|
appendMatchingEdgesFromSelectorIds(
|
|
37350
|
+
selectorMatchCtx,
|
|
37245
37351
|
selectorIds,
|
|
37246
37352
|
node,
|
|
37247
|
-
selectorMetadataById,
|
|
37248
|
-
selectorsById,
|
|
37249
37353
|
applies,
|
|
37250
|
-
appliesByElementNodeMutable
|
|
37251
|
-
perf,
|
|
37252
|
-
rootElementsByFile,
|
|
37253
|
-
logger
|
|
37354
|
+
appliesByElementNodeMutable
|
|
37254
37355
|
);
|
|
37255
37356
|
}
|
|
37256
37357
|
perf.selectorMatchMs = performance.now() - selectorMatchStartedAt;
|
|
@@ -37258,7 +37359,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37258
37359
|
for (const edges of appliesByElementNodeMutable.values()) {
|
|
37259
37360
|
edges.sort(compareLayoutEdge);
|
|
37260
37361
|
}
|
|
37261
|
-
const
|
|
37362
|
+
const appliesByNode = /* @__PURE__ */ new Map();
|
|
37262
37363
|
const tailwind = css.tailwind;
|
|
37263
37364
|
for (let i = 0; i < elements.length; i++) {
|
|
37264
37365
|
const node = elements[i];
|
|
@@ -37266,7 +37367,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37266
37367
|
const edges = appliesByElementNodeMutable.get(node) ?? [];
|
|
37267
37368
|
const cascade = buildCascadeMapForElement(node, edges, monitoredDeclarationsBySelectorId, tailwind);
|
|
37268
37369
|
cascadeByElementNode.set(node, cascade);
|
|
37269
|
-
|
|
37370
|
+
appliesByNode.set(node, edges);
|
|
37270
37371
|
}
|
|
37271
37372
|
perf.cascadeBuildMs = performance.now() - cascadeStartedAt;
|
|
37272
37373
|
const snapshotByElementNode = buildSignalSnapshotIndex(elements, cascadeByElementNode, perf);
|
|
@@ -37274,7 +37375,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37274
37375
|
const factIndex = buildElementFactIndex(elements, snapshotByElementNode);
|
|
37275
37376
|
const conditionalDeltaIndex = buildConditionalDeltaIndex(
|
|
37276
37377
|
elements,
|
|
37277
|
-
|
|
37378
|
+
appliesByNode,
|
|
37278
37379
|
monitoredDeclarationsBySelectorId
|
|
37279
37380
|
);
|
|
37280
37381
|
const elementsWithConditionalOverflowDelta = buildConditionalDeltaSignalGroupElements(
|
|
@@ -37292,7 +37393,7 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37292
37393
|
contextByParentNode,
|
|
37293
37394
|
measurementNodeByRootKey,
|
|
37294
37395
|
snapshotByElementNode,
|
|
37295
|
-
|
|
37396
|
+
snapshotHotSignalsByNode: factIndex.snapshotHotSignalsByNode
|
|
37296
37397
|
});
|
|
37297
37398
|
finalizeTableCellBaselineRelevance(contextByParentNode, cohortIndex.verticalAlignConsensusByParent);
|
|
37298
37399
|
perf.conditionalSignals = cohortIndex.conditionalSignals;
|
|
@@ -37308,11 +37409,11 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37308
37409
|
childrenByParentNode: childrenByParentNodeMutable,
|
|
37309
37410
|
elementBySolidFileAndId: elementBySolidFileAndIdMutable,
|
|
37310
37411
|
elementRefsBySolidFileAndId: elementRefsBySolidFileAndIdMutable,
|
|
37311
|
-
|
|
37312
|
-
|
|
37412
|
+
appliesByNode,
|
|
37413
|
+
selectorCandidatesByNode,
|
|
37313
37414
|
selectorsById,
|
|
37314
37415
|
measurementNodeByRootKey,
|
|
37315
|
-
|
|
37416
|
+
snapshotHotSignalsByNode: factIndex.snapshotHotSignalsByNode,
|
|
37316
37417
|
elementsByTagName: factIndex.elementsByTagName,
|
|
37317
37418
|
elementsWithConditionalDeltaBySignal: conditionalDeltaIndex.elementsWithConditionalDeltaBySignal,
|
|
37318
37419
|
elementsWithConditionalOverflowDelta,
|
|
@@ -37320,12 +37421,12 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37320
37421
|
elementsByKnownSignalValue: factIndex.elementsByKnownSignalValue,
|
|
37321
37422
|
dynamicSlotCandidateElements: factIndex.dynamicSlotCandidateElements,
|
|
37322
37423
|
scrollContainerElements: factIndex.scrollContainerElements,
|
|
37323
|
-
|
|
37324
|
-
|
|
37325
|
-
|
|
37326
|
-
|
|
37327
|
-
|
|
37328
|
-
|
|
37424
|
+
reservedSpaceFactsByNode: factIndex.reservedSpaceFactsByNode,
|
|
37425
|
+
scrollContainerFactsByNode: factIndex.scrollContainerFactsByNode,
|
|
37426
|
+
flowParticipationFactsByNode: factIndex.flowParticipationFactsByNode,
|
|
37427
|
+
containingBlockFactsByNode: factIndex.containingBlockFactsByNode,
|
|
37428
|
+
conditionalSignalDeltaFactsByNode: conditionalDeltaIndex.conditionalSignalDeltaFactsByNode,
|
|
37429
|
+
baselineOffsetFactsByNode: conditionalDeltaIndex.baselineOffsetFactsByNode,
|
|
37329
37430
|
statefulSelectorEntriesByRuleId: statefulRuleIndexes.selectorEntriesByRuleId,
|
|
37330
37431
|
statefulNormalizedDeclarationsByRuleId: statefulRuleIndexes.normalizedDeclarationsByRuleId,
|
|
37331
37432
|
statefulBaseValueIndex: statefulRuleIndexes.baseValueIndex,
|
|
@@ -37337,11 +37438,11 @@ function buildLayoutGraph(solids, css, logger = noopLogger) {
|
|
|
37337
37438
|
};
|
|
37338
37439
|
}
|
|
37339
37440
|
function buildElementFactIndex(elements, snapshotByElementNode) {
|
|
37340
|
-
const
|
|
37341
|
-
const
|
|
37342
|
-
const
|
|
37343
|
-
const
|
|
37344
|
-
const
|
|
37441
|
+
const reservedSpaceFactsByNode = /* @__PURE__ */ new Map();
|
|
37442
|
+
const scrollContainerFactsByNode = /* @__PURE__ */ new Map();
|
|
37443
|
+
const flowParticipationFactsByNode = /* @__PURE__ */ new Map();
|
|
37444
|
+
const containingBlockFactsByNode = /* @__PURE__ */ new Map();
|
|
37445
|
+
const snapshotHotSignalsByNode = /* @__PURE__ */ new Map();
|
|
37345
37446
|
const elementsByTagName = /* @__PURE__ */ new Map();
|
|
37346
37447
|
const elementsByKnownSignalValue = /* @__PURE__ */ new Map();
|
|
37347
37448
|
const dynamicSlotCandidateElements = [];
|
|
@@ -37351,7 +37452,7 @@ function buildElementFactIndex(elements, snapshotByElementNode) {
|
|
|
37351
37452
|
const node = elements[i];
|
|
37352
37453
|
if (!node) continue;
|
|
37353
37454
|
const snapshot = snapshotByElementNode.get(node);
|
|
37354
|
-
if (node.textualContent ===
|
|
37455
|
+
if (node.textualContent === 2 /* Unknown */ && node.siblingCount >= 2) {
|
|
37355
37456
|
dynamicSlotCandidateElements.push(node);
|
|
37356
37457
|
}
|
|
37357
37458
|
if (node.tagName) {
|
|
@@ -37372,18 +37473,18 @@ function buildElementFactIndex(elements, snapshotByElementNode) {
|
|
|
37372
37473
|
nearestPositionedAncestorHasReservedSpace = parentPositioned.hasReservedSpace;
|
|
37373
37474
|
}
|
|
37374
37475
|
}
|
|
37375
|
-
|
|
37476
|
+
containingBlockFactsByNode.set(node, {
|
|
37376
37477
|
nearestPositionedAncestorKey,
|
|
37377
37478
|
nearestPositionedAncestorHasReservedSpace
|
|
37378
37479
|
});
|
|
37379
37480
|
if (!snapshot) continue;
|
|
37380
37481
|
const reservedSpaceFact = computeReservedSpaceFact(snapshot);
|
|
37381
|
-
|
|
37482
|
+
reservedSpaceFactsByNode.set(node, reservedSpaceFact);
|
|
37382
37483
|
const scrollFact = computeScrollContainerFact(snapshot);
|
|
37383
|
-
|
|
37484
|
+
scrollContainerFactsByNode.set(node, scrollFact);
|
|
37384
37485
|
if (scrollFact.isScrollContainer) scrollContainerElements.push(node);
|
|
37385
|
-
|
|
37386
|
-
|
|
37486
|
+
flowParticipationFactsByNode.set(node, computeFlowParticipationFact(snapshot));
|
|
37487
|
+
snapshotHotSignalsByNode.set(node, computeHotSignals(snapshot));
|
|
37387
37488
|
const positionSignal = snapshot.signals.get("position");
|
|
37388
37489
|
const isPositioned = positionSignal !== void 0 && positionSignal.kind === "known" && positionSignal.normalized !== "static";
|
|
37389
37490
|
if (isPositioned) {
|
|
@@ -37414,49 +37515,163 @@ function buildElementFactIndex(elements, snapshotByElementNode) {
|
|
|
37414
37515
|
}
|
|
37415
37516
|
}
|
|
37416
37517
|
return {
|
|
37417
|
-
|
|
37418
|
-
|
|
37518
|
+
reservedSpaceFactsByNode,
|
|
37519
|
+
scrollContainerFactsByNode,
|
|
37419
37520
|
scrollContainerElements,
|
|
37420
|
-
|
|
37421
|
-
|
|
37422
|
-
|
|
37521
|
+
flowParticipationFactsByNode,
|
|
37522
|
+
containingBlockFactsByNode,
|
|
37523
|
+
snapshotHotSignalsByNode,
|
|
37423
37524
|
elementsByTagName,
|
|
37424
37525
|
elementsByKnownSignalValue,
|
|
37425
37526
|
dynamicSlotCandidateElements
|
|
37426
37527
|
};
|
|
37427
37528
|
}
|
|
37428
|
-
|
|
37529
|
+
var ABSENT_NUMERIC = Object.freeze({
|
|
37530
|
+
present: false,
|
|
37531
|
+
value: null,
|
|
37532
|
+
kind: 3 /* Unknown */
|
|
37533
|
+
});
|
|
37534
|
+
var ABSENT_NORMALIZED = Object.freeze({
|
|
37535
|
+
present: false,
|
|
37536
|
+
value: null,
|
|
37537
|
+
kind: 3 /* Unknown */
|
|
37538
|
+
});
|
|
37539
|
+
function toHotNumeric(signal) {
|
|
37540
|
+
if (signal.kind !== "known") {
|
|
37541
|
+
return {
|
|
37542
|
+
present: true,
|
|
37543
|
+
value: null,
|
|
37544
|
+
kind: signal.guard.kind === 1 /* Conditional */ ? 2 /* Conditional */ : 3 /* Unknown */
|
|
37545
|
+
};
|
|
37546
|
+
}
|
|
37429
37547
|
return {
|
|
37430
|
-
|
|
37431
|
-
|
|
37432
|
-
|
|
37433
|
-
placeSelf: computeHotNormalized(snapshot, "place-self"),
|
|
37434
|
-
writingMode: computeHotNormalized(snapshot, "writing-mode"),
|
|
37435
|
-
direction: computeHotNormalized(snapshot, "direction"),
|
|
37436
|
-
display: computeHotNormalized(snapshot, "display"),
|
|
37437
|
-
alignItems: computeHotNormalized(snapshot, "align-items"),
|
|
37438
|
-
placeItems: computeHotNormalized(snapshot, "place-items"),
|
|
37439
|
-
position: computeHotNormalized(snapshot, "position"),
|
|
37440
|
-
insetBlockStart: computeHotNumeric(snapshot, "inset-block-start"),
|
|
37441
|
-
insetBlockEnd: computeHotNumeric(snapshot, "inset-block-end"),
|
|
37442
|
-
transform: computeHotNumeric(snapshot, "transform"),
|
|
37443
|
-
translate: computeHotNumeric(snapshot, "translate"),
|
|
37444
|
-
top: computeHotNumeric(snapshot, "top"),
|
|
37445
|
-
bottom: computeHotNumeric(snapshot, "bottom"),
|
|
37446
|
-
marginTop: computeHotNumeric(snapshot, "margin-top"),
|
|
37447
|
-
marginBottom: computeHotNumeric(snapshot, "margin-bottom")
|
|
37548
|
+
present: true,
|
|
37549
|
+
value: signal.px,
|
|
37550
|
+
kind: signal.guard.kind === 1 /* Conditional */ ? 2 /* Conditional */ : signal.quality === "estimated" ? 1 /* Interval */ : 0 /* Exact */
|
|
37448
37551
|
};
|
|
37449
37552
|
}
|
|
37450
|
-
function
|
|
37553
|
+
function toHotNormalized(signal) {
|
|
37554
|
+
if (signal.kind !== "known") {
|
|
37555
|
+
return {
|
|
37556
|
+
present: true,
|
|
37557
|
+
value: null,
|
|
37558
|
+
kind: signal.guard.kind === 1 /* Conditional */ ? 2 /* Conditional */ : 3 /* Unknown */
|
|
37559
|
+
};
|
|
37560
|
+
}
|
|
37451
37561
|
return {
|
|
37452
|
-
present:
|
|
37453
|
-
|
|
37562
|
+
present: true,
|
|
37563
|
+
value: signal.normalized,
|
|
37564
|
+
kind: signal.guard.kind === 1 /* Conditional */ ? 2 /* Conditional */ : signal.quality === "estimated" ? 1 /* Interval */ : 0 /* Exact */
|
|
37454
37565
|
};
|
|
37455
37566
|
}
|
|
37456
|
-
function
|
|
37567
|
+
function computeHotSignals(snapshot) {
|
|
37568
|
+
let lineHeight = ABSENT_NUMERIC;
|
|
37569
|
+
let verticalAlign = ABSENT_NORMALIZED;
|
|
37570
|
+
let alignSelf = ABSENT_NORMALIZED;
|
|
37571
|
+
let placeSelf = ABSENT_NORMALIZED;
|
|
37572
|
+
let flexDirection = ABSENT_NORMALIZED;
|
|
37573
|
+
let gridAutoFlow = ABSENT_NORMALIZED;
|
|
37574
|
+
let writingMode = ABSENT_NORMALIZED;
|
|
37575
|
+
let direction = ABSENT_NORMALIZED;
|
|
37576
|
+
let display = ABSENT_NORMALIZED;
|
|
37577
|
+
let alignItems = ABSENT_NORMALIZED;
|
|
37578
|
+
let placeItems = ABSENT_NORMALIZED;
|
|
37579
|
+
let position = ABSENT_NORMALIZED;
|
|
37580
|
+
let insetBlockStart = ABSENT_NUMERIC;
|
|
37581
|
+
let insetBlockEnd = ABSENT_NUMERIC;
|
|
37582
|
+
let transform = ABSENT_NUMERIC;
|
|
37583
|
+
let translate = ABSENT_NUMERIC;
|
|
37584
|
+
let top = ABSENT_NUMERIC;
|
|
37585
|
+
let bottom = ABSENT_NUMERIC;
|
|
37586
|
+
let marginTop = ABSENT_NUMERIC;
|
|
37587
|
+
let marginBottom = ABSENT_NUMERIC;
|
|
37588
|
+
for (const [name, value2] of snapshot.signals) {
|
|
37589
|
+
switch (name) {
|
|
37590
|
+
case "line-height":
|
|
37591
|
+
lineHeight = toHotNumeric(value2);
|
|
37592
|
+
break;
|
|
37593
|
+
case "vertical-align":
|
|
37594
|
+
verticalAlign = toHotNormalized(value2);
|
|
37595
|
+
break;
|
|
37596
|
+
case "align-self":
|
|
37597
|
+
alignSelf = toHotNormalized(value2);
|
|
37598
|
+
break;
|
|
37599
|
+
case "place-self":
|
|
37600
|
+
placeSelf = toHotNormalized(value2);
|
|
37601
|
+
break;
|
|
37602
|
+
case "flex-direction":
|
|
37603
|
+
flexDirection = toHotNormalized(value2);
|
|
37604
|
+
break;
|
|
37605
|
+
case "grid-auto-flow":
|
|
37606
|
+
gridAutoFlow = toHotNormalized(value2);
|
|
37607
|
+
break;
|
|
37608
|
+
case "writing-mode":
|
|
37609
|
+
writingMode = toHotNormalized(value2);
|
|
37610
|
+
break;
|
|
37611
|
+
case "direction":
|
|
37612
|
+
direction = toHotNormalized(value2);
|
|
37613
|
+
break;
|
|
37614
|
+
case "display":
|
|
37615
|
+
display = toHotNormalized(value2);
|
|
37616
|
+
break;
|
|
37617
|
+
case "align-items":
|
|
37618
|
+
alignItems = toHotNormalized(value2);
|
|
37619
|
+
break;
|
|
37620
|
+
case "place-items":
|
|
37621
|
+
placeItems = toHotNormalized(value2);
|
|
37622
|
+
break;
|
|
37623
|
+
case "position":
|
|
37624
|
+
position = toHotNormalized(value2);
|
|
37625
|
+
break;
|
|
37626
|
+
case "inset-block-start":
|
|
37627
|
+
insetBlockStart = toHotNumeric(value2);
|
|
37628
|
+
break;
|
|
37629
|
+
case "inset-block-end":
|
|
37630
|
+
insetBlockEnd = toHotNumeric(value2);
|
|
37631
|
+
break;
|
|
37632
|
+
case "transform":
|
|
37633
|
+
transform = toHotNumeric(value2);
|
|
37634
|
+
break;
|
|
37635
|
+
case "translate":
|
|
37636
|
+
translate = toHotNumeric(value2);
|
|
37637
|
+
break;
|
|
37638
|
+
case "top":
|
|
37639
|
+
top = toHotNumeric(value2);
|
|
37640
|
+
break;
|
|
37641
|
+
case "bottom":
|
|
37642
|
+
bottom = toHotNumeric(value2);
|
|
37643
|
+
break;
|
|
37644
|
+
case "margin-top":
|
|
37645
|
+
marginTop = toHotNumeric(value2);
|
|
37646
|
+
break;
|
|
37647
|
+
case "margin-bottom":
|
|
37648
|
+
marginBottom = toHotNumeric(value2);
|
|
37649
|
+
break;
|
|
37650
|
+
default:
|
|
37651
|
+
break;
|
|
37652
|
+
}
|
|
37653
|
+
}
|
|
37457
37654
|
return {
|
|
37458
|
-
|
|
37459
|
-
|
|
37655
|
+
lineHeight,
|
|
37656
|
+
verticalAlign,
|
|
37657
|
+
alignSelf,
|
|
37658
|
+
placeSelf,
|
|
37659
|
+
flexDirection,
|
|
37660
|
+
gridAutoFlow,
|
|
37661
|
+
writingMode,
|
|
37662
|
+
direction,
|
|
37663
|
+
display,
|
|
37664
|
+
alignItems,
|
|
37665
|
+
placeItems,
|
|
37666
|
+
position,
|
|
37667
|
+
insetBlockStart,
|
|
37668
|
+
insetBlockEnd,
|
|
37669
|
+
transform,
|
|
37670
|
+
translate,
|
|
37671
|
+
top,
|
|
37672
|
+
bottom,
|
|
37673
|
+
marginTop,
|
|
37674
|
+
marginBottom
|
|
37460
37675
|
};
|
|
37461
37676
|
}
|
|
37462
37677
|
function computeReservedSpaceFact(snapshot) {
|
|
@@ -37491,15 +37706,14 @@ function computeReservedSpaceFact(snapshot) {
|
|
|
37491
37706
|
function hasPositiveOrDeclaredDimension(snapshot, property) {
|
|
37492
37707
|
const signal = snapshot.signals.get(property);
|
|
37493
37708
|
if (!signal) return false;
|
|
37494
|
-
if (signal.guard !==
|
|
37709
|
+
if (signal.guard.kind !== 0 /* Unconditional */) return false;
|
|
37495
37710
|
let normalized = "";
|
|
37496
37711
|
if (signal.kind === "known") {
|
|
37497
37712
|
if (signal.px !== null) return signal.px > 0;
|
|
37498
37713
|
normalized = signal.normalized.trim().toLowerCase();
|
|
37499
37714
|
}
|
|
37500
37715
|
if (signal.kind === "unknown") {
|
|
37501
|
-
|
|
37502
|
-
normalized = signal.raw.trim().toLowerCase();
|
|
37716
|
+
return signal.source !== null;
|
|
37503
37717
|
}
|
|
37504
37718
|
if (normalized.length === 0) return false;
|
|
37505
37719
|
if (isNonReservingDimension(normalized)) return false;
|
|
@@ -37508,15 +37722,14 @@ function hasPositiveOrDeclaredDimension(snapshot, property) {
|
|
|
37508
37722
|
function hasUsableAspectRatio(snapshot) {
|
|
37509
37723
|
const signal = snapshot.signals.get("aspect-ratio");
|
|
37510
37724
|
if (!signal) return false;
|
|
37511
|
-
if (signal.guard !==
|
|
37725
|
+
if (signal.guard.kind !== 0 /* Unconditional */) return false;
|
|
37726
|
+
if (signal.kind === "unknown") {
|
|
37727
|
+
return false;
|
|
37728
|
+
}
|
|
37512
37729
|
let normalized = "";
|
|
37513
37730
|
if (signal.kind === "known") {
|
|
37514
37731
|
normalized = signal.normalized.trim().toLowerCase();
|
|
37515
37732
|
}
|
|
37516
|
-
if (signal.kind === "unknown") {
|
|
37517
|
-
if (signal.raw === null) return false;
|
|
37518
|
-
normalized = signal.raw.trim().toLowerCase();
|
|
37519
|
-
}
|
|
37520
37733
|
if (normalized.length === 0) return false;
|
|
37521
37734
|
return normalized !== "auto";
|
|
37522
37735
|
}
|
|
@@ -37534,8 +37747,8 @@ function computeScrollContainerFact(snapshot) {
|
|
|
37534
37747
|
const yFromLonghand = parseSingleAxisScroll(overflowY);
|
|
37535
37748
|
const xScroll = shorthandAxis.x;
|
|
37536
37749
|
const yScroll = yFromLonghand === null ? shorthandAxis.y : yFromLonghand;
|
|
37537
|
-
const hasConditionalScroll = overflowSignal?.guard ===
|
|
37538
|
-
const hasUnconditionalScroll = overflowSignal?.guard ===
|
|
37750
|
+
const hasConditionalScroll = overflowSignal?.guard.kind === 1 /* Conditional */ && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 1 /* Conditional */ && yFromLonghand === true;
|
|
37751
|
+
const hasUnconditionalScroll = overflowSignal?.guard.kind === 0 /* Unconditional */ && (shorthandAxis.x || shorthandAxis.y) || overflowYSignal?.guard.kind === 0 /* Unconditional */ && yFromLonghand === true;
|
|
37539
37752
|
return {
|
|
37540
37753
|
isScrollContainer: xScroll || yScroll,
|
|
37541
37754
|
axis: toScrollAxis(xScroll, yScroll),
|
|
@@ -37545,18 +37758,18 @@ function computeScrollContainerFact(snapshot) {
|
|
|
37545
37758
|
hasUnconditionalScroll
|
|
37546
37759
|
};
|
|
37547
37760
|
}
|
|
37761
|
+
var NO_SCROLL = Object.freeze({ x: false, y: false });
|
|
37762
|
+
var BOTH_SCROLL = Object.freeze({ x: true, y: true });
|
|
37548
37763
|
function parseOverflowShorthandAxis(value2) {
|
|
37549
|
-
if (value2 === null) return
|
|
37550
|
-
const
|
|
37551
|
-
|
|
37552
|
-
|
|
37553
|
-
|
|
37554
|
-
|
|
37555
|
-
|
|
37556
|
-
|
|
37557
|
-
|
|
37558
|
-
const second = tokens[1];
|
|
37559
|
-
if (!second) return { x: SCROLLABLE_VALUES.has(first), y: false };
|
|
37764
|
+
if (value2 === null) return NO_SCROLL;
|
|
37765
|
+
const trimmed = value2.trim();
|
|
37766
|
+
const spaceIdx = trimmed.indexOf(" ");
|
|
37767
|
+
if (spaceIdx === -1) {
|
|
37768
|
+
const scroll = SCROLLABLE_VALUES.has(trimmed);
|
|
37769
|
+
return scroll ? BOTH_SCROLL : NO_SCROLL;
|
|
37770
|
+
}
|
|
37771
|
+
const first = trimmed.slice(0, spaceIdx);
|
|
37772
|
+
const second = trimmed.slice(spaceIdx + 1).trimStart();
|
|
37560
37773
|
return {
|
|
37561
37774
|
x: SCROLLABLE_VALUES.has(first),
|
|
37562
37775
|
y: SCROLLABLE_VALUES.has(second)
|
|
@@ -37564,16 +37777,16 @@ function parseOverflowShorthandAxis(value2) {
|
|
|
37564
37777
|
}
|
|
37565
37778
|
function parseSingleAxisScroll(value2) {
|
|
37566
37779
|
if (value2 === null) return null;
|
|
37567
|
-
const
|
|
37568
|
-
const
|
|
37569
|
-
|
|
37780
|
+
const trimmed = value2.trim();
|
|
37781
|
+
const spaceIdx = trimmed.indexOf(" ");
|
|
37782
|
+
const first = spaceIdx === -1 ? trimmed : trimmed.slice(0, spaceIdx);
|
|
37570
37783
|
return SCROLLABLE_VALUES.has(first);
|
|
37571
37784
|
}
|
|
37572
37785
|
function toScrollAxis(x, y) {
|
|
37573
|
-
if (x && y) return
|
|
37574
|
-
if (x) return
|
|
37575
|
-
if (y) return
|
|
37576
|
-
return
|
|
37786
|
+
if (x && y) return 3 /* Both */;
|
|
37787
|
+
if (x) return 1 /* X */;
|
|
37788
|
+
if (y) return 2 /* Y */;
|
|
37789
|
+
return 0 /* None */;
|
|
37577
37790
|
}
|
|
37578
37791
|
function computeFlowParticipationFact(snapshot) {
|
|
37579
37792
|
const signal = snapshot.signals.get("position");
|
|
@@ -37590,8 +37803,8 @@ function computeFlowParticipationFact(snapshot) {
|
|
|
37590
37803
|
return {
|
|
37591
37804
|
inFlow: !outOfFlow,
|
|
37592
37805
|
position,
|
|
37593
|
-
hasConditionalOutOfFlow: signal.guard ===
|
|
37594
|
-
hasUnconditionalOutOfFlow: signal.guard ===
|
|
37806
|
+
hasConditionalOutOfFlow: signal.guard.kind === 1 /* Conditional */ && outOfFlow,
|
|
37807
|
+
hasUnconditionalOutOfFlow: signal.guard.kind === 0 /* Unconditional */ && outOfFlow
|
|
37595
37808
|
};
|
|
37596
37809
|
}
|
|
37597
37810
|
function buildContextIndex(childrenByParentNode, snapshotByElementNode, perf) {
|
|
@@ -37666,7 +37879,7 @@ function collectAlignmentCases(context) {
|
|
|
37666
37879
|
subjectDeclaredOffsetDeviation,
|
|
37667
37880
|
subjectEffectiveOffsetDeviation,
|
|
37668
37881
|
subjectLineHeightDeviation,
|
|
37669
|
-
subjectStats.element.snapshot.textualContent,
|
|
37882
|
+
subjectStats.element.snapshot.node.textualContent,
|
|
37670
37883
|
subjectStats.element,
|
|
37671
37884
|
subjectStats.contentComposition,
|
|
37672
37885
|
cohortContentCompositions
|
|
@@ -37759,26 +37972,26 @@ function coverageFromNumeric(value2) {
|
|
|
37759
37972
|
}
|
|
37760
37973
|
function coverageFromConflict(value2) {
|
|
37761
37974
|
const certainty = coverageFromKind(value2.kind);
|
|
37762
|
-
if (value2.value ===
|
|
37975
|
+
if (value2.value === 2 /* Unknown */) return certainty * 0.4;
|
|
37763
37976
|
return certainty;
|
|
37764
37977
|
}
|
|
37765
37978
|
function coverageFromTextContrast(value2) {
|
|
37766
|
-
if (value2 ===
|
|
37979
|
+
if (value2 === 2 /* Unknown */) return 0.35;
|
|
37767
37980
|
return 1;
|
|
37768
37981
|
}
|
|
37769
37982
|
function coverageFromSubjectText(subjectTextualContent) {
|
|
37770
|
-
if (subjectTextualContent ===
|
|
37983
|
+
if (subjectTextualContent === 2 /* Unknown */) return 0.35;
|
|
37771
37984
|
return 1;
|
|
37772
37985
|
}
|
|
37773
37986
|
function coverageFromContextCertainty(certainty) {
|
|
37774
|
-
if (certainty ===
|
|
37775
|
-
if (certainty ===
|
|
37987
|
+
if (certainty === 0 /* Resolved */) return 1;
|
|
37988
|
+
if (certainty === 1 /* Conditional */) return 0.55;
|
|
37776
37989
|
return 0.25;
|
|
37777
37990
|
}
|
|
37778
37991
|
function coverageFromKind(kind) {
|
|
37779
|
-
if (kind ===
|
|
37780
|
-
if (kind ===
|
|
37781
|
-
if (kind ===
|
|
37992
|
+
if (kind === 0 /* Exact */) return 1;
|
|
37993
|
+
if (kind === 1 /* Interval */) return 0.78;
|
|
37994
|
+
if (kind === 2 /* Conditional */) return 0.5;
|
|
37782
37995
|
return 0.2;
|
|
37783
37996
|
}
|
|
37784
37997
|
function averageCoverage(...values) {
|
|
@@ -37811,24 +38024,7 @@ function resolveEffectiveAlignmentContext(parentContext, child, measurementNode,
|
|
|
37811
38024
|
const childContext = contextByParentNode.get(child);
|
|
37812
38025
|
if (!childContext) return parentContext;
|
|
37813
38026
|
if (childContext.baselineRelevance !== "irrelevant") return parentContext;
|
|
37814
|
-
return {
|
|
37815
|
-
kind: parentContext.kind,
|
|
37816
|
-
certainty: parentContext.certainty,
|
|
37817
|
-
parentSolidFile: parentContext.parentSolidFile,
|
|
37818
|
-
parentElementId: parentContext.parentElementId,
|
|
37819
|
-
parentElementKey: parentContext.parentElementKey,
|
|
37820
|
-
parentTag: parentContext.parentTag,
|
|
37821
|
-
axis: parentContext.axis,
|
|
37822
|
-
axisCertainty: parentContext.axisCertainty,
|
|
37823
|
-
inlineDirection: parentContext.inlineDirection,
|
|
37824
|
-
inlineDirectionCertainty: parentContext.inlineDirectionCertainty,
|
|
37825
|
-
parentDisplay: parentContext.parentDisplay,
|
|
37826
|
-
parentAlignItems: parentContext.parentAlignItems,
|
|
37827
|
-
parentPlaceItems: parentContext.parentPlaceItems,
|
|
37828
|
-
hasPositionedOffset: parentContext.hasPositionedOffset,
|
|
37829
|
-
baselineRelevance: "irrelevant",
|
|
37830
|
-
evidence: parentContext.evidence
|
|
37831
|
-
};
|
|
38027
|
+
return deriveAlignmentContext(parentContext, { baselineRelevance: "irrelevant" });
|
|
37832
38028
|
}
|
|
37833
38029
|
function compareAlignmentCaseOrder(left, right) {
|
|
37834
38030
|
if (left.subject.solidFile < right.subject.solidFile) return -1;
|
|
@@ -37847,12 +38043,12 @@ function buildConsistencyEvidence(input) {
|
|
|
37847
38043
|
input.cohortProfile.medianLineHeightPx,
|
|
37848
38044
|
input.cohortProfile.medianDeclaredOffsetPx
|
|
37849
38045
|
);
|
|
37850
|
-
const
|
|
38046
|
+
const offsetRaw = normalizeDeviation(
|
|
37851
38047
|
input.subjectEffectiveOffsetDeviation,
|
|
37852
38048
|
input.cohortProfile.effectiveOffsetDispersionPx,
|
|
37853
38049
|
effectiveOffsetScaleReference
|
|
37854
38050
|
);
|
|
37855
|
-
const
|
|
38051
|
+
const declaredOffsetRaw = normalizeDeviation(
|
|
37856
38052
|
input.subjectDeclaredOffsetDeviation,
|
|
37857
38053
|
input.cohortProfile.declaredOffsetDispersionPx,
|
|
37858
38054
|
declaredOffsetScaleReference
|
|
@@ -37863,10 +38059,15 @@ function buildConsistencyEvidence(input) {
|
|
|
37863
38059
|
input.cohortProfile.medianLineHeightPx
|
|
37864
38060
|
);
|
|
37865
38061
|
const baselinesIrrelevant = input.context.baselineRelevance === "irrelevant";
|
|
37866
|
-
const
|
|
37867
|
-
const
|
|
37868
|
-
const
|
|
37869
|
-
const
|
|
38062
|
+
const blockAxisIsMainAxis = !input.context.crossAxisIsBlockAxis;
|
|
38063
|
+
const suppressAll = blockAxisIsMainAxis;
|
|
38064
|
+
const offset = suppressAll ? ZERO_STRENGTH : offsetRaw;
|
|
38065
|
+
const declaredOffset = suppressAll ? ZERO_STRENGTH : declaredOffsetRaw;
|
|
38066
|
+
const baselineStrength = baselinesIrrelevant || suppressAll ? ZERO_STRENGTH : resolveBaselineStrength(input, lineHeight);
|
|
38067
|
+
const contextStrength = baselinesIrrelevant || suppressAll ? ZERO_STRENGTH : resolveContextStrength(input, lineHeight);
|
|
38068
|
+
const replacedStrength = baselinesIrrelevant || suppressAll ? ZERO_STRENGTH : resolveReplacedControlStrength(input, lineHeight);
|
|
38069
|
+
const compositionResult = baselinesIrrelevant || suppressAll ? null : resolveContentCompositionStrength(input);
|
|
38070
|
+
const compositionStrength = compositionResult ? compositionResult.evidence : ZERO_STRENGTH;
|
|
37870
38071
|
const contextCertaintyPenalty = resolveContextCertaintyPenalty(input);
|
|
37871
38072
|
const provenance = input.cohortProvenance;
|
|
37872
38073
|
const atoms = buildEvidenceAtoms(
|
|
@@ -37887,6 +38088,7 @@ function buildConsistencyEvidence(input) {
|
|
|
37887
38088
|
contextStrength: contextStrength.strength,
|
|
37888
38089
|
replacedStrength: replacedStrength.strength,
|
|
37889
38090
|
compositionStrength: compositionStrength.strength,
|
|
38091
|
+
majorityClassification: compositionResult ? compositionResult.divergence.majorityClassification : 5 /* Unknown */,
|
|
37890
38092
|
identifiability: input.subjectIdentifiability,
|
|
37891
38093
|
factSummary,
|
|
37892
38094
|
atoms
|
|
@@ -37922,7 +38124,7 @@ function resolveOffsetScaleReference(medianLineHeightPx, fallbackMedianOffsetPx)
|
|
|
37922
38124
|
}
|
|
37923
38125
|
function resolveBaselineStrength(input, lineHeight) {
|
|
37924
38126
|
const verticalAlign = input.cohortSignals.verticalAlign;
|
|
37925
|
-
const hasConflict = verticalAlign.value ===
|
|
38127
|
+
const hasConflict = verticalAlign.value === 0 /* Conflict */;
|
|
37926
38128
|
const conflict = hasConflict ? alignmentStrengthCalibration.baselineConflictBoost : 0;
|
|
37927
38129
|
const kind = resolveBaselineEvidenceKind(lineHeight.kind, verticalAlign.kind, hasConflict);
|
|
37928
38130
|
return {
|
|
@@ -37932,7 +38134,7 @@ function resolveBaselineStrength(input, lineHeight) {
|
|
|
37932
38134
|
}
|
|
37933
38135
|
function resolveBaselineEvidenceKind(lineHeightKind, verticalAlignKind, hasConflict) {
|
|
37934
38136
|
if (!hasConflict) return mergeEvidenceKind(lineHeightKind, verticalAlignKind);
|
|
37935
|
-
if (lineHeightKind ===
|
|
38137
|
+
if (lineHeightKind === 3 /* Unknown */) return verticalAlignKind;
|
|
37936
38138
|
return mergeEvidenceKind(lineHeightKind, verticalAlignKind);
|
|
37937
38139
|
}
|
|
37938
38140
|
function resolveContextStrength(input, lineHeight) {
|
|
@@ -37960,7 +38162,7 @@ function resolveContextConflictEvidence(input) {
|
|
|
37960
38162
|
const alignSelf = input.cohortSignals.alignSelf;
|
|
37961
38163
|
const placeSelf = input.cohortSignals.placeSelf;
|
|
37962
38164
|
const kind = mergeEvidenceKind(alignSelf.kind, placeSelf.kind);
|
|
37963
|
-
const hasConflict = alignSelf.value ===
|
|
38165
|
+
const hasConflict = alignSelf.value === 0 /* Conflict */ || placeSelf.value === 0 /* Conflict */;
|
|
37964
38166
|
if (!hasConflict) {
|
|
37965
38167
|
return {
|
|
37966
38168
|
strength: 0,
|
|
@@ -37974,23 +38176,23 @@ function resolveContextConflictEvidence(input) {
|
|
|
37974
38176
|
}
|
|
37975
38177
|
function resolveReplacedControlStrength(input, lineHeight) {
|
|
37976
38178
|
const subject = input.subject.snapshot;
|
|
37977
|
-
const hasReplacedPair = subject.isControl || subject.isReplaced || input.cohortSignals.hasControlOrReplacedPeer;
|
|
38179
|
+
const hasReplacedPair = subject.node.isControl || subject.node.isReplaced || input.cohortSignals.hasControlOrReplacedPeer;
|
|
37978
38180
|
if (!hasReplacedPair) {
|
|
37979
38181
|
return {
|
|
37980
38182
|
strength: 0,
|
|
37981
38183
|
kind: lineHeight.kind
|
|
37982
38184
|
};
|
|
37983
38185
|
}
|
|
37984
|
-
if (input.cohortSignals.textContrastWithPeers ===
|
|
38186
|
+
if (input.cohortSignals.textContrastWithPeers === 0 /* Different */) {
|
|
37985
38187
|
return {
|
|
37986
38188
|
strength: alignmentStrengthCalibration.replacedDifferentTextBoost,
|
|
37987
|
-
kind:
|
|
38189
|
+
kind: 0 /* Exact */
|
|
37988
38190
|
};
|
|
37989
38191
|
}
|
|
37990
|
-
if (input.cohortSignals.textContrastWithPeers ===
|
|
38192
|
+
if (input.cohortSignals.textContrastWithPeers === 2 /* Unknown */) {
|
|
37991
38193
|
return {
|
|
37992
38194
|
strength: alignmentStrengthCalibration.replacedUnknownTextBoost,
|
|
37993
|
-
kind:
|
|
38195
|
+
kind: 2 /* Conditional */
|
|
37994
38196
|
};
|
|
37995
38197
|
}
|
|
37996
38198
|
return {
|
|
@@ -37999,22 +38201,28 @@ function resolveReplacedControlStrength(input, lineHeight) {
|
|
|
37999
38201
|
};
|
|
38000
38202
|
}
|
|
38001
38203
|
function resolveContentCompositionStrength(input) {
|
|
38002
|
-
const
|
|
38204
|
+
const divergence = resolveCompositionDivergence(
|
|
38003
38205
|
input.subjectContentComposition,
|
|
38004
38206
|
input.cohortContentCompositions,
|
|
38005
38207
|
input.context
|
|
38006
38208
|
);
|
|
38007
|
-
if (
|
|
38209
|
+
if (divergence.strength <= 0) {
|
|
38008
38210
|
return {
|
|
38009
|
-
|
|
38010
|
-
|
|
38211
|
+
evidence: {
|
|
38212
|
+
strength: 0,
|
|
38213
|
+
kind: 0 /* Exact */
|
|
38214
|
+
},
|
|
38215
|
+
divergence
|
|
38011
38216
|
};
|
|
38012
38217
|
}
|
|
38013
38218
|
const subjectClassification = input.subjectContentComposition.classification;
|
|
38014
|
-
const kind = subjectClassification ===
|
|
38219
|
+
const kind = subjectClassification === 5 /* Unknown */ ? 2 /* Conditional */ : 0 /* Exact */;
|
|
38015
38220
|
return {
|
|
38016
|
-
|
|
38017
|
-
|
|
38221
|
+
evidence: {
|
|
38222
|
+
strength: clamp(divergence.strength, 0, 1),
|
|
38223
|
+
kind
|
|
38224
|
+
},
|
|
38225
|
+
divergence
|
|
38018
38226
|
};
|
|
38019
38227
|
}
|
|
38020
38228
|
function resolveContextCertaintyPenalty(input) {
|
|
@@ -38086,9 +38294,9 @@ function buildEvidenceAtoms(input, offset, declaredOffset, baselineStrength, con
|
|
|
38086
38294
|
return out;
|
|
38087
38295
|
}
|
|
38088
38296
|
function mapContextCertaintyToEvidenceKind(certainty) {
|
|
38089
|
-
if (certainty ===
|
|
38090
|
-
if (certainty ===
|
|
38091
|
-
return
|
|
38297
|
+
if (certainty === 0 /* Resolved */) return 0 /* Exact */;
|
|
38298
|
+
if (certainty === 1 /* Conditional */) return 2 /* Conditional */;
|
|
38299
|
+
return 3 /* Unknown */;
|
|
38092
38300
|
}
|
|
38093
38301
|
function pushSupportAtom(out, factorId, valueKind, strength, coverage, provenance) {
|
|
38094
38302
|
pushAtom(out, factorId, valueKind, strength, coverage, provenance, "support");
|
|
@@ -38114,19 +38322,19 @@ function pushAtom(out, factorId, valueKind, strength, coverage, provenance, expe
|
|
|
38114
38322
|
}
|
|
38115
38323
|
function toPositiveContribution(strength, maxWeight, valueKind) {
|
|
38116
38324
|
const contribution = clamp(strength, 0, 2) * maxWeight;
|
|
38117
|
-
if (valueKind ===
|
|
38325
|
+
if (valueKind === 0 /* Exact */) {
|
|
38118
38326
|
return {
|
|
38119
38327
|
min: contribution,
|
|
38120
38328
|
max: contribution
|
|
38121
38329
|
};
|
|
38122
38330
|
}
|
|
38123
|
-
if (valueKind ===
|
|
38331
|
+
if (valueKind === 1 /* Interval */) {
|
|
38124
38332
|
return {
|
|
38125
38333
|
min: contribution * evidenceContributionCalibration.supportIntervalLowerScale,
|
|
38126
38334
|
max: contribution
|
|
38127
38335
|
};
|
|
38128
38336
|
}
|
|
38129
|
-
if (valueKind ===
|
|
38337
|
+
if (valueKind === 2 /* Conditional */) {
|
|
38130
38338
|
return {
|
|
38131
38339
|
min: 0,
|
|
38132
38340
|
max: contribution * evidenceContributionCalibration.supportConditionalUpperScale
|
|
@@ -38139,19 +38347,19 @@ function toPositiveContribution(strength, maxWeight, valueKind) {
|
|
|
38139
38347
|
}
|
|
38140
38348
|
function toNegativeContribution(strength, maxPenalty, valueKind) {
|
|
38141
38349
|
const penalty = clamp(strength, 0, 1) * maxPenalty;
|
|
38142
|
-
if (valueKind ===
|
|
38350
|
+
if (valueKind === 0 /* Exact */) {
|
|
38143
38351
|
return {
|
|
38144
38352
|
min: -penalty,
|
|
38145
38353
|
max: -penalty
|
|
38146
38354
|
};
|
|
38147
38355
|
}
|
|
38148
|
-
if (valueKind ===
|
|
38356
|
+
if (valueKind === 1 /* Interval */) {
|
|
38149
38357
|
return {
|
|
38150
38358
|
min: -penalty,
|
|
38151
38359
|
max: -penalty * evidenceContributionCalibration.penaltyIntervalUpperScale
|
|
38152
38360
|
};
|
|
38153
38361
|
}
|
|
38154
|
-
if (valueKind ===
|
|
38362
|
+
if (valueKind === 2 /* Conditional */) {
|
|
38155
38363
|
return {
|
|
38156
38364
|
min: -penalty,
|
|
38157
38365
|
max: 0
|
|
@@ -38162,7 +38370,7 @@ function toNegativeContribution(strength, maxPenalty, valueKind) {
|
|
|
38162
38370
|
max: 0
|
|
38163
38371
|
};
|
|
38164
38372
|
}
|
|
38165
|
-
var ZERO_STRENGTH = { strength: 0, kind:
|
|
38373
|
+
var ZERO_STRENGTH = { strength: 0, kind: 0 /* Exact */ };
|
|
38166
38374
|
|
|
38167
38375
|
// src/cross-file/layout/consistency-policy.ts
|
|
38168
38376
|
function applyConsistencyPolicy(input) {
|
|
@@ -38246,23 +38454,38 @@ function resolveConfidence(posterior, evidenceMass) {
|
|
|
38246
38454
|
const confidence = posterior.lower * weightedMass * (1 - intervalWidth * alignmentPolicyCalibration.confidenceIntervalPenalty);
|
|
38247
38455
|
return clamp(confidence, 0, 1);
|
|
38248
38456
|
}
|
|
38457
|
+
var EMPTY_FACTOR_LIST = Object.freeze([]);
|
|
38249
38458
|
function selectTopFactors(evidence) {
|
|
38250
|
-
const
|
|
38251
|
-
|
|
38252
|
-
|
|
38253
|
-
|
|
38254
|
-
|
|
38255
|
-
if (
|
|
38256
|
-
|
|
38459
|
+
const atoms = evidence.atoms;
|
|
38460
|
+
if (atoms.length === 0) return EMPTY_FACTOR_LIST;
|
|
38461
|
+
const top = [];
|
|
38462
|
+
for (let i = 0; i < atoms.length; i++) {
|
|
38463
|
+
const atom = atoms[i];
|
|
38464
|
+
if (!atom) continue;
|
|
38465
|
+
const mag = Math.abs((atom.contribution.min + atom.contribution.max) / 2);
|
|
38466
|
+
if (mag <= 0) continue;
|
|
38467
|
+
if (top.length < 4) {
|
|
38468
|
+
top.push({ id: atom.factorId, mag });
|
|
38469
|
+
continue;
|
|
38470
|
+
}
|
|
38471
|
+
let minIdx = 0;
|
|
38472
|
+
for (let j = 1; j < top.length; j++) {
|
|
38473
|
+
const curr = top[j];
|
|
38474
|
+
const best = top[minIdx];
|
|
38475
|
+
if (curr && best && curr.mag < best.mag) minIdx = j;
|
|
38476
|
+
}
|
|
38477
|
+
const minEntry = top[minIdx];
|
|
38478
|
+
if (minEntry && mag > minEntry.mag) {
|
|
38479
|
+
top[minIdx] = { id: atom.factorId, mag };
|
|
38480
|
+
}
|
|
38481
|
+
}
|
|
38482
|
+
top.sort((a, b) => {
|
|
38483
|
+
if (a.mag !== b.mag) return b.mag - a.mag;
|
|
38484
|
+
if (a.id < b.id) return -1;
|
|
38485
|
+
if (a.id > b.id) return 1;
|
|
38257
38486
|
return 0;
|
|
38258
38487
|
});
|
|
38259
|
-
|
|
38260
|
-
for (let i = 0; i < sorted.length && i < 4; i++) {
|
|
38261
|
-
const item = sorted[i];
|
|
38262
|
-
if (!item) continue;
|
|
38263
|
-
out.push(item.factorId);
|
|
38264
|
-
}
|
|
38265
|
-
return out;
|
|
38488
|
+
return top.map((t) => t.id);
|
|
38266
38489
|
}
|
|
38267
38490
|
function logistic(value2) {
|
|
38268
38491
|
if (value2 > 30) return 1;
|
|
@@ -38283,7 +38506,7 @@ function evaluateAlignmentCase(input) {
|
|
|
38283
38506
|
evidenceMass: policy.evidenceMass
|
|
38284
38507
|
};
|
|
38285
38508
|
}
|
|
38286
|
-
const signalFindings = buildFindingsFromAtoms(evidence.atoms, input);
|
|
38509
|
+
const signalFindings = buildFindingsFromAtoms(evidence.atoms, input, evidence);
|
|
38287
38510
|
return {
|
|
38288
38511
|
kind: "accept",
|
|
38289
38512
|
evaluation: {
|
|
@@ -38303,12 +38526,12 @@ function evaluateAlignmentCase(input) {
|
|
|
38303
38526
|
}
|
|
38304
38527
|
};
|
|
38305
38528
|
}
|
|
38306
|
-
function buildFindingsFromAtoms(atoms, input) {
|
|
38529
|
+
function buildFindingsFromAtoms(atoms, input, evidence) {
|
|
38307
38530
|
const byKind = /* @__PURE__ */ new Map();
|
|
38308
38531
|
for (let i = 0; i < atoms.length; i++) {
|
|
38309
38532
|
const atom = atoms[i];
|
|
38310
38533
|
if (!atom) continue;
|
|
38311
|
-
const factor = toFindingFactor(atom.factorId, input);
|
|
38534
|
+
const factor = toFindingFactor(atom.factorId, input, evidence);
|
|
38312
38535
|
if (factor === null) continue;
|
|
38313
38536
|
const meanContribution = (atom.contribution.min + atom.contribution.max) / 2;
|
|
38314
38537
|
if (meanContribution <= 0) continue;
|
|
@@ -38329,7 +38552,7 @@ function buildFindingsFromAtoms(atoms, input) {
|
|
|
38329
38552
|
}
|
|
38330
38553
|
return [...byKind.values()];
|
|
38331
38554
|
}
|
|
38332
|
-
function toFindingFactor(factorId, input) {
|
|
38555
|
+
function toFindingFactor(factorId, input, evidence) {
|
|
38333
38556
|
switch (factorId) {
|
|
38334
38557
|
case "offset-delta":
|
|
38335
38558
|
return {
|
|
@@ -38359,17 +38582,15 @@ function toFindingFactor(factorId, input) {
|
|
|
38359
38582
|
case "content-composition-conflict":
|
|
38360
38583
|
return {
|
|
38361
38584
|
kind: "content-composition-conflict",
|
|
38362
|
-
message: formatContentCompositionFinding(input)
|
|
38585
|
+
message: formatContentCompositionFinding(input, evidence)
|
|
38363
38586
|
};
|
|
38364
38587
|
default:
|
|
38365
38588
|
return null;
|
|
38366
38589
|
}
|
|
38367
38590
|
}
|
|
38368
|
-
function formatContentCompositionFinding(input) {
|
|
38591
|
+
function formatContentCompositionFinding(input, evidence) {
|
|
38369
38592
|
const subjectClassification = formatCompositionClassification(input.subjectContentComposition.classification);
|
|
38370
|
-
const majorityClassification = formatCompositionClassification(
|
|
38371
|
-
resolveMajorityClassification(input.cohortContentCompositions)
|
|
38372
|
-
);
|
|
38593
|
+
const majorityClassification = formatCompositionClassification(evidence.majorityClassification);
|
|
38373
38594
|
const fixSuggestion = formatCompositionFixSuggestion(input.subjectContentComposition);
|
|
38374
38595
|
return `siblings have identical CSS but different content composition (subject: ${subjectClassification}, majority: ${majorityClassification}; fix: ${fixSuggestion})`;
|
|
38375
38596
|
}
|
|
@@ -38428,7 +38649,7 @@ function recordPolicyMetrics(context, evidenceMass, posteriorLower, posteriorUpp
|
|
|
38428
38649
|
context.layout.perf.factorCoverageSum += clamp(evidenceMass, 0, 1);
|
|
38429
38650
|
context.layout.perf.factorCoverageCount++;
|
|
38430
38651
|
const width = clamp(posteriorUpper - posteriorLower, 0, 1);
|
|
38431
|
-
context.layout.perf.posteriorWidths
|
|
38652
|
+
reservoirPush(context.layout.perf.posteriorWidths, width);
|
|
38432
38653
|
if (width > 1e-3) context.layout.perf.uncertaintyEscalations++;
|
|
38433
38654
|
}
|
|
38434
38655
|
|
|
@@ -38447,16 +38668,16 @@ function readNodeRefById(layout, solidFile, elementId) {
|
|
|
38447
38668
|
}
|
|
38448
38669
|
function isFlowRelevantBySiblingsOrText(node, textualContent) {
|
|
38449
38670
|
if (node.siblingCount >= 2) return true;
|
|
38450
|
-
return textualContent ===
|
|
38671
|
+
return textualContent === 0 /* Yes */ || textualContent === 2 /* Unknown */ || textualContent === 3 /* DynamicText */;
|
|
38451
38672
|
}
|
|
38452
38673
|
function isDeferredContainerLike(node, textualContent) {
|
|
38453
38674
|
if (node.siblingCount >= 2) return true;
|
|
38454
|
-
if (textualContent ===
|
|
38675
|
+
if (textualContent === 2 /* Unknown */) return true;
|
|
38455
38676
|
if (node.tagName !== null && SECTIONING_CONTAINER_TAGS.has(node.tagName)) return true;
|
|
38456
38677
|
return false;
|
|
38457
38678
|
}
|
|
38458
38679
|
function isDynamicContainerLike(node) {
|
|
38459
|
-
return node.textualContent ===
|
|
38680
|
+
return node.textualContent === 2 /* Unknown */ && node.siblingCount >= 2;
|
|
38460
38681
|
}
|
|
38461
38682
|
function isLikelyViewportAffectingContainer(node) {
|
|
38462
38683
|
if (node.siblingCount >= 2) return true;
|
|
@@ -39696,7 +39917,7 @@ var cssLayoutScrollbarGutterInstability = defineCrossRule({
|
|
|
39696
39917
|
const snapshot = collectSignalSnapshot(context, node);
|
|
39697
39918
|
const scroll = readScrollContainerFact(context.layout, node);
|
|
39698
39919
|
if (!scroll.isScrollContainer) continue;
|
|
39699
|
-
if (scroll.axis !==
|
|
39920
|
+
if (scroll.axis !== 2 /* Y */ && scroll.axis !== 3 /* Both */) continue;
|
|
39700
39921
|
const scrollbarWidth = readKnownNormalized(snapshot, "scrollbar-width");
|
|
39701
39922
|
if (scrollbarWidth === "none") continue;
|
|
39702
39923
|
const gutter = readKnownNormalized(snapshot, "scrollbar-gutter");
|
|
@@ -39826,10 +40047,10 @@ var cssLayoutConditionalDisplayCollapse = defineCrossRule({
|
|
|
39826
40047
|
const display = readKnownNormalizedWithGuard(snapshot, "display");
|
|
39827
40048
|
if (!display || !COLLAPSING_DISPLAYS.has(display)) continue;
|
|
39828
40049
|
const displaySignal = snapshot.signals.get("display");
|
|
39829
|
-
if (!displaySignal || displaySignal.guard !==
|
|
40050
|
+
if (!displaySignal || displaySignal.guard.kind !== 1 /* Conditional */) continue;
|
|
39830
40051
|
const flow = readFlowParticipationFact(context.layout, node);
|
|
39831
40052
|
if (!flow.inFlow) continue;
|
|
39832
|
-
if (!isFlowRelevantBySiblingsOrText(node, snapshot.textualContent)) continue;
|
|
40053
|
+
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
39833
40054
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
39834
40055
|
if (reservedSpace.hasReservedSpace) continue;
|
|
39835
40056
|
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalDisplayCollapse.id, "conditionalDisplayCollapse", messages152.conditionalDisplayCollapse, cssLayoutConditionalDisplayCollapse.severity, { display })) continue;
|
|
@@ -39865,10 +40086,10 @@ var cssLayoutConditionalWhiteSpaceWrapShift = defineCrossRule({
|
|
|
39865
40086
|
if (!hasWrapShiftDelta(whiteSpaceDelta)) continue;
|
|
39866
40087
|
if (!whiteSpace) continue;
|
|
39867
40088
|
const whiteSpaceSignal = snapshot.signals.get("white-space");
|
|
39868
|
-
if (!whiteSpaceSignal || whiteSpaceSignal.guard !==
|
|
40089
|
+
if (!whiteSpaceSignal || whiteSpaceSignal.guard.kind !== 1 /* Conditional */) continue;
|
|
39869
40090
|
const flow = readFlowParticipationFact(context.layout, node);
|
|
39870
40091
|
if (!flow.inFlow) continue;
|
|
39871
|
-
if (!isFlowRelevantBySiblingsOrText(node, snapshot.textualContent)) continue;
|
|
40092
|
+
if (!isFlowRelevantBySiblingsOrText(node, snapshot.node.textualContent)) continue;
|
|
39872
40093
|
if (hasStableTextShell(snapshot)) continue;
|
|
39873
40094
|
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutConditionalWhiteSpaceWrapShift.id, "conditionalWhiteSpaceShift", messages153.conditionalWhiteSpaceShift, cssLayoutConditionalWhiteSpaceWrapShift.severity, { whiteSpace })) continue;
|
|
39874
40095
|
}
|
|
@@ -40005,7 +40226,7 @@ var cssLayoutContentVisibilityNoIntrinsicSize = defineCrossRule({
|
|
|
40005
40226
|
const node = candidates[i];
|
|
40006
40227
|
if (!node) continue;
|
|
40007
40228
|
const snapshot = collectSignalSnapshot(context, node);
|
|
40008
|
-
if (!isDeferredContainerLike(node, snapshot.textualContent)) continue;
|
|
40229
|
+
if (!isDeferredContainerLike(node, snapshot.node.textualContent)) continue;
|
|
40009
40230
|
const reservedSpace = readReservedSpaceFact(context.layout, node);
|
|
40010
40231
|
if (reservedSpace.hasReservedSpace) continue;
|
|
40011
40232
|
if (!emitLayoutDiagnostic(context.layout, node, emit, cssLayoutContentVisibilityNoIntrinsicSize.id, "missingIntrinsicSize", messages156.missingIntrinsicSize, cssLayoutContentVisibilityNoIntrinsicSize.severity)) continue;
|
|
@@ -40064,11 +40285,11 @@ function collectConditionalOffsets(layout, node, snapshot) {
|
|
|
40064
40285
|
if (!delta.hasConditional || !delta.hasDelta) continue;
|
|
40065
40286
|
const signal = snapshot.signals.get(name);
|
|
40066
40287
|
if (!signal) continue;
|
|
40067
|
-
if (signal.guard !==
|
|
40288
|
+
if (signal.guard.kind !== 1 /* Conditional */) continue;
|
|
40068
40289
|
if (signal.kind !== "known") continue;
|
|
40069
40290
|
if (signal.px === null) continue;
|
|
40070
40291
|
if (Math.abs(signal.px) <= 0.25) continue;
|
|
40071
|
-
out.push({ property: name, value: signal.px, guardKey: signal.
|
|
40292
|
+
out.push({ property: name, value: signal.px, guardKey: signal.guard.key });
|
|
40072
40293
|
}
|
|
40073
40294
|
return out;
|
|
40074
40295
|
}
|
|
@@ -40089,8 +40310,8 @@ function hasEffectivePositionForConditionalOffset(snapshot, guardKey) {
|
|
|
40089
40310
|
const position = snapshot.signals.get("position");
|
|
40090
40311
|
if (!position) return false;
|
|
40091
40312
|
if (position.kind !== "known") return false;
|
|
40092
|
-
if (position.guard !==
|
|
40093
|
-
if (position.
|
|
40313
|
+
if (position.guard.kind !== 1 /* Conditional */) return false;
|
|
40314
|
+
if (position.guard.key !== guardKey) return false;
|
|
40094
40315
|
return position.normalized !== "static";
|
|
40095
40316
|
}
|
|
40096
40317
|
function hasStableBaseline(baselineBySignal, property, expectedPx) {
|
|
@@ -42304,13 +42525,14 @@ var RULES = [
|
|
|
42304
42525
|
{
|
|
42305
42526
|
"id": "resource-implicit-suspense",
|
|
42306
42527
|
"severity": "warn",
|
|
42307
|
-
"description": "Detect createResource
|
|
42308
|
-
"fixable":
|
|
42528
|
+
"description": "Detect createResource that implicitly triggers or permanently breaks Suspense boundaries.",
|
|
42529
|
+
"fixable": true,
|
|
42309
42530
|
"category": "reactivity",
|
|
42310
42531
|
"plugin": "solid",
|
|
42311
42532
|
"messages": {
|
|
42312
|
-
"loadingMismatch": "createResource '{{name}}' has no initialValue but uses
|
|
42313
|
-
"conditionalSuspense": "createResource '{{name}}'
|
|
42533
|
+
"loadingMismatch": "createResource '{{name}}' has no initialValue but uses {{name}}.loading for manual loading UI. Suspense intercepts before your loading UI renders \u2014 the component is unmounted before the <Show>/<Switch> evaluates. Replace createResource with onMount + createSignal to decouple from Suspense entirely.",
|
|
42534
|
+
"conditionalSuspense": "createResource '{{name}}' is inside a conditional mount point ({{mountTag}}) with a distant Suspense boundary. The SuspenseContext increment fires when the fetcher's Promise is pending and unmounts the entire page subtree \u2014 initialValue does NOT prevent this. Replace createResource with onMount + createSignal to avoid Suspense interaction.",
|
|
42535
|
+
"missingErrorBoundary": "createResource '{{name}}' has no <ErrorBoundary> between its component and the nearest <Suspense>. When the fetcher throws (network error, 401/403/503, timeout), the error propagates to Suspense which has no error handling \u2014 the boundary breaks permanently. Wrap the component in <ErrorBoundary> or replace createResource with onMount + createSignal and catch errors in the fetcher."
|
|
42314
42536
|
}
|
|
42315
42537
|
},
|
|
42316
42538
|
{
|
|
@@ -42513,7 +42735,7 @@ var RULES_BY_CATEGORY = {
|
|
|
42513
42735
|
"css-structure": [{ "id": "css-no-empty-rule", "severity": "warn", "description": "Disallow empty CSS rules.", "fixable": false, "category": "css-structure", "plugin": "css", "messages": { "emptyRule": "Empty rule `{{selector}}` should be removed." } }, { "id": "css-no-unknown-container-name", "severity": "error", "description": "Disallow unknown named containers in @container queries.", "fixable": false, "category": "css-structure", "plugin": "css", "messages": { "unknownContainer": "Unknown container name `{{name}}` in @container query." } }, { "id": "css-no-unused-container-name", "severity": "warn", "description": "Disallow unused named containers.", "fixable": false, "category": "css-structure", "plugin": "css", "messages": { "unusedContainer": "Container name `{{name}}` is declared but never queried." } }, { "id": "layer-requirement-for-component-rules", "severity": "warn", "description": "Require style rules to be inside @layer when the file defines layers.", "fixable": false, "category": "css-structure", "plugin": "css", "messages": { "missingLayer": "Rule `{{selector}}` is not inside any @layer block while this file uses @layer. Place component rules inside an explicit layer." } }],
|
|
42514
42736
|
"jsx": [{ "id": "components-return-once", "severity": "error", "description": "Disallow early returns in components. Solid components only run once, and so conditionals should be inside JSX.", "fixable": true, "category": "jsx", "plugin": "solid", "messages": { "noEarlyReturn": "Early returns in Solid components break reactivity because the component function only runs once. Use <Show> or <Switch>/<Match> inside the JSX to conditionally render content instead of returning early from the function.", "noConditionalReturn": "Conditional expressions in return statements break reactivity because Solid components only run once. Wrap the condition in <Show when={...}> for a single condition, or <Switch>/<Match> for multiple conditions." } }, { "id": "jsx-no-duplicate-props", "severity": "error", "description": "Disallow passing the same prop twice in JSX.", "fixable": true, "category": "jsx", "plugin": "solid", "messages": { "noDuplicateProps": "Duplicate prop detected. Each prop should only be specified once; the second value will override the first.", "noDuplicateClass": "Duplicate `class` prop detected. While this might appear to work, it can break unexpectedly because only one class binding is applied. Use `classList` to conditionally apply multiple classes.", "noDuplicateChildren": "Conflicting children: {{used}}. Only one method of setting children is allowed at a time." } }, { "id": "jsx-no-script-url", "severity": "error", "description": "Disallow javascript: URLs.", "fixable": true, "category": "jsx", "plugin": "solid", "messages": { "noJSURL": "Using javascript: URLs is a security risk because it can enable cross-site scripting (XSS) attacks. Use an event handler like onClick instead, or navigate programmatically with useNavigate()." } }, { "id": "jsx-no-undef", "severity": "error", "description": "Disallow references to undefined variables in JSX. Handles custom directives.", "fixable": false, "category": "jsx", "plugin": "solid", "messages": { "customDirectiveUndefined": "Custom directive '{{identifier}}' is not defined. Directives must be imported or declared in scope before use (e.g., `const {{identifier}} = (el, accessor) => { ... }`)." } }, { "id": "jsx-uses-vars", "severity": "warn", "description": "Detect imported components and directives that are never used in JSX.", "fixable": false, "category": "jsx", "plugin": "solid", "messages": { "unusedComponent": "Component '{{name}}' is imported but never used in JSX.", "unusedDirective": "Directive '{{name}}' is imported but never used in JSX." } }, { "id": "no-innerhtml", "severity": "error", "description": "Disallow usage of the innerHTML attribute, which can lead to security vulnerabilities.", "fixable": true, "category": "jsx", "plugin": "solid", "messages": { "dangerous": "Using innerHTML with dynamic content is a security risk. Unsanitized user input can lead to cross-site scripting (XSS) attacks. Use a sanitization library or render content safely.", "conflict": "The innerHTML prop will overwrite all child elements. Remove the children or use innerHTML on an empty element.", "notHtml": "The innerHTML value doesn't appear to be HTML. If you're setting text content, use innerText instead for clarity and safety.", "dangerouslySetInnerHTML": "The dangerouslySetInnerHTML is a React prop that Solid doesn't support. Use innerHTML instead." } }, { "id": "no-unknown-namespaces", "severity": "error", "description": "Enforce using only Solid-specific namespaced attribute names (i.e. `'on:'` in `<div on:click={...} />`).", "fixable": false, "category": "jsx", "plugin": "solid", "messages": { "unknownNamespace": "'{{namespace}}:' is not a recognized Solid namespace. Valid namespaces are: {{validNamespaces}}.", "styleNamespace": "The 'style:' namespace works but is discouraged. Use the style prop with an object instead: style={{ {{property}}: value }}.", "classNamespace": `The 'class:' namespace works but is discouraged. Use the classList prop instead: classList={{ "{{className}}": condition }}.`, "componentNamespace": "Namespaced attributes like '{{namespace}}:' only work on DOM elements, not components. The '{{fullName}}' attribute will be passed as a regular prop named '{{fullName}}'." } }, { "id": "show-truthy-conversion", "severity": "error", "description": "Detect <Show when={expr}> where expr is not explicitly boolean, which may have unexpected truthy/falsy behavior.", "fixable": true, "category": "jsx", "plugin": "solid", "messages": { "showNonBoolean": "<Show when={{{{expr}}}}> uses truthy/falsy conversion. Value '0' or empty string '' will hide content. Use explicit boolean: when={Boolean({{expr}})} or when={{{expr}}} != null}" } }, { "id": "suspense-boundary-missing", "severity": "error", "description": "Detect missing fallback props on Suspense/ErrorBoundary, and lazy components without Suspense wrapper.", "fixable": false, "category": "jsx", "plugin": "solid", "messages": { "suspenseNoFallback": "<Suspense> should have a fallback prop to show while children are loading. Add: fallback={<Loading />}", "errorBoundaryNoFallback": "<ErrorBoundary> should have a fallback prop to show when an error occurs. Add: fallback={(err) => <Error error={err} />}", "lazyNoSuspense": "Lazy component '{{name}}' must be wrapped in a <Suspense> boundary. Add a <Suspense fallback={...}> ancestor." } }, { "id": "validate-jsx-nesting", "severity": "error", "description": "Validates that HTML elements are nested according to the HTML5 specification.", "fixable": false, "category": "jsx", "plugin": "solid", "messages": { "invalidNesting": "Invalid HTML nesting: <{{child}}> cannot be a child of <{{parent}}>. {{reason}}.", "voidElementWithChildren": "<{{parent}}> is a void element and cannot have children. Found <{{child}}> as a child.", "invalidListChild": "<{{child}}> is not a valid direct child of <{{parent}}>. Only <li> elements can be direct children of <ul> and <ol>.", "invalidSelectChild": "<{{child}}> is not a valid direct child of <select>. Only <option> and <optgroup> elements are allowed.", "invalidTableChild": "<{{child}}> is not a valid direct child of <{{parent}}>. Expected: {{expected}}.", "invalidDlChild": "<{{child}}> is not a valid direct child of <dl>. Only <dt>, <dd>, and <div> elements are allowed." } }],
|
|
42515
42737
|
"performance": [{ "id": "avoid-arguments-object", "severity": "warn", "description": "Disallow arguments object (use rest parameters instead).", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "avoidArguments": "arguments object can prevent V8 optimization. Use rest parameters (...args) instead." } }, { "id": "avoid-chained-array-methods", "severity": "warn", "description": "Flags chained array methods creating 3+ intermediate arrays, or filter().map() pattern.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "avoidChainedArrayMethods": "Chain creates {{count}} intermediate array(s). Consider reduce() or a loop. Chain: {{chain}}", "mapJoinHotPath": "map().join() inside loops allocates intermediate arrays on a hot path. Prefer single-pass string construction." } }, { "id": "avoid-defensive-copy-for-scalar-stat", "severity": "warn", "description": "Disallow defensive array copies passed into scalar statistic calls.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "defensiveCopy": "Defensive copy before scalar statistic '{{stat}}' allocates unnecessarily. Prefer readonly/non-mutating scalar computation." } }, { "id": "avoid-delete-operator", "severity": "warn", "description": "Disallow delete operator on objects (causes V8 deoptimization).", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "avoidDelete": "delete operator transitions object to slow mode. Use `obj.prop = undefined` or destructuring instead." } }, { "id": "avoid-function-allocation-in-hot-loop", "severity": "warn", "description": "Disallow creating closures inside loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "closureInLoop": "Function created inside loop allocates new closure per iteration. Consider hoisting or using event delegation." } }, { "id": "avoid-hidden-class-transition", "severity": "warn", "description": "Suggest consistent object shapes to avoid V8 hidden class transitions.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "hiddenClassTransition": "Property '{{property}}' added conditionally to '{{object}}' creates inconsistent object shapes. Initialize '{{property}}' in the object literal." } }, { "id": "avoid-intermediate-map-copy", "severity": "warn", "description": "Disallow temporary Map allocations that are copied key-for-key into another Map.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "intermediateMapCopy": "Intermediate Map '{{tempName}}' is copied into '{{outName}}' key-for-key. Build output directly to avoid extra allocation." } }, { "id": "avoid-megamorphic-property-access", "severity": "warn", "description": "Avoid property access on `any` or wide union types to prevent V8 deoptimization.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "megamorphicAccess": "Property access on `any` or wide union type causes V8 deoptimization. Consider narrowing the type." } }, { "id": "avoid-quadratic-pair-comparison", "severity": "warn", "description": "Disallow nested for-loops over the same collection creating O(n\xB2) pair comparison.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "quadraticPair": "Nested loops over `{{collection}}` create O(n\xB2) pair comparison. Group by a key property first." } }, { "id": "avoid-quadratic-spread", "severity": "error", "description": "Disallow spreading accumulator in reduce callbacks (O(n\xB2) complexity).", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "quadraticSpread": "Spreading accumulator in reduce creates O(n\xB2) complexity. Use push() instead." } }, { "id": "avoid-repeated-indexof-check", "severity": "warn", "description": "Disallow 3+ .indexOf() calls on the same array variable in one function.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "repeatedIndexOf": "{{count}} .indexOf() calls on `{{name}}` in the same function. Use a Set, regex, or single-pass scan instead." } }, { "id": "avoid-slice-sort-pattern", "severity": "warn", "description": "Disallow .slice().sort() and .slice().reverse() chains. Use .toSorted()/.toReversed().", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "sliceSort": ".slice().sort() creates an intermediate array. Use .toSorted() instead.", "sliceReverse": ".slice().reverse() creates an intermediate array. Use .toReversed() instead.", "spreadSort": "[...array].sort() creates an intermediate array. Use .toSorted() instead.", "spreadReverse": "[...array].reverse() creates an intermediate array. Use .toReversed() instead." } }, { "id": "avoid-sparse-arrays", "severity": "warn", "description": "Disallow new Array(n) without fill (creates holey array).", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "sparseArray": "new Array(n) creates a holey array. Use Array.from() or .fill() instead." } }, { "id": "avoid-spread-sort-map-join-pipeline", "severity": "warn", "description": "Disallow [...iterable].sort().map().join() pipelines on hot paths.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "spreadSortMapJoin": "Spread+sort+map+join pipeline allocates multiple intermediates. Prefer single-pass string construction on hot paths." } }, { "id": "bounded-worklist-traversal", "severity": "warn", "description": "Detect queue/worklist traversals with unbounded growth and no guard.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "boundedWorklist": "Worklist '{{name}}' grows via push() without visited set or explicit size bound. Add traversal guard to prevent pathological growth." } }, { "id": "closure-captured-scope", "severity": "warn", "description": "Detect closures returned from scopes containing large allocations that may be retained.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "capturedScope": "Returned closure shares scope with large allocation '{{name}}'. V8 may retain the allocation via scope capture even though the closure doesn't reference it. Move the allocation to an inner scope." } }, { "id": "closure-dom-circular", "severity": "warn", "description": "Detect event handler property assignments that create closure-DOM circular references.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "circularRef": "Event handler on '{{param}}' creates a closure that captures '{{param}}', forming a closure-DOM circular reference. Use addEventListener with a named handler for easier cleanup." } }, { "id": "create-root-dispose", "severity": "warn", "description": "Detect createRoot with unused dispose parameter.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "unusedDispose": "createRoot() dispose parameter is never used. The reactive tree will never be cleaned up. Call dispose(), return it, or pass it to onCleanup()." } }, { "id": "detached-dom-reference", "severity": "warn", "description": "Detect DOM query results stored in module-scoped variables that may hold detached nodes.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "detachedRef": "DOM query result from '{{method}}' stored in module-scoped variable '{{name}}'. If the DOM node is removed, this reference prevents garbage collection. Use a local variable or WeakRef instead." } }, { "id": "effect-outside-root", "severity": "error", "description": "Detect reactive computations created outside a reactive root (no Owner).", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "orphanedEffect": "{{primitive}}() called outside a reactive root. Without an Owner, this computation is never disposed and leaks memory. Wrap in a component, createRoot, or runWithOwner." } }, { "id": "finalization-registry-leak", "severity": "error", "description": "Detect FinalizationRegistry.register() where heldValue references the target.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "selfReference": "FinalizationRegistry.register() heldValue references the target '{{name}}'. This strong reference prevents the target from being garbage collected, defeating the purpose of the registry." } }, { "id": "no-char-array-materialization", "severity": "warn", "description": 'Disallow split(""), Array.from(str), or [...str] in parsing loops.', "fixable": false, "category": "performance", "plugin": "solid", "messages": { "charArrayMaterialization": "Character array materialization via {{pattern}} in parsing loops allocates O(n) extra memory. Prefer index-based scanning." } }, { "id": "no-double-pass-delimiter-count", "severity": "warn", "description": "Disallow split-based delimiter counting followed by additional split passes.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "doublePassDelimiterCount": "Delimiter counting via `split(...).length` plus another `split(...)` repeats full-string passes. Prefer one indexed scan." } }, { "id": "no-full-split-in-hot-parse", "severity": "warn", "description": "Disallow full split() materialization inside hot string parsing loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "fullSplitInHotParse": "`split()` inside parsing loops materializes full token arrays each iteration. Prefer cursor/index scanning." } }, { "id": "no-heavy-parser-constructor-in-loop", "severity": "warn", "description": "Disallow constructing heavy parsing helpers inside loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "heavyParserConstructor": "`new {{ctor}}(...)` inside parsing loops repeatedly allocates heavy parser helpers. Hoist and reuse instances." } }, { "id": "no-leaked-abort-controller", "severity": "warn", "description": "Detect AbortController in effects without abort() in onCleanup.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedAbort": "new AbortController() inside a reactive effect without onCleanup. Add onCleanup(() => controller.abort())." } }, { "id": "no-leaked-animation-frame", "severity": "warn", "description": "Detect requestAnimationFrame in effects without cancelAnimationFrame in onCleanup.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedRaf": "requestAnimationFrame() inside a reactive effect without onCleanup. Add onCleanup(() => cancelAnimationFrame(id))." } }, { "id": "no-leaked-event-listener", "severity": "warn", "description": "Detect addEventListener in effects without removeEventListener in onCleanup.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedListener": "addEventListener() inside a reactive effect without onCleanup. Each re-run leaks a listener. Add onCleanup(() => removeEventListener(...))." } }, { "id": "no-leaked-observer", "severity": "warn", "description": "Detect Observer APIs in effects without disconnect() in onCleanup.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedObserver": "new {{type}}() inside a reactive effect without onCleanup. Add onCleanup(() => observer.disconnect())." } }, { "id": "no-leaked-subscription", "severity": "warn", "description": "Detect WebSocket/EventSource/BroadcastChannel in effects without close() in onCleanup.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedSubscription": "new {{type}}() inside a reactive effect without onCleanup. Add onCleanup(() => instance.close())." } }, { "id": "no-leaked-timer", "severity": "warn", "description": "Detect setInterval/setTimeout in effects without onCleanup to clear them.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "leakedTimer": "{{setter}}() inside a reactive effect without onCleanup. Each re-run leaks a timer. Add onCleanup(() => {{clearer}}(id))." } }, { "id": "no-loop-string-plus-equals", "severity": "warn", "description": "Disallow repeated string += accumulation in parsing loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "loopStringPlusEquals": "Repeated string `+=` in parsing loops creates avoidable allocations. Buffer chunks and join once." } }, { "id": "no-multipass-split-pipeline", "severity": "warn", "description": "Disallow multipass split/map/filter pipelines in parsing code.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "multipassSplit": "`split()` followed by multiple array passes allocates heavily on parsing paths. Prefer single-pass parsing." } }, { "id": "no-per-char-substring-scan", "severity": "warn", "description": "Disallow per-character substring/charAt scanning patterns in loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "perCharSubstring": "Per-character `{{method}}()` scanning in loops allocates extra strings. Prefer index + charCodeAt scanning." } }, { "id": "no-repeated-token-normalization", "severity": "warn", "description": "Disallow repeated trim/lower/upper normalization chains on the same token in one function.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "repeatedTokenNormalization": "Repeated token normalization `{{chain}}` on `{{name}}` in one function. Compute once and reuse." } }, { "id": "no-rescan-indexof-loop", "severity": "warn", "description": "Disallow repeated indexOf/includes scans from start in parsing loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "rescanIndexOf": "Repeated `{{method}}()` from string start inside loops rescans prior text. Pass a cursor start index." } }, { "id": "no-rest-slice-loop", "severity": "warn", "description": "Disallow repeated self-slice reassignment loops in string parsing code.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "restSliceLoop": "Repeated `{{name}} = {{name}}.{{method}}(...)` in loops creates string churn. Track cursor indexes instead." } }, { "id": "no-shift-splice-head-consume", "severity": "warn", "description": "Disallow shift/splice(0,1) head-consume patterns in loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "headConsume": "Head-consuming `{{method}}()` inside loops causes array reindexing costs. Use index cursor iteration instead." } }, { "id": "no-write-only-index", "severity": "warn", "description": "Detect index structures that are written but never queried by key.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "writeOnlyIndex": "Index '{{name}}' is built via writes but never queried by key. Remove it or use direct collection flow." } }, { "id": "prefer-charcode-over-regex-test", "severity": "warn", "description": "Prefer charCodeAt() range checks over regex .test() for single-character classification.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "regexTest": "Regex `{{pattern}}`.test() on a single character. Use charCodeAt() range checks instead." } }, { "id": "prefer-index-scan-over-string-iterator", "severity": "warn", "description": "Prefer index-based string scanning over for-of iteration in ASCII parser code.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "preferIndexScan": "ASCII parsing loops should avoid `for...of` string iteration. Prefer indexed scanning with charCodeAt for lower overhead." } }, { "id": "prefer-lazy-property-access", "severity": "warn", "description": "Suggests moving property access after early returns when not used immediately.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "preferLazyPropertyAccess": "Property '{{propertyName}}' assigned to '{{variableName}}' before early return but not used there. Move assignment after early returns." } }, { "id": "prefer-map-lookup-over-linear-scan", "severity": "warn", "description": "Disallow repeated linear scans over fixed literal collections in hot paths.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "preferMapLookup": "Linear scan over fixed collection '{{name}}' in '{{fnName}}'. Precompute Map/Set lookup for O(1) access." } }, { "id": "prefer-map-over-object-dictionary", "severity": "warn", "description": "Suggest Map for dictionary-like objects with dynamic keys.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "preferMap": "Dynamic key assignment on dictionary object causes hidden class transitions. Consider using Map." } }, { "id": "prefer-precompiled-regex", "severity": "warn", "description": "Prefer hoisting regex literals to module-level constants to avoid repeated compilation.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "inlineRegex": "Regex `{{pattern}}` is compiled on every call. Hoist to a module-level constant." } }, { "id": "prefer-set-has-over-equality-chain", "severity": "warn", "description": "Disallow 4+ guard-style equality checks against string literals on the same variable. Use a Set.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "equalityChain": "{{count}} equality checks against `{{name}}`. Extract literals to a Set and use .has() instead." } }, { "id": "prefer-set-lookup-in-loop", "severity": "warn", "description": "Disallow linear search methods (.includes/.indexOf) on arrays inside loops.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "preferSet": "`.{{method}}()` on `{{name}}` called inside a loop. Convert to a Set for O(1) lookups." } }, { "id": "recursive-timer", "severity": "warn", "description": "Detect setTimeout that recursively calls its enclosing function.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "recursiveTimer": "setTimeout() recursively calls '{{name}}', creating an unbreakable polling loop. Add a termination condition or use setInterval with cleanup." } }, { "id": "self-referencing-store", "severity": "error", "description": "Detect setStore() where the value argument references the store itself.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "selfReference": "setStore() value references the store variable '{{name}}', creating a circular proxy reference. This prevents garbage collection and can cause infinite loops." } }, { "id": "unbounded-collection", "severity": "warn", "description": "Detect module-scoped Map/Set/Array that only grow without removal.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "unboundedCollection": "Module-scoped {{type}} '{{name}}' only uses additive methods ({{methods}}). Without removal or clearing, this grows unbounded. Consider WeakMap, LRU eviction, or periodic clear()." } }, { "id": "unbounded-signal-accumulation", "severity": "warn", "description": "Detect signal setters that accumulate data without truncation via spread+append pattern.", "fixable": false, "category": "performance", "plugin": "solid", "messages": { "unbounded": "Signal setter '{{name}}' accumulates data without bounds. The array grows monotonically via spread+append. Add truncation (e.g. prev.slice(-limit)) to prevent unbounded growth." } }],
|
|
42516
|
-
"reactivity": [{ "id": "async-tracked", "severity": "error", "description": "Disallow async functions in tracked scopes (createEffect, createMemo, etc.)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "asyncCreateEffect": "Async function{{fnName}} in createEffect loses tracking after await. Read all signals before the first await, or use createResource for async data fetching.", "asyncCreateMemo": "Async function{{fnName}} in createMemo won't work correctly. createMemo must be synchronous. For async derived data, use createResource instead.", "asyncCreateComputed": "Async function{{fnName}} in createComputed won't track properly. createComputed must be synchronous\u2014signal reads after await won't trigger re-computation.", "asyncCreateRenderEffect": "Async function{{fnName}} in createRenderEffect breaks DOM update timing. createRenderEffect must be synchronous. Move async work to onMount or createResource.", "asyncTrackedGeneric": "Async function{{fnName}} in {{source}} won't track reactivity after await. Solid's tracking only works synchronously\u2014signal reads after await are ignored." } }, { "id": "children-helper-misuse", "severity": "error", "description": "Detect misuse of the children() helper that causes unnecessary re-computation or breaks reactivity", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "multipleChildrenCalls": "The children() helper should only be called once per component. Each call re-resolves children, causing unnecessary computation. Store the result and reuse the accessor.", "directChildrenAccess": "Access props.children through the children() helper in reactive contexts. Direct access won't properly resolve or track children. Use: const resolved = children(() => props.children);" } }, { "id": "cleanup-scope", "severity": "error", "description": "Detect onCleanup called outside of a valid reactive scope", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "cleanupOutsideScope": "onCleanup() called outside a reactive scope ({{location}}). The cleanup function will never execute unless this code runs within a component, effect, createRoot, or runWithOwner." } }, { "id": "derived-signal", "severity": "error", "description": "Detect functions that capture reactive values but are called in untracked contexts", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "moduleScopeInit": "Assigning '{{fnName}}()' to '{{varName}}' at module scope runs once at startup. It captures {{vars}} which won't trigger updates.", "moduleScopeCall": "'{{fnName}}()' at module scope executes once when the module loads. It captures {{vars}}\u2014changes won't cause this to re-run.", "componentTopLevelInit": "'{{fnName}}()' assigned to '{{varName}}' in '{{componentName}}' captures a one-time snapshot of {{vars}}. Changes won't update '{{varName}}'. Call in JSX or use createMemo().", "componentTopLevelCall": "'{{fnName}}()' at top-level of '{{componentName}}' runs once and captures a snapshot of {{vars}}. Changes won't re-run this. Move inside JSX: {{{fnName}}()} or wrap with createMemo().", "utilityFnCall": "'{{fnName}}()' inside '{{utilityName}}' won't be reactive. Call '{{utilityName}}' from a tracked scope (createEffect, JSX), or pass {{vars}} as parameters.", "syncCallbackCall": "'{{fnName}}()' inside {{methodName}}() callback runs outside a tracking scope. The result captures a snapshot of {{vars}} that won't update.", "untrackedCall": "'{{fnName}}()' called in an untracked context. It captures {{vars}} which won't trigger updates here. Move to JSX or a tracked scope." } }, { "id": "effect-as-memo", "severity": "error", "description": "Detect createEffect that only sets a derived signal value, which should be createMemo instead", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "effectAsMemo": "This createEffect only computes a derived value. Use createMemo() instead: const {{signalName}} = createMemo(() => {{expression}});" } }, { "id": "effect-as-mount", "severity": "error", "description": "Detect createEffect/createRenderEffect with no reactive dependencies that should be onMount instead", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "effectAsMount": "This {{primitive}} has no reactive dependencies and runs only once. Use onMount() for initialization logic that doesn't need to re-run." } }, { "id": "inline-component", "severity": "error", "description": "Detect component functions defined inside other components, which causes remount on every parent update", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "inlineComponent": "Component '{{name}}' is defined inside another component. This creates a new component type on every render, causing unmount/remount. Move the component definition outside." } }, { "id": "no-top-level-signal-call", "severity": "error", "description": "Disallow calling signals at component top-level (captures stale snapshots)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "assignedToVar": "'{{name}}()' assigned to '{{varName}}' in {{componentName}} captures a one-time snapshot. '{{varName}}' won't update when {{name}} changes. Use createMemo(): `const {{varName}} = createMemo(() => {{name}}());`", "computedValue": "'{{name}}()' in computation at top-level of {{componentName}} captures a stale snapshot. Wrap with createMemo(): `const {{varName}} = createMemo(() => /* computation using {{name}}() */);`", "templateLiteral": "'{{name}}()' in template literal at top-level of {{componentName}} captures a stale snapshot. Use createMemo() or compute directly in JSX: `{`Hello, ${{{name}}()}!`}`", "destructuring": "Destructuring '{{name}}()' at top-level of {{componentName}} captures a stale snapshot. Access properties in JSX or createMemo(): `{{{name}}().propertyName}`", "objectLiteral": "'{{name}}()' in object literal at top-level of {{componentName}} captures a stale snapshot. Use createMemo() for the object, or spread in JSX.", "arrayCreation": "'{{name}}()' in array creation at top-level of {{componentName}} captures a stale snapshot. Wrap with createMemo(): `const items = createMemo(() => Array.from(...));`", "earlyReturn": "'{{name}}()' in early return at top-level of {{componentName}} captures a stale snapshot. Use <Show when={{{name}}()}> for conditional rendering instead.", "conditionalAssign": "'{{name}}()' in ternary at top-level of {{componentName}} captures a stale snapshot. Use createMemo() or compute in JSX: `{{{name}}() ? 'Yes' : 'No'}`", "functionArgument": "'{{name}}()' passed as argument at top-level of {{componentName}} captures a stale snapshot. Move to createEffect() or compute in JSX.", "syncCallback": "'{{name}}()' inside {{methodName}}() at top-level of {{componentName}} captures a stale snapshot. Wrap the entire computation in createMemo(): `const result = createMemo(() => items.{{methodName}}(...));`", "topLevelCall": "'{{name}}()' at top-level of {{componentName}} captures a one-time snapshot. Changes to {{name}} won't update the result. Call directly in JSX or wrap in createMemo()." } }, { "id": "ref-early-access", "severity": "error", "description": "Detect accessing refs before they are assigned (before mount)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "refBeforeMount": "Ref '{{name}}' is accessed before component mounts. Refs are undefined until after mount. Access in onMount(), createEffect(), or event handlers." } }, { "id": "resource-access-unchecked", "severity": "error", "description": "Detect accessing resource data without checking loading/error state.", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "resourceUnchecked": "Accessing resource '{{name}}' without checking loading/error state may return undefined. Wrap in <Show when={!{{name}}.loading}> or <Suspense>." } }, { "id": "resource-implicit-suspense", "severity": "warn", "description": "Detect createResource without initialValue that implicitly triggers Suspense boundaries.", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "loadingMismatch": "createResource '{{name}}' has no initialValue but uses manual loading checks ({{name}}.loading). Without initialValue, Suspense intercepts before your loading UI renders. Add initialValue to the options: createResource(fetcher, { initialValue: ... })", "conditionalSuspense": "createResource '{{name}}' has no initialValue and is rendered inside a conditional mount point ({{mountTag}}). This will trigger a distant Suspense boundary and unmount the entire subtree. Add initialValue to the options: createResource(fetcher, { initialValue: ... })" } }, { "id": "resource-refetch-loop", "severity": "error", "description": "Detect refetch() calls inside createEffect which can cause infinite loops", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "refetchInEffect": "Calling {{name}}.refetch() inside createEffect may cause infinite loops. The resource tracks its own dependencies. Move refetch to an event handler or use on() to control dependencies." } }, { "id": "signal-call", "severity": "error", "description": "Require signals to be called as functions when used in tracked contexts", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "signalInJsxText": "Signal '{{name}}' in JSX text should be called: {{{name}}()}. Without (), you're rendering the function, not its value.", "signalInJsxAttribute": "Signal '{{name}}' in JSX attribute should be called: {{attr}}={{{name}}()}. Without (), the attribute won't update reactively.", "signalInTernary": "Signal '{{name}}' in ternary should be called: {{name}}() ? ... : .... The condition won't react to changes without ().", "signalInLogical": "Signal '{{name}}' in logical expression should be called: {{name}}() && .... Without (), this always evaluates to truthy (functions are truthy).", "signalInComparison": "Signal '{{name}}' in comparison should be called: {{name}}() === .... Comparing functions always returns false.", "signalInArithmetic": "Signal '{{name}}' in arithmetic should be called: {{name}}() + .... Math on functions produces NaN.", "signalInTemplate": "Signal '{{name}}' in template literal should be called: `...${{{name}}()}...`. Without (), you're embedding '[Function]'.", "signalInTrackedScope": "Signal '{{name}}' in {{where}} should be called: {{name}}(). Without (), reactivity is lost.", "badSignal": "The reactive variable '{{name}}' should be called as a function when used in {{where}}." } }, { "id": "signal-in-loop", "severity": "error", "description": "Detect problematic signal usage inside For/Index loop callbacks", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "signalInLoop": "Creating signals inside <{{component}}> callback creates new signals on each render. Use a store at the parent level, or derive state from the index.", "signalCallInvariant": "Signal '{{name}}' called inside <{{component}}> produces the same value for every item. Extract to a variable or memoize with createMemo() before the loop.", "derivedCallInvariant": "'{{name}}()' inside <{{component}}> captures {{captures}} but doesn't use the loop item. Extract the call before the loop or pass the item as a parameter." } }, { "id": "store-reactive-break", "severity": "error", "description": "Detect patterns that break store reactivity: spreading stores, top-level property extraction, or destructuring", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "storeSpread": "Spreading a store ({...store}) creates a static snapshot that won't update. Access store properties directly in JSX or tracked contexts.", "storeTopLevelAccess": "Accessing store property '{{property}}' at component top-level captures the value once. Access store.{{property}} directly in JSX or wrap in createMemo().", "storeDestructure": "Destructuring a store breaks reactivity. Access properties via store.{{property}} instead of destructuring." } }, { "id": "transition-pending-unchecked", "severity": "error", "description": "Detect useTransition usage without handling the isPending state", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "pendingUnchecked": "useTransition returns [isPending, startTransition]. The isPending state should be used to show loading UI during transitions." } }],
|
|
42738
|
+
"reactivity": [{ "id": "async-tracked", "severity": "error", "description": "Disallow async functions in tracked scopes (createEffect, createMemo, etc.)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "asyncCreateEffect": "Async function{{fnName}} in createEffect loses tracking after await. Read all signals before the first await, or use createResource for async data fetching.", "asyncCreateMemo": "Async function{{fnName}} in createMemo won't work correctly. createMemo must be synchronous. For async derived data, use createResource instead.", "asyncCreateComputed": "Async function{{fnName}} in createComputed won't track properly. createComputed must be synchronous\u2014signal reads after await won't trigger re-computation.", "asyncCreateRenderEffect": "Async function{{fnName}} in createRenderEffect breaks DOM update timing. createRenderEffect must be synchronous. Move async work to onMount or createResource.", "asyncTrackedGeneric": "Async function{{fnName}} in {{source}} won't track reactivity after await. Solid's tracking only works synchronously\u2014signal reads after await are ignored." } }, { "id": "children-helper-misuse", "severity": "error", "description": "Detect misuse of the children() helper that causes unnecessary re-computation or breaks reactivity", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "multipleChildrenCalls": "The children() helper should only be called once per component. Each call re-resolves children, causing unnecessary computation. Store the result and reuse the accessor.", "directChildrenAccess": "Access props.children through the children() helper in reactive contexts. Direct access won't properly resolve or track children. Use: const resolved = children(() => props.children);" } }, { "id": "cleanup-scope", "severity": "error", "description": "Detect onCleanup called outside of a valid reactive scope", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "cleanupOutsideScope": "onCleanup() called outside a reactive scope ({{location}}). The cleanup function will never execute unless this code runs within a component, effect, createRoot, or runWithOwner." } }, { "id": "derived-signal", "severity": "error", "description": "Detect functions that capture reactive values but are called in untracked contexts", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "moduleScopeInit": "Assigning '{{fnName}}()' to '{{varName}}' at module scope runs once at startup. It captures {{vars}} which won't trigger updates.", "moduleScopeCall": "'{{fnName}}()' at module scope executes once when the module loads. It captures {{vars}}\u2014changes won't cause this to re-run.", "componentTopLevelInit": "'{{fnName}}()' assigned to '{{varName}}' in '{{componentName}}' captures a one-time snapshot of {{vars}}. Changes won't update '{{varName}}'. Call in JSX or use createMemo().", "componentTopLevelCall": "'{{fnName}}()' at top-level of '{{componentName}}' runs once and captures a snapshot of {{vars}}. Changes won't re-run this. Move inside JSX: {{{fnName}}()} or wrap with createMemo().", "utilityFnCall": "'{{fnName}}()' inside '{{utilityName}}' won't be reactive. Call '{{utilityName}}' from a tracked scope (createEffect, JSX), or pass {{vars}} as parameters.", "syncCallbackCall": "'{{fnName}}()' inside {{methodName}}() callback runs outside a tracking scope. The result captures a snapshot of {{vars}} that won't update.", "untrackedCall": "'{{fnName}}()' called in an untracked context. It captures {{vars}} which won't trigger updates here. Move to JSX or a tracked scope." } }, { "id": "effect-as-memo", "severity": "error", "description": "Detect createEffect that only sets a derived signal value, which should be createMemo instead", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "effectAsMemo": "This createEffect only computes a derived value. Use createMemo() instead: const {{signalName}} = createMemo(() => {{expression}});" } }, { "id": "effect-as-mount", "severity": "error", "description": "Detect createEffect/createRenderEffect with no reactive dependencies that should be onMount instead", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "effectAsMount": "This {{primitive}} has no reactive dependencies and runs only once. Use onMount() for initialization logic that doesn't need to re-run." } }, { "id": "inline-component", "severity": "error", "description": "Detect component functions defined inside other components, which causes remount on every parent update", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "inlineComponent": "Component '{{name}}' is defined inside another component. This creates a new component type on every render, causing unmount/remount. Move the component definition outside." } }, { "id": "no-top-level-signal-call", "severity": "error", "description": "Disallow calling signals at component top-level (captures stale snapshots)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "assignedToVar": "'{{name}}()' assigned to '{{varName}}' in {{componentName}} captures a one-time snapshot. '{{varName}}' won't update when {{name}} changes. Use createMemo(): `const {{varName}} = createMemo(() => {{name}}());`", "computedValue": "'{{name}}()' in computation at top-level of {{componentName}} captures a stale snapshot. Wrap with createMemo(): `const {{varName}} = createMemo(() => /* computation using {{name}}() */);`", "templateLiteral": "'{{name}}()' in template literal at top-level of {{componentName}} captures a stale snapshot. Use createMemo() or compute directly in JSX: `{`Hello, ${{{name}}()}!`}`", "destructuring": "Destructuring '{{name}}()' at top-level of {{componentName}} captures a stale snapshot. Access properties in JSX or createMemo(): `{{{name}}().propertyName}`", "objectLiteral": "'{{name}}()' in object literal at top-level of {{componentName}} captures a stale snapshot. Use createMemo() for the object, or spread in JSX.", "arrayCreation": "'{{name}}()' in array creation at top-level of {{componentName}} captures a stale snapshot. Wrap with createMemo(): `const items = createMemo(() => Array.from(...));`", "earlyReturn": "'{{name}}()' in early return at top-level of {{componentName}} captures a stale snapshot. Use <Show when={{{name}}()}> for conditional rendering instead.", "conditionalAssign": "'{{name}}()' in ternary at top-level of {{componentName}} captures a stale snapshot. Use createMemo() or compute in JSX: `{{{name}}() ? 'Yes' : 'No'}`", "functionArgument": "'{{name}}()' passed as argument at top-level of {{componentName}} captures a stale snapshot. Move to createEffect() or compute in JSX.", "syncCallback": "'{{name}}()' inside {{methodName}}() at top-level of {{componentName}} captures a stale snapshot. Wrap the entire computation in createMemo(): `const result = createMemo(() => items.{{methodName}}(...));`", "topLevelCall": "'{{name}}()' at top-level of {{componentName}} captures a one-time snapshot. Changes to {{name}} won't update the result. Call directly in JSX or wrap in createMemo()." } }, { "id": "ref-early-access", "severity": "error", "description": "Detect accessing refs before they are assigned (before mount)", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "refBeforeMount": "Ref '{{name}}' is accessed before component mounts. Refs are undefined until after mount. Access in onMount(), createEffect(), or event handlers." } }, { "id": "resource-access-unchecked", "severity": "error", "description": "Detect accessing resource data without checking loading/error state.", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "resourceUnchecked": "Accessing resource '{{name}}' without checking loading/error state may return undefined. Wrap in <Show when={!{{name}}.loading}> or <Suspense>." } }, { "id": "resource-implicit-suspense", "severity": "warn", "description": "Detect createResource that implicitly triggers or permanently breaks Suspense boundaries.", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "loadingMismatch": "createResource '{{name}}' has no initialValue but uses {{name}}.loading for manual loading UI. Suspense intercepts before your loading UI renders \u2014 the component is unmounted before the <Show>/<Switch> evaluates. Replace createResource with onMount + createSignal to decouple from Suspense entirely.", "conditionalSuspense": "createResource '{{name}}' is inside a conditional mount point ({{mountTag}}) with a distant Suspense boundary. The SuspenseContext increment fires when the fetcher's Promise is pending and unmounts the entire page subtree \u2014 initialValue does NOT prevent this. Replace createResource with onMount + createSignal to avoid Suspense interaction.", "missingErrorBoundary": "createResource '{{name}}' has no <ErrorBoundary> between its component and the nearest <Suspense>. When the fetcher throws (network error, 401/403/503, timeout), the error propagates to Suspense which has no error handling \u2014 the boundary breaks permanently. Wrap the component in <ErrorBoundary> or replace createResource with onMount + createSignal and catch errors in the fetcher." } }, { "id": "resource-refetch-loop", "severity": "error", "description": "Detect refetch() calls inside createEffect which can cause infinite loops", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "refetchInEffect": "Calling {{name}}.refetch() inside createEffect may cause infinite loops. The resource tracks its own dependencies. Move refetch to an event handler or use on() to control dependencies." } }, { "id": "signal-call", "severity": "error", "description": "Require signals to be called as functions when used in tracked contexts", "fixable": true, "category": "reactivity", "plugin": "solid", "messages": { "signalInJsxText": "Signal '{{name}}' in JSX text should be called: {{{name}}()}. Without (), you're rendering the function, not its value.", "signalInJsxAttribute": "Signal '{{name}}' in JSX attribute should be called: {{attr}}={{{name}}()}. Without (), the attribute won't update reactively.", "signalInTernary": "Signal '{{name}}' in ternary should be called: {{name}}() ? ... : .... The condition won't react to changes without ().", "signalInLogical": "Signal '{{name}}' in logical expression should be called: {{name}}() && .... Without (), this always evaluates to truthy (functions are truthy).", "signalInComparison": "Signal '{{name}}' in comparison should be called: {{name}}() === .... Comparing functions always returns false.", "signalInArithmetic": "Signal '{{name}}' in arithmetic should be called: {{name}}() + .... Math on functions produces NaN.", "signalInTemplate": "Signal '{{name}}' in template literal should be called: `...${{{name}}()}...`. Without (), you're embedding '[Function]'.", "signalInTrackedScope": "Signal '{{name}}' in {{where}} should be called: {{name}}(). Without (), reactivity is lost.", "badSignal": "The reactive variable '{{name}}' should be called as a function when used in {{where}}." } }, { "id": "signal-in-loop", "severity": "error", "description": "Detect problematic signal usage inside For/Index loop callbacks", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "signalInLoop": "Creating signals inside <{{component}}> callback creates new signals on each render. Use a store at the parent level, or derive state from the index.", "signalCallInvariant": "Signal '{{name}}' called inside <{{component}}> produces the same value for every item. Extract to a variable or memoize with createMemo() before the loop.", "derivedCallInvariant": "'{{name}}()' inside <{{component}}> captures {{captures}} but doesn't use the loop item. Extract the call before the loop or pass the item as a parameter." } }, { "id": "store-reactive-break", "severity": "error", "description": "Detect patterns that break store reactivity: spreading stores, top-level property extraction, or destructuring", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "storeSpread": "Spreading a store ({...store}) creates a static snapshot that won't update. Access store properties directly in JSX or tracked contexts.", "storeTopLevelAccess": "Accessing store property '{{property}}' at component top-level captures the value once. Access store.{{property}} directly in JSX or wrap in createMemo().", "storeDestructure": "Destructuring a store breaks reactivity. Access properties via store.{{property}} instead of destructuring." } }, { "id": "transition-pending-unchecked", "severity": "error", "description": "Detect useTransition usage without handling the isPending state", "fixable": false, "category": "reactivity", "plugin": "solid", "messages": { "pendingUnchecked": "useTransition returns [isPending, startTransition]. The isPending state should be used to show loading UI during transitions." } }],
|
|
42517
42739
|
"solid": [{ "id": "batch-optimization", "severity": "warn", "description": "Suggest using batch() when multiple signal setters are called in the same synchronous scope", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "multipleSetters": "Multiple signal updates in the same scope cause multiple re-renders. Wrap in batch() for a single update: batch(() => { {{setters}} });" } }, { "id": "imports", "severity": "error", "description": 'Enforce consistent imports from "solid-js", "solid-js/web", and "solid-js/store".', "fixable": false, "category": "solid", "plugin": "solid", "messages": { "preferSource": 'Prefer importing {{name}} from "{{source}}".' } }, { "id": "index-vs-for", "severity": "warn", "description": "Suggest <For> for object arrays and <Index> for primitive arrays.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "indexWithObjects": "<Index> with object arrays causes the item accessor to change on any array mutation. Use <For> for objects to maintain reference stability.", "forWithPrimitives": "<For> with primitive arrays (strings, numbers) keys by value, which may cause unexpected re-renders. Consider <Index> if index stability is preferred." } }, { "id": "no-react-deps", "severity": "error", "description": "Disallow usage of dependency arrays in `createEffect`, `createMemo`, and `createRenderEffect`.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "noUselessDep": "In Solid, `{{name}}` doesn't accept a dependency array because it automatically tracks its dependencies. If you really need to override the list of dependencies, use `on`." } }, { "id": "no-react-specific-props", "severity": "error", "description": "Disallow usage of React-specific `className`/`htmlFor` props, which were deprecated in v1.4.0.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "prefer": "Prefer the `{{to}}` prop over the deprecated `{{from}}` prop.", "noUselessKey": "Elements in a <For> or <Index> list do not need a key prop." } }, { "id": "prefer-for", "severity": "warn", "description": "Enforce using Solid's `<For />` component for mapping an array to JSX elements.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "preferFor": "Prefer Solid's `<For each={...}>` component for rendering lists of objects. Array#map recreates all DOM elements on every update, while <For> updates only changed items by keying on reference.", "preferIndex": "Prefer Solid's `<Index each={...}>` component for rendering lists of primitives. Array#map recreates all DOM elements on every update, while <Index> updates only changed items by keying on index position.", "preferForOrIndex": "Prefer Solid's `<For />` or `<Index />` component for rendering lists. Use <For> when items are objects (keys by reference), or <Index> when items are primitives like strings/numbers (keys by index). Array#map recreates all DOM elements on every update." } }, { "id": "prefer-memo-complex-styles", "severity": "warn", "description": "Enforce extracting complex style computations to createMemo for better approach. Complex inline style objects are rebuilt on every render, which can impact approach.", "fixable": false, "category": "solid", "plugin": "solid", "messages": { "preferMemoComplexStyle": "Complex style computation should be extracted to createMemo() for better approach. This style object contains {{complexity}} conditional expressions that are recalculated on every render.", "preferMemoConditionalSpread": "Conditional spread operators in style objects should be extracted to createMemo(). Pattern like `...(condition ? {...} : {})` creates new objects on every render." } }, { "id": "prefer-show", "severity": "warn", "description": "Enforce using Solid's `<Show />` component for conditionally showing content. Solid's compiler covers this case, so it's a stylistic rule only.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "preferShowAnd": "Prefer Solid's `<Show when={...}>` component for conditional rendering. While Solid's compiler handles `&&` expressions, <Show> is more explicit and provides better readability for conditional content.", "preferShowTernary": "Prefer Solid's `<Show when={...} fallback={...}>` component for conditional rendering with a fallback. This provides clearer intent and better readability than ternary expressions." } }, { "id": "self-closing-comp", "severity": "warn", "description": "Disallow extra closing tags for components without children.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "selfClose": "Empty elements should be self-closing. Use `<{{name}} />` instead of `<{{name}}></{{name}}>` for cleaner, more concise JSX.", "dontSelfClose": "This element should not be self-closing based on your configuration. Use `<{{name}}></{{name}}>` instead of `<{{name}} />` for explicit opening and closing tags." } }, { "id": "style-prop", "severity": "warn", "description": "Require CSS properties in the `style` prop to be valid and kebab-cased (ex. 'font-size'), not camel-cased (ex. 'fontSize') like in React, and that property values with dimensions are strings, not numbers with implicit 'px' units.", "fixable": true, "category": "solid", "plugin": "solid", "messages": { "kebabStyleProp": "Solid uses kebab-case for CSS property names, not camelCase like React. Use '{{kebabName}}' instead of '{{name}}'.", "invalidStyleProp": "'{{name}}' is not a valid CSS property. Check for typos, or if this is a custom property, prefix it with '--' (e.g., '--{{name}}').", "numericStyleValue": "Numeric values for dimensional properties need explicit units in Solid. Unlike React, Solid does not auto-append 'px'. Use '{{value}}px' or another appropriate unit.", "stringStyle": "Use an object for the style prop instead of a string for better approach and type safety. Example: style={{ '{{prop}}': '{{value}}' }}." } }]
|
|
42518
42740
|
};
|
|
42519
42741
|
function getRule2(id) {
|