perf: complete persist-load P2 hydration pass

This commit is contained in:
Youzini-afk
2026-04-22 19:31:44 +08:00
parent 37c6266a81
commit e880fe0b39
10 changed files with 1037 additions and 23 deletions

View File

@@ -58,6 +58,48 @@ function normalizeStringArray(values = []) {
return result;
}
function isAlreadyNormalizedStringArray(values = []) {
if (!Array.isArray(values)) return false;
const seen = new Set();
for (const value of values) {
if (typeof value !== "string") return false;
const normalized = normalizeString(value);
const key = normalizeKey(normalized);
if (!normalized || normalized !== value || seen.has(key)) {
return false;
}
seen.add(key);
}
return true;
}
function canReuseNormalizedMemoryScope(scope = {}, defaults = {}) {
if (
!scope ||
typeof scope !== "object" ||
Array.isArray(scope) ||
(defaults && typeof defaults === "object" && Object.keys(defaults).length > 0)
) {
return false;
}
const layer = normalizeLayer(scope.layer);
const ownerType = normalizeOwnerType(layer, normalizeString(scope.ownerType));
const ownerId = ownerType
? normalizeString(scope.ownerId || scope.ownerName)
: "";
const ownerName = ownerType ? normalizeString(scope.ownerName) : "";
const regionPrimary = normalizeString(scope.regionPrimary);
return (
scope.layer === layer &&
normalizeString(scope.ownerType) === ownerType &&
normalizeString(scope.ownerId || "") === ownerId &&
normalizeString(scope.ownerName || "") === ownerName &&
normalizeString(scope.regionPrimary || "") === regionPrimary &&
isAlreadyNormalizedStringArray(scope.regionPath) &&
isAlreadyNormalizedStringArray(scope.regionSecondary)
);
}
function normalizeOwnerValueSet(values = []) {
return new Set(
normalizeStringArray(values).map((value) => normalizeKey(value)),
@@ -88,6 +130,9 @@ export function createDefaultMemoryScope(overrides = {}) {
}
export function normalizeMemoryScope(scope = {}, defaults = {}) {
if (canReuseNormalizedMemoryScope(scope, defaults)) {
return scope;
}
const merged = {
...DEFAULT_MEMORY_SCOPE,
...(defaults || {}),

View File

@@ -147,7 +147,50 @@ export function createDefaultTimelineState(overrides = {}) {
};
}
function canReuseNormalizedStoryTime(value = {}, defaults = {}) {
if (
!value ||
typeof value !== "object" ||
Array.isArray(value) ||
(defaults && typeof defaults === "object" && Object.keys(defaults).length > 0)
) {
return false;
}
return (
normalizeString(value.segmentId || "") === String(value.segmentId || "") &&
normalizeString(value.label || "") === String(value.label || "") &&
normalizeEnum(value.tense, STORY_TENSE_VALUES, "unknown") === value.tense &&
normalizeEnum(value.relation, STORY_RELATION_VALUES, "unknown") === value.relation &&
normalizeString(value.anchorLabel || "") === String(value.anchorLabel || "") &&
normalizeEnum(value.confidence, STORY_CONFIDENCE_VALUES, "medium") ===
value.confidence &&
normalizeEnum(value.source, STORY_SOURCE_VALUES, "derived") === value.source
);
}
function canReuseNormalizedStoryTimeSpan(value = {}, defaults = {}) {
if (
!value ||
typeof value !== "object" ||
Array.isArray(value) ||
(defaults && typeof defaults === "object" && Object.keys(defaults).length > 0)
) {
return false;
}
return (
normalizeString(value.startSegmentId || "") === String(value.startSegmentId || "") &&
normalizeString(value.endSegmentId || "") === String(value.endSegmentId || "") &&
normalizeString(value.startLabel || "") === String(value.startLabel || "") &&
normalizeString(value.endLabel || "") === String(value.endLabel || "") &&
(value.mixed === true || value.mixed === false) &&
normalizeEnum(value.source, STORY_SOURCE_VALUES, "derived") === value.source
);
}
export function normalizeStoryTime(value = {}, defaults = {}) {
if (canReuseNormalizedStoryTime(value, defaults)) {
return value;
}
return createDefaultStoryTime({
...defaults,
...(value && typeof value === "object" && !Array.isArray(value) ? value : {}),
@@ -155,6 +198,9 @@ export function normalizeStoryTime(value = {}, defaults = {}) {
}
export function normalizeStoryTimeSpan(value = {}, defaults = {}) {
if (canReuseNormalizedStoryTimeSpan(value, defaults)) {
return value;
}
return createDefaultStoryTimeSpan({
...defaults,
...(value && typeof value === "object" && !Array.isArray(value) ? value : {}),