mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-26 19:18:14 -06:00
engine.batch: drop the events a rolled-back atomic batch queued
A failing atomic batch restored the project, history and state but left the events its steps had already published, so the UI could open the comp the rollback had just undone. Snapshot the event count with the other snapshots and truncate before the rollback bumps. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
@@ -56,6 +56,9 @@ fn batch(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let label = str_p(p, "label").unwrap_or("Batch").to_string();
|
||||
let atomic = p.get("atomic").and_then(Value::as_bool).unwrap_or(true);
|
||||
let (project, history, state) = (s.project.clone(), s.history.clone(), s.state.clone());
|
||||
// Rolled-back steps may have queued events (an `OpenComp`, a Toast) for the state that is
|
||||
// about to be dropped: the UI must not act on them.
|
||||
let event_mark = s.events.len();
|
||||
let mut results: Vec<Value> = Vec::with_capacity(steps.len());
|
||||
for (i, step) in steps.iter().enumerate() {
|
||||
let run = |s: &mut Session, results: &[Value]| -> Result<Value> {
|
||||
@@ -87,6 +90,7 @@ fn batch(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
s.project = project;
|
||||
s.history = history;
|
||||
s.state = state;
|
||||
s.events.truncate(event_mark);
|
||||
s.sanitize_after_replacement(edited.as_ref());
|
||||
s.ime_revision = s.ime_revision.max(interim_revision);
|
||||
s.bump();
|
||||
|
||||
@@ -542,6 +542,29 @@ fn atomic_batch_rollback_after_a_cross_comp_editor_switch_bumps_the_epoch() {
|
||||
assert_ime_epoch_changed(&s, owner, "an identical layer in another comp must not revive the old token");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_atomic_batch_drops_the_events_its_failed_steps_queued() {
|
||||
let (mut s, _) = session("abcdef");
|
||||
let original = s.active_comp_id().unwrap();
|
||||
// `comp.new` opens the comp it creates; go back so the batch's switch is a real one.
|
||||
let other = new_other_comp(&mut s);
|
||||
s.execute("comp.open", json!({"comp": original.0})).unwrap();
|
||||
s.drain_events();
|
||||
let r = s.execute(
|
||||
"engine.batch",
|
||||
json!({"atomic": true, "steps": [
|
||||
{"command": "comp.open", "params": {"comp": other}},
|
||||
{"command": "no.suchCommand", "params": {}}
|
||||
]}),
|
||||
);
|
||||
assert!(r.is_err());
|
||||
assert_eq!(s.active_comp_id(), Some(original), "the batch restored the original comp");
|
||||
assert!(
|
||||
!s.drain_events().iter().any(|e| matches!(e, crate::Event::OpenComp(id) if id.0 == other)),
|
||||
"the rolled-back step's OpenComp is not queued for the UI"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn atomic_batch_rollback_after_closing_the_editor_does_not_revive_it() {
|
||||
let (mut s, t) = session("abcdef");
|
||||
|
||||
Reference in New Issue
Block a user