diff --git a/crates/engine/src/js.rs b/crates/engine/src/js.rs index 82ee90c5d..73be05660 100644 --- a/crates/engine/src/js.rs +++ b/crates/engine/src/js.rs @@ -30,10 +30,13 @@ impl JsOutput { self.alerts.extend(o.alerts.iter().cloned()); self.console.extend(o.console.iter().cloned()); // A field's own scripts (keystroke, format, validate, calculate) run unasked: only a - // button's may show or hide a side panel. + // button's may show or hide a side panel, or open Save As. for r in &o.requests { match r { Request::ShowPanel(_) => self.console.push("A field script asked to show a side panel; only a button may show a side panel".into()), + Request::SaveAs => { + self.console.push("A field script asked to save the document as a new file; only a button may open Save As".into()) + } r => self.requests.push(r.clone()), } } diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 72854e37a..4c19b8011 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -6133,3 +6133,26 @@ fn an_xfa_button_may_show_a_side_panel_and_other_events_may_not() { assert!(out.requests.is_empty(), "only a click shows a panel: {out:?}"); assert!(out.console.iter().any(|c| c.contains("show a side panel")), "{:?}", out.console); } + +#[test] +fn a_fields_own_script_may_not_save_as_or_show_a_panel() { + let mut s = Session::new().with_clock(|| 1_700_000_000); + let id = s.open("order.pdf", None, Arc::new(scripted_form()), None).unwrap(); + s.apply( + id, + Edit::SetFieldScript { + name: "qty".into(), + event: "validate".into(), + script: Some("app.execMenuItem('SaveAs'); app.execMenuItem('ShowHideFileAttachment');".into()), + }, + ) + .unwrap(); + s.take_js_output(id); + s.apply(id, Edit::SetFieldValue { name: "qty".into(), value: FieldValue::Text("4".into()) }).unwrap(); + let out = s.take_js_output(id); + assert!(out.requests.is_empty(), "a validate script runs unasked: {out:?}"); + assert_eq!(out.console.iter().filter(|c| c.contains("only a button may")).count(), 2, "{:?}", out.console); + // A button's script may. + let o = s.run_javascript(id, "app.execMenuItem('SaveAs');", Some("go")).unwrap(); + assert_eq!(o.requests, [js::Request::SaveAs]); +}