mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
Reject negative or fractional index in fill.set and stroke.set
Found while testing crates/engine/src/cmd/edit.rs:1180 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
23bdebd973
commit
a911ab9614
@@ -1177,7 +1177,7 @@ fn paint_list(s: &mut Session, p: &Value, fills: bool, add: bool) -> Result<Valu
|
||||
fn paint_set(s: &mut Session, p: &Value, fills: bool) -> Result<Value> {
|
||||
let cmd = if fills { "fill.set" } else { "stroke.set" };
|
||||
let ids = req_targets(cmd, s, p)?;
|
||||
let idx = num(p, "index").map(|x| x.max(0.0) as usize);
|
||||
let idx = if get(p, "index").is_none() { None } else { Some(req_index(cmd, p, "index")?) };
|
||||
let new_paint = match get(p, "paint") {
|
||||
Some(v) => Some(paint_of(v).ok_or_else(|| bad(cmd, "invalid paint"))?),
|
||||
None => None,
|
||||
|
||||
@@ -1594,6 +1594,8 @@ mod page_copy_navigation_tests;
|
||||
#[cfg(test)]
|
||||
mod page_target_tests;
|
||||
#[cfg(test)]
|
||||
mod paint_index_tests;
|
||||
#[cfg(test)]
|
||||
mod paint_reorder_tests;
|
||||
#[cfg(test)]
|
||||
mod paint_tests;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//! `fill.set` / `stroke.set` reject a negative, fractional or non-finite `index` instead of
|
||||
//! clamping or truncating it onto another paint (like `fill.remove` / `stroke.remove`).
|
||||
|
||||
use figcraft_doc::NodeId;
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::Session;
|
||||
|
||||
fn ex(s: &mut Session, cmd: &str, p: Value) -> Value {
|
||||
s.execute(cmd, &p).unwrap_or_else(|e| panic!("{cmd} {p}: {e}"))
|
||||
}
|
||||
|
||||
fn paints(s: &Session, id: NodeId) -> String {
|
||||
let n = s.doc().unwrap().node(id).unwrap();
|
||||
format!("{:?} {:?}", n.fills, n.strokes)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paint_set_rejects_bad_index_and_leaves_the_paints_alone() {
|
||||
let mut s = Session::new();
|
||||
let r = NodeId(ex(&mut s, "shape.rectangle", json!({"x": 0, "y": 0, "width": 10, "height": 10}))["id"].as_u64().unwrap());
|
||||
for add in ["fill.add", "stroke.add"] {
|
||||
for c in ["#0000FF", "#FFFF00"] {
|
||||
ex(&mut s, add, json!({"ids": [r], "color": c}));
|
||||
}
|
||||
}
|
||||
let before = paints(&s, r);
|
||||
for cmd in ["fill.set", "stroke.set"] {
|
||||
for bad in [json!(-1), json!(0.5), json!(1.9), json!("-1"), json!("1.5"), json!("NaN"), json!("inf"), json!("abc")] {
|
||||
let res = s.execute(cmd, &json!({"ids": [r], "index": bad, "color": "#FF0000"}));
|
||||
assert!(res.is_err(), "{cmd} index {bad} was accepted: {res:?}");
|
||||
assert_eq!(paints(&s, r), before, "{cmd} index {bad} changed the document");
|
||||
}
|
||||
ex(&mut s, cmd, json!({"ids": [r], "index": 1, "color": "#FF0000"}));
|
||||
assert_ne!(paints(&s, r), before, "{cmd} with a valid index still edits");
|
||||
ex(&mut s, "edit.undo", json!({}));
|
||||
assert_eq!(paints(&s, r), before);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user