Files
rea/src/domain/javascript/javascriptSemanticPrimitives.ts
T
Ysopwnable 9f8659e053 fix(javascript): enforce semantic byte bounds for literals
Fixes #3933. Part of #4027.

Normalize exact literals and configuration defaults through the shared primitive owner. Preserve tagged limits through member/destructuring projection and record encountered bounds in per-analysis state independently of later selected values. Remove the retained-value rescan and duplicate default reader. Preserve source Evidence, bounded/null values, aggregate wire capacity and complete endpoint lookup identities for query/trace/comparison.

Validated 66 focused and 932 semantic tests on the restored identical runtime; final public selection 7/7 adds an augmented large-endpoint acceptance (67 distinct focused cases across invocations). Full static/docs and fresh real Obsidian controls passed. Compact measurements and rejected attempts remain recorded.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-15 23:43:05 +08:00

69 lines
2.6 KiB
TypeScript

import type {
JavaScriptSemanticPrimitive,
JavaScriptSemanticValue,
} from "./javascriptSemanticValueTypes.js";
import { compareUnicodeCodePoints } from "../unicodeCodePointOrder.js";
import { semanticPrimitiveKey } from "./javascriptSemanticProvenance.js";
import {
SEMANTIC_PRIMITIVE_CANDIDATE_LIMIT,
exceedsSemanticPrimitiveStringByteBudget,
semanticResourceLimitUnknown,
} from "./javascriptSemanticResourceLimits.js";
/** Normalize one bounded collection of possible primitive values. */
export const semanticPrimitiveSet = (
values: readonly JavaScriptSemanticPrimitive[],
): JavaScriptSemanticValue => {
let uniqueValues: Set<JavaScriptSemanticPrimitive> | undefined;
for (const value of values) {
if (typeof value === "number" && !Number.isFinite(value))
return {
status: "unknown",
reason: "Nonfinite numbers are outside the JSON primitive lattice.",
};
if (typeof value === "number" && Object.is(value, -0))
return {
status: "unknown",
reason: "Negative zero cannot be preserved by JSON primitive evidence.",
};
// The common literal path needs validation, but no deduplication, sorting
// or canonical-key allocation. Check strings before retaining the value.
if (values.length === 1)
return typeof value === "string" &&
exceedsSemanticPrimitiveStringByteBudget([value])
? semanticResourceLimitUnknown("primitive-bytes")
: { status: "literal", value };
uniqueValues ??= new Set<JavaScriptSemanticPrimitive>();
uniqueValues.add(value);
if (uniqueValues.size > SEMANTIC_PRIMITIVE_CANDIDATE_LIMIT)
return semanticResourceLimitUnknown("primitive-candidates");
}
if (uniqueValues === undefined) return { status: "union", values: [] };
if (
exceedsSemanticPrimitiveStringByteBudget(
[...uniqueValues].flatMap((value) =>
typeof value === "string" ? [value] : [],
),
)
)
return semanticResourceLimitUnknown("primitive-bytes");
const unique = [...uniqueValues]
.map((value) => ({ key: semanticPrimitiveKey(value), value }))
.sort((left, right) => compareUnicodeCodePoints(left.key, right.key))
.map(({ value }) => value);
const only = unique[0];
return unique.length === 1 && only !== undefined
? { status: "literal", value: only }
: { status: "union", values: unique };
};
/** Read the primitive candidates retained in one lattice value. */
export const semanticPrimitiveCandidates = (
value: JavaScriptSemanticValue,
): readonly JavaScriptSemanticPrimitive[] | null =>
value.status === "literal"
? [value.value]
: value.status === "union"
? value.values
: null;