mirror of
https://github.com/block/buzz.git
synced 2026-10-30 14:01:37 +00:00
Three review findings against the tracer's honesty contract: - The readiness -> paint frame was unguarded. `awaitDeferredCommit` checks age, frame gap, and visibility on every frame it drives, but the one rAF it queues before `record()` checked neither age nor gap, so a suspension in that seam (App Nap fires no visibilitychange) recorded the whole absence as a clean switch. - DM actions await `open_dm` before `goChannel`, so that relay round-trip sat outside the measurement; Pulse's note actions used raw `navigate` and produced no measurement at all. Callers now capture the click anchor and hand it to `goChannel`, and Pulse routes through `goChannel`. - A `navigate()` rejection left the trace it opened active, so an untraced re-entry could settle the failed attempt. Cancellation is by trace identity, so a newer same-channel attempt is never erased. Signed-off-by: Max Lampert <maxwell@squareup.com>
78 lines
2.7 KiB
TypeScript
78 lines
2.7 KiB
TypeScript
import {
|
|
allowNavigation,
|
|
type GuardedNavigation,
|
|
} from "@/app/navigation/navigationGuard";
|
|
import {
|
|
beginChannelSwitchTrace,
|
|
cancelChannelSwitchTrace,
|
|
dropActiveChannelSwitchTrace,
|
|
} from "@/shared/lib/channelSwitchPerf";
|
|
|
|
/**
|
|
* commitGuardedNavigation runs the shared commit flow for app navigations:
|
|
* skip same-destination no-ops, consult the navigation guard, then navigate.
|
|
* `force` and `hasStateUpdate` both defeat the no-op skip — a same-href
|
|
* navigation that writes router state (setting or clearing the search
|
|
* highlight) must commit, or the state never lands. When `traceChannelId` is
|
|
* set, the channel-switch trace opens only after the guard accepts — a
|
|
* refused click must not leave an orphan trace that a later history
|
|
* navigation (deliberately untraced) would settle with the refused click's
|
|
* inflated wall time. When `leavesChannelSurface` is set, any active trace is
|
|
* dropped instead: the trace may be live with no channel screen mounted
|
|
* (route still resolving), so this is the only reliable exit hook. A
|
|
* `navigate()` rejection cancels the trace this call opened — by identity, so
|
|
* a newer same-channel attempt is never erased — because no destination
|
|
* committed and an untraced re-entry would otherwise settle the failed
|
|
* attempt. Returns whether the navigation was performed. `deps` exists for
|
|
* unit tests.
|
|
*/
|
|
export async function commitGuardedNavigation(
|
|
input: {
|
|
currentHref: string;
|
|
nextHref: string;
|
|
force?: boolean;
|
|
guardedTarget: GuardedNavigation;
|
|
hasStateUpdate?: boolean;
|
|
leavesChannelSurface?: boolean;
|
|
traceChannelId?: string;
|
|
/** Click-time anchor for callers that await before `goChannel`. */
|
|
traceStartedAt?: number;
|
|
navigate: () => Promise<unknown>;
|
|
},
|
|
deps: {
|
|
allow?: typeof allowNavigation;
|
|
beginTrace?: typeof beginChannelSwitchTrace;
|
|
cancelTrace?: typeof cancelChannelSwitchTrace;
|
|
dropActiveTrace?: typeof dropActiveChannelSwitchTrace;
|
|
} = {},
|
|
): Promise<boolean> {
|
|
const allow = deps.allow ?? allowNavigation;
|
|
const beginTrace = deps.beginTrace ?? beginChannelSwitchTrace;
|
|
const cancelTrace = deps.cancelTrace ?? cancelChannelSwitchTrace;
|
|
const dropActiveTrace = deps.dropActiveTrace ?? dropActiveChannelSwitchTrace;
|
|
if (
|
|
input.currentHref === input.nextHref &&
|
|
!input.force &&
|
|
!input.hasStateUpdate
|
|
) {
|
|
return false;
|
|
}
|
|
if (!allow(input.guardedTarget)) {
|
|
return false;
|
|
}
|
|
if (input.leavesChannelSurface) {
|
|
dropActiveTrace();
|
|
}
|
|
let handle = null;
|
|
if (input.traceChannelId !== undefined) {
|
|
handle = beginTrace(input.traceChannelId, input.traceStartedAt) ?? null;
|
|
}
|
|
try {
|
|
await input.navigate();
|
|
} catch (error) {
|
|
cancelTrace(handle);
|
|
throw error;
|
|
}
|
|
return true;
|
|
}
|