diff --git a/crates/engine/src/cmd/assets.rs b/crates/engine/src/cmd/assets.rs index c8a817d5..7962b2db 100644 --- a/crates/engine/src/cmd/assets.rs +++ b/crates/engine/src/cmd/assets.rs @@ -80,12 +80,13 @@ fn clean_name(name: &str) -> Option { fn add(s: &mut Session, p: &Value) -> Result { const C: &str = "assets.add"; - let ids = match ids_param(p, "ids") { - Some(ids) => { - let d = &s.doc()?.doc; - roots_of(d, d.paint_order(ids)) - } - None => selected_roots(s)?, + let ids = if p.get("ids").is_some_and(|v| !v.is_null()) { + // An explicit list is authoritative: never silently drop malformed or stale ids. + let ids = checked_ids_param(s, p, "ids", C)?; + let d = &s.doc()?.doc; + roots_of(d, d.paint_order(ids)) + } else { + selected_roots(s)? }; if ids.is_empty() { return Err(bad(C, "select the art to collect (or give its ids)")); diff --git a/crates/engine/src/tests_assets.rs b/crates/engine/src/tests_assets.rs index 2a674b15..79c11c99 100644 --- a/crates/engine/src/tests_assets.rs +++ b/crates/engine/src/tests_assets.rs @@ -265,3 +265,21 @@ fn assets_export_into_a_folder() { assert!(dir.join("2x/Logo@2x.png").is_file() && dir.join("PDF/Logo.pdf").is_file()); let _ = std::fs::remove_dir_all(&dir); } + +#[test] +fn collecting_explicit_assets_rejects_invalid_ids_without_adding_anything() { + let mut s = session(); + let a = rect(&mut s, 10.0, 10.0, 20.0, 20.0); + let b = rect(&mut s, 50.0, 10.0, 20.0, 20.0); + let original_selection = s.doc().unwrap().selection.objects.clone(); + let before = undo_len(&s); + for ids in [json!([a, "not an object"]), json!([a, 3.5]), json!([a, u64::MAX]), json!({"id": a})] { + assert!(s.execute("assets.add", &json!({"ids": ids})).is_err(), "invalid ids: {ids}"); + assert!(assets(&mut s).is_empty(), "invalid ids must not collect only the valid subset"); + assert_eq!(undo_len(&s), before); + assert_eq!(s.doc().unwrap().selection.objects, original_selection); + } + // Valid ids still collect art in document paint order. + assert_eq!(run(&mut s, "assets.add", json!({"ids": [b, a]}))["added"], 2); + assert_eq!(assets(&mut s).len(), 2); +}