fix(flex): flex.reorder clamps a huge by instead of overflowing (#973)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-14 22:49:37 -04:00
co-authored by Claude Opus 5.5
parent ee498ac68f
commit 8a98451d2d
+11 -1
View File
@@ -378,7 +378,7 @@ fn reorder(s: &mut Session, p: &Value) -> Result<Value> {
let Content::Group { items } = &mut c.content else { return Err(bad("flex.reorder", "the object isn't in a Flex Layout")) };
let n = items.len() as i64;
let from = *last as i64;
let target = to.unwrap_or(from + by.unwrap_or(0)).clamp(0, n - 1);
let target = to.unwrap_or(from.saturating_add(by.unwrap_or(0))).clamp(0, n - 1);
let moved = items.remove(from as usize);
items.insert(target as usize, moved);
*sel = Selection::items(vec![id]);
@@ -428,6 +428,16 @@ mod tests {
s.doc().unwrap().doc.item(ItemId(id)).unwrap().bounds()
}
#[test]
fn reorder_by_a_huge_step_clamps_instead_of_overflowing() {
let (mut s, ids) = session_with_boxes(&[[84.0, 84.0, 184.0, 184.0], [284.0, 84.0, 384.0, 184.0]]);
s.execute("selection.set", &json!({"ids": ids})).unwrap();
s.execute("flex.add", &json!({})).unwrap();
// `from + by` used to overflow (a panic with overflow checks on).
s.execute("flex.reorder", &json!({"id": ids[0], "by": i64::MAX})).unwrap();
s.execute("flex.reorder", &json!({"id": ids[0], "by": i64::MIN})).unwrap();
}
/// The video: four objects in a row become a container that keeps them where they are (Row,
/// Auto size, Space Between at their spacing, aligned to the top), then a fixed 2-column layout.
#[test]