From a7249ad1a486b35d751dd52eab21a068a96733c3 Mon Sep 17 00:00:00 2001 From: Nigel Ihza Firdausy <106657905+Ni-zav@users.noreply.github.com> Date: Sun, 11 Oct 2026 21:19:59 +0700 Subject: [PATCH] fix(script): keep After Effects Undo command ID 16 stable (#812) --- crates/script/src/prelude.js | 7 ++++++- crates/script/src/tests.rs | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/script/src/prelude.js b/crates/script/src/prelude.js index f50a968c..a8b34170 100644 --- a/crates/script/src/prelude.js +++ b/crates/script/src/prelude.js @@ -1798,8 +1798,13 @@ var app = { beginSuppressDialogs: function () {}, endSuppressDialogs: function () {}, purge: function () { __call("edit.purge", { what: "all" }); }, - findMenuCommandId: function (name) { return __get("menuCommandId", { name: String(name) }); }, + findMenuCommandId: function (name) { + // Well-known After Effects ids must not shift when EffectCraft registers a command. + if (String(name) === "Undo") return 16; + return __get("menuCommandId", { name: String(name) }); + }, executeCommand: function (id) { + if (id === 16) return __call("edit.undo", {}); var cmd = typeof id === "number" ? __get("commandAt", { index: id }) : String(id); if (!cmd) throw __err("Unknown command id " + id); return __call(cmd, {}); diff --git a/crates/script/src/tests.rs b/crates/script/src/tests.rs index b50a7bfb..5df09e8a 100644 --- a/crates/script/src/tests.rs +++ b/crates/script/src/tests.rs @@ -730,3 +730,20 @@ fn import_options_sequence_picks_one_still_or_the_run() { assert_eq!(kind_of(&s, "shot_[0001-0003].png"), FootageKind::Sequence); let _ = std::fs::remove_dir_all(&dir); } + +#[test] +fn script_undo_uses_stable_after_effects_command_id() { + let mut s = session(); + let lookup = ok(&mut s, "app.findMenuCommandId('Undo')"); + assert_eq!(lookup.result, json!(16)); + // ID 16 used to index an unrelated command as the registry grew. It must + // undo the preceding layer creation rather than dispatching by position. + let r = ok( + &mut s, + "var c = app.project.items.addComp('Undo ID', 100, 100, 1, 1, 24); c.layers.addNull(); app.executeCommand(16); c.numLayers", + ); + assert_eq!(r.result, json!(0)); + assert_eq!(s.project.comp(ItemId(1)).unwrap().layers.len(), 0); + // Lookup of other command names still uses the existing registry. + assert!(ok(&mut s, "app.findMenuCommandId('New Project')").result.as_u64().unwrap_or(0) > 0); +}