Reject negative or fractional index in effect.set, export.update and export.remove

Found while testing crates/engine/src/cmd/edit.rs:256 (effect.set), :305 (export.update), :317 (export.remove)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-15 01:08:36 +00:00
co-authored by Claude Haiku 5.5
parent 833f0d2c27
commit 87b9a3a9ce
2 changed files with 24 additions and 3 deletions
+3 -3
View File
@@ -253,7 +253,7 @@ pub fn specs() -> Vec<CommandSpec> {
ok()
}),
spec!("effect.set", "Set effect", "{ids?, index, effect {..}}", true, |s, p| {
let i = req_num("effect.set", p, "index")? as usize;
let i = req_index("effect.set", p, "index")?;
let e: Effect = parse("effect.set", p, "effect")?.ok_or_else(|| bad("effect.set", "`effect` required"))?;
for id in req_targets("effect.set", s, p)? {
let n = s.doc_mut()?.get_mut(id)?;
@@ -302,7 +302,7 @@ pub fn specs() -> Vec<CommandSpec> {
true,
|s, p| {
let cmd = "export.update";
let i = req_num(cmd, p, "index")? as usize;
let i = req_index(cmd, p, "index")?;
super::file::export_setting(cmd, ExportSetting::default(), p)?;
for id in req_targets(cmd, s, p)? {
let n = s.doc_mut()?.get_mut(id)?;
@@ -314,7 +314,7 @@ pub fn specs() -> Vec<CommandSpec> {
}
),
spec!("export.remove", "Remove export setting", "{ids?, index}", true, |s, p| {
let i = req_num("export.remove", p, "index")? as usize;
let i = req_index("export.remove", p, "index")?;
for id in req_targets("export.remove", s, p)? {
let n = s.doc_mut()?.get_mut(id)?;
if i < n.exports.len() {
+21
View File
@@ -85,3 +85,24 @@ fn inspect_and_css_show_the_new_effects() {
let css = code_for(doc, r, CodeLang::Css);
assert!(css.contains("backdrop-filter: blur(2px);"), "{css}");
}
#[test]
fn negative_or_fractional_index_is_refused_not_item_zero() {
let mut s = Session::new();
let r = rect(&mut s);
s.execute("effect.add", &json!({"ids": [r], "type": "layerBlur"})).unwrap();
s.execute("export.add", &json!({"ids": [r]})).unwrap();
s.execute("export.add", &json!({"ids": [r]})).unwrap();
let before = s.doc().unwrap().node(r).unwrap().clone();
assert_eq!(before.exports.len(), 2);
for index in [json!(-1), json!(-0.5), json!(1.5)] {
let set = json!({"ids": [r], "index": index, "effect": {"type": "dropShadow"}});
assert!(s.execute("effect.set", &set).is_err(), "effect.set index {index}");
let upd = json!({"ids": [r], "index": index, "format": "svg"});
assert!(s.execute("export.update", &upd).is_err(), "export.update index {index}");
assert!(s.execute("export.remove", &json!({"ids": [r], "index": index})).is_err(), "export.remove index {index}");
let n = s.doc().unwrap().node(r).unwrap();
assert_eq!(n.effects, before.effects, "index {index}");
assert_eq!(n.exports, before.exports, "index {index}");
}
}