From 9d10d84dee22252d0d4d747729767b1798100c53 Mon Sep 17 00:00:00 2001 From: Nigel Ihza Firdausy <106657905+Ni-zav@users.noreply.github.com> Date: Sat, 10 Oct 2026 15:53:14 +0700 Subject: [PATCH] fix(engine): validate text layer position coordinates (#537) --- crates/engine/src/commands/layer.rs | 2 +- crates/engine/src/tests.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/commands/layer.rs b/crates/engine/src/commands/layer.rs index eaf70cf7..0264373a 100644 --- a/crates/engine/src/commands/layer.rs +++ b/crates/engine/src/commands/layer.rs @@ -173,7 +173,7 @@ fn new_text(s: &mut Session, p: &Value) -> Result { } let layer_name = str_p(p, "name").map(str::to_string); apply_text_params("layer.newText", &q, &mut doc, None)?; - let mut pos = p.get("position").and_then(|v| v.as_array()).map(|a| [a[0].as_f64().unwrap_or(0.0), a.get(1).and_then(Value::as_f64).unwrap_or(0.0)]); + let mut pos = position_p(p, "layer.newText")?; if let Some([x, y, w, h]) = bx { let (w, h) = (w.abs().max(1.0), h.abs().max(1.0)); doc.box_size = Some([w, h]); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 0fa0fd0f..3a21c1c6 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -542,3 +542,21 @@ fn render_queue_add_accepts_documented_settings_when_checked() { assert!(r.is_ok(), "{r:?}"); assert!(s.execute_checked("renderQueue.add", json!({"bogus": 1})).is_err()); } + +#[test] +fn new_text_rejects_malformed_positions_without_creating_a_layer() { + let mut s = Session::default(); + s.execute("comp.new", json!({"name": "C", "width": 64, "height": 64, "duration": 1})).unwrap(); + for position in [json!([]), json!([10]), json!(["x", 20]), json!([null, 20])] { + let err = s.execute("layer.newText", json!({"text": "Hello", "position": position})).unwrap_err(); + assert!(err.to_string().contains("position: [x, y]"), "{err}"); + assert!(s.active_comp().unwrap().layers.is_empty()); + } + s.execute("layer.newText", json!({"name": "Valid", "text": "Hello", "position": [10, 20]})).unwrap(); + assert_eq!( + s.active_comp().unwrap().layers[0].props.prop("transform/position").unwrap().value, + effectcraft_keyframe::Value::Vec3([10.0, 20.0, 0.0]) + ); + s.execute("layer.newText", json!({"text": "No explicit position"})).unwrap(); + assert_eq!(s.active_comp().unwrap().layers.len(), 2); +}