mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-29 12:38:58 -06:00
M6: a document script that throws no longer stops the form's other scripts (#3940)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
75207dc8ed
commit
e76ebb9ea3
@@ -31,6 +31,13 @@ impl JsOutput {
|
||||
self.console.extend(o.console.iter().cloned());
|
||||
self.requests.extend(o.requests.iter().cloned());
|
||||
self.errors.extend(o.error.iter().cloned());
|
||||
// The document scripts run before every field script, so a failing one would repeat
|
||||
// once per calculation; it is reported once.
|
||||
for e in &o.doc_errors {
|
||||
if !self.errors.contains(e) {
|
||||
self.errors.push(e.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn append(&mut self, other: JsOutput) {
|
||||
|
||||
@@ -4015,6 +4015,11 @@ fn recognize_text_reads_a_picture_on_a_page_that_has_text() {
|
||||
/// A form whose scripts are custom JavaScript: total = price × qty (calculate, through a
|
||||
/// document-level function), shown with a custom format; qty is validated; a button script.
|
||||
fn scripted_form() -> Vec<u8> {
|
||||
scripted_form_with("function times\\(a, b\\) { console.println('times'); return a * b; }")
|
||||
}
|
||||
|
||||
/// [`scripted_form`] with `helpers` (PDF string syntax) as its document-level script.
|
||||
fn scripted_form_with(helpers: &str) -> Vec<u8> {
|
||||
let text = |name: &str, y: u32, aa: &str| {
|
||||
format!("<< /Type /Annot /Subtype /Widget /FT /Tx /T ({name}) /Rect [20 {y} 180 {}] /P 3 0 R /F 4 {aa} >>", y + 20)
|
||||
};
|
||||
@@ -4028,7 +4033,7 @@ fn scripted_form() -> Vec<u8> {
|
||||
"<< /Type /Annot /Subtype /Widget /FT /Btn /Ff 65536 /T (go) /Rect [20 150 80 170] /P 3 0 R /F 4 >>".to_string(),
|
||||
"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>".to_string(),
|
||||
"<< >>".to_string(),
|
||||
"<< /S /JavaScript /JS (function times\\(a, b\\) { console.println('times'); return a * b; }) >>".to_string(),
|
||||
format!("<< /S /JavaScript /JS ({helpers}) >>"),
|
||||
];
|
||||
let mut out = b"%PDF-1.7\n".to_vec();
|
||||
let mut offsets = Vec::new();
|
||||
@@ -4090,6 +4095,27 @@ fn scripts_in_an_xfa_form_see_the_xfa_plugin_installed() {
|
||||
assert_eq!((o.error, o.result.as_deref()), (None, Some("undefined number 3.5")));
|
||||
}
|
||||
|
||||
/// #3940: a document-level script that defines the helper and then calls a method PdfCraft lacks
|
||||
/// (an Acrobat form copying a button icon at open) left every calculated field blank. The
|
||||
/// helper stays defined, the form calculates, and the error is reported once.
|
||||
#[test]
|
||||
fn a_document_script_that_throws_still_lets_the_form_calculate() {
|
||||
let helpers =
|
||||
"function times\\(a, b\\) { return a * b; } this.getField\\('go'\\).buttonSetIcon\\(this.getField\\('go'\\).buttonGetIcon\\(\\)\\);";
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
let id = s.open("order.pdf", None, Arc::new(scripted_form_with(helpers)), None).unwrap();
|
||||
let _ = s.take_js_output(id);
|
||||
s.apply(id, Edit::SetFieldValue { name: "qty".into(), value: FieldValue::Text("4".into()) }).unwrap();
|
||||
let total = s.get(id).unwrap().form.iter().find(|f| f.name == "total").unwrap().value.clone();
|
||||
assert_eq!(total, ["10"], "calculated through the helper the failing script defined");
|
||||
let out = s.take_js_output(id);
|
||||
assert_eq!(out.errors.len(), 1, "reported once, not once per script: {out:?}");
|
||||
assert!(out.errors[0].starts_with("document script 1: TypeError"), "{out:?}");
|
||||
// The console runs too, and says which document script failed.
|
||||
let o = s.run_javascript(id, "times(2, 3)", None).unwrap();
|
||||
assert_eq!((o.error, o.result.as_deref(), o.doc_errors.len()), (None, Some("6"), 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edit_history_does_not_replay_field_script_side_effects() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
|
||||
Reference in New Issue
Block a user