From f1f7da1f40c27b2476ee287a3aea045f0ba861c1 Mon Sep 17 00:00:00 2001 From: midasmatterhorn <248507632+midasmatterhorn@users.noreply.github.com> Date: Wed, 14 Oct 2026 18:01:41 +0300 Subject: [PATCH] engine: refuse page.move for node ids that are not pages --- crates/engine/src/cmd/page.rs | 3 +++ crates/engine/src/panels_behaviour_tests.rs | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/crates/engine/src/cmd/page.rs b/crates/engine/src/cmd/page.rs index b2d46988..3fd03746 100644 --- a/crates/engine/src/cmd/page.rs +++ b/crates/engine/src/cmd/page.rs @@ -102,6 +102,9 @@ pub fn specs() -> Vec { let id = id(p, "id").unwrap_or(s.page()?); let k = req_num("page.move", p, "index")?.max(0.0) as usize; let doc = s.doc_mut()?; + if !doc.pages.contains(&id) { + return Err(bad("page.move", format!("{id} is not a page"))); + } doc.pages.retain(|x| *x != id); let k = k.min(doc.pages.len()); doc.pages.insert(k, id); diff --git a/crates/engine/src/panels_behaviour_tests.rs b/crates/engine/src/panels_behaviour_tests.rs index f2802461..99b1caa8 100644 --- a/crates/engine/src/panels_behaviour_tests.rs +++ b/crates/engine/src/panels_behaviour_tests.rs @@ -337,6 +337,17 @@ fn pages_by_the_documented_rules() { assert_ne!(s.page().unwrap(), div, "deleting the open page opens a page, never a divider"); } +#[test] +fn page_move_refuses_what_is_not_a_page() { + let mut s = Session::new(); + let r = rect(&mut s, "r", 30.0, 40.0, None); + let before = pages(&mut s); + assert!(s.execute("page.move", &json!({"id": r, "index": 0})).is_err(), "a layer id is not a page"); + assert!(s.execute("page.move", &json!({"id": 999999, "index": 0})).is_err(), "a page that isn't there is not a page"); + assert_eq!(pages(&mut s), before, "the page list is untouched"); + assert!(s.doc().unwrap().validate().is_empty(), "the document still checks out"); +} + #[test] fn assets_panel_lists_files_and_drops_by_the_documented_rules() { let mut s = Session::new();