fix(web): keep credential sync reset ahead of repaint wiring in mount
Task 7 reordered mount_ck so the daemon-dependent web_credential_sync::start() runs only after the postMessage bridge init gate. But start() bundled two things: a pure state reset (*self = default) and a daemon policy fetch. Moving the whole call past the gate also moved the reset past repaint_coalescer::install, so an early repaint (e.g. during the 2s await_init in an iframe) could queue a credential change via credential_changed() that the later reset silently wiped — the pre-existing invariant guarded by canvaskit_repaint_persists_local_settings_and_syncs_only_credential_changes. Split the two phases: add web_credential_sync::reset() (pure state clear, no daemon request) called BEFORE the first repaint and the rAF coalescer install, and keep start() (now begin_policy_check only, the daemon fetch) after the bridge gate. Both invariants hold: the reset precedes repaint wiring, and no daemon request fires before the gate. The daemon behavior is unchanged in the normal flow (reset() then begin_policy_check equals the old start()), and strictly better in the race edge — a change queued between reset and start is now preserved instead of wiped. Test updated to assert the reset (not the now-daemon-facing start) precedes install; the semantic invariant it protects is unchanged and is now expressed against the actual code order. start()'s ordering after the gate stays covered by canvaskit_mount_queues_an_initial_snapshot_only_when_local_credentials_exist.
This commit is contained in:
parent
b6077ab09b
commit
cd465f9899
|
|
@ -952,6 +952,14 @@ pub async fn mount_ck(canvas_id: String) -> Result<(), JsValue> {
|
|||
a11y,
|
||||
ime,
|
||||
}));
|
||||
// Reset the credential-sync queue BEFORE the first repaint and before the
|
||||
// rAF coalescer is installed below. `repaint` calls
|
||||
// `web_credential_sync::credential_changed` whenever a credential edit
|
||||
// lands, so the reset must precede any repaint wiring — otherwise an early
|
||||
// repaint could queue a change that a later reset silently wipes. This is a
|
||||
// pure state reset (no daemon request), so it is safe ahead of the bridge
|
||||
// init gate; the daemon-facing policy fetch (`start`) still waits for it.
|
||||
crate::web_credential_sync::reset();
|
||||
{
|
||||
let mut b = inner.borrow_mut();
|
||||
let _ = b.resize_to_window(&window)?;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ enum SyncAction {
|
|||
}
|
||||
|
||||
impl CredentialSyncState {
|
||||
// Combined reset + policy-check. The mount now drives these two phases
|
||||
// separately (`reset` early, `start` after the bridge gate), so this stays
|
||||
// as the state-machine's tested "full start" shape.
|
||||
#[cfg(test)]
|
||||
fn start(&mut self) -> SyncAction {
|
||||
*self = Self::default();
|
||||
self.begin_policy_check()
|
||||
|
|
@ -138,8 +142,20 @@ thread_local! {
|
|||
static SYNC_STATE: RefCell<CredentialSyncState> = RefCell::new(CredentialSyncState::default());
|
||||
}
|
||||
|
||||
/// Clear the transient credential-sync queue. Split out of `start` so the
|
||||
/// mount can reset state BEFORE repaint callbacks are wired: `repaint` calls
|
||||
/// `credential_changed` when a credential edit lands, so an early repaint must
|
||||
/// not queue a change that a later reset silently wipes. This issues no daemon
|
||||
/// request, so it is safe to run ahead of the postMessage bridge init gate.
|
||||
pub(crate) fn reset() {
|
||||
SYNC_STATE.with(|state| *state.borrow_mut() = CredentialSyncState::default());
|
||||
}
|
||||
|
||||
/// Begin credential-policy discovery against the daemon. This issues a daemon
|
||||
/// request, so the mount calls it only AFTER the bridge init gate (managed mode
|
||||
/// needs the auth token on the wire). State must already be cleared via `reset`.
|
||||
pub(crate) fn start() {
|
||||
let action = SYNC_STATE.with(|state| state.borrow_mut().start());
|
||||
let action = SYNC_STATE.with(|state| state.borrow_mut().begin_policy_check());
|
||||
dispatch(action);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,11 +117,11 @@ fn canvaskit_repaint_persists_local_settings_and_syncs_only_credential_changes()
|
|||
let install = source
|
||||
.find("repaint_coalescer::install")
|
||||
.expect("repaint coalescer installation");
|
||||
let sync_start = source
|
||||
.find("web_credential_sync::start")
|
||||
.expect("credential policy discovery");
|
||||
let sync_reset = source
|
||||
.find("web_credential_sync::reset")
|
||||
.expect("credential sync state reset");
|
||||
assert!(
|
||||
sync_start < install,
|
||||
sync_reset < install,
|
||||
"credential sync state is reset before repaint callbacks can queue changes"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue