Merge remote-tracking branch 'origin/staging' into cloudflare-migration
This commit is contained in:
@@ -21,7 +21,7 @@ on:
|
|||||||
# branch-protection required check (cla/cla-assistant.yml) reports against.
|
# branch-protection required check (cla/cla-assistant.yml) reports against.
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: read
|
pull-requests: write
|
||||||
issues: write
|
issues: write
|
||||||
statuses: write
|
statuses: write
|
||||||
|
|
||||||
|
|||||||
@@ -902,10 +902,11 @@ function PlayInner() {
|
|||||||
lastSavedFingerprintRef.current = "";
|
lastSavedFingerprintRef.current = "";
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Defensive: saveStory is contracted never to throw, but if a future edit
|
.catch(() => {
|
||||||
// to this callback ever does, an unhandled rejection here would poison the
|
if (lastSavedFingerprintRef.current === fingerprint) {
|
||||||
// chain and freeze ALL subsequent saves. Swallow to keep the chain alive.
|
lastSavedFingerprintRef.current = "";
|
||||||
.catch(() => {});
|
}
|
||||||
|
});
|
||||||
}, [session]);
|
}, [session]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
currentSceneRef.current = currentScene;
|
currentSceneRef.current = currentScene;
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ export const STORY_SCHEMA_VERSION = 1;
|
|||||||
* crosses a storage/serialization boundary and could arrive as a non-number,
|
* crosses a storage/serialization boundary and could arrive as a non-number,
|
||||||
* guarding against the historical `t.getTime is not a function` white-screen. */
|
* guarding against the historical `t.getTime is not a function` white-screen. */
|
||||||
export function coerceEpoch(value: unknown, fallback: number): number {
|
export function coerceEpoch(value: unknown, fallback: number): number {
|
||||||
|
if (value == null) return fallback;
|
||||||
// Number.isFinite (not just !isNaN) so ±Infinity also falls through to the
|
// Number.isFinite (not just !isNaN) so ±Infinity also falls through to the
|
||||||
// fallback — new Date(Infinity).getTime() is NaN, not a usable epoch.
|
// fallback — new Date(Infinity).getTime() is NaN, not a usable epoch.
|
||||||
if (typeof value === "number" && Number.isFinite(value)) return value;
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
||||||
const d = value instanceof Date ? value : new Date(value as string | number);
|
const d = value instanceof Date ? value : new Date(value as string | number);
|
||||||
const t = d.getTime();
|
const t = d.getTime();
|
||||||
return Number.isNaN(t) ? fallback : t;
|
return Number.isFinite(t) ? t : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** local-first sync state of a record.
|
/** local-first sync state of a record.
|
||||||
|
|||||||
Reference in New Issue
Block a user