From d67c4b3059ceee93c134c9132bb2203566b8bd71 Mon Sep 17 00:00:00 2001 From: aiongg Date: Thu, 22 Oct 2026 21:41:50 +0000 Subject: [PATCH] fix(js): an XFA value past the effect cap leaves the field unchanged --- crates/js/src/tests.rs | 15 +++++++++++++++ crates/js/src/xfa.rs | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/js/src/tests.rs b/crates/js/src/tests.rs index 07f04614d..01a436240 100644 --- a/crates/js/src/tests.rs +++ b/crates/js/src/tests.rs @@ -723,6 +723,21 @@ mod xfa_model { assert!(!o.effects.iter().any(|e| matches!(e, XfaEffect::SetPresence { som, .. } | XfaEffect::SetAccess { som, .. } if som.contains("qty")))); } + /// Past the effect cap, a value written to a field with no effect yet is left out of reads as + /// well as the effects; a field written again before the cap still takes its new value. + #[test] + fn a_value_past_the_effect_cap_is_left_out_of_reads_and_effects_alike() { + let o = go( + "price.rawValue = 1; for (var i = 0; i < 20000; i++) xfa.host.beep(); qty.rawValue = 9; price.rawValue = 3; qty.rawValue + ':' + price.rawValue", + "form1[0].page1[0]", + "click", + ); + assert_eq!(o.error, None, "{o:?}"); + assert_eq!(o.effects.len(), MAX_EFFECTS); + assert_eq!(o.result.as_deref(), Some("4:3")); + assert!(!o.effects.iter().any(|e| matches!(e, XfaEffect::SetValue { som, .. } if som.contains("qty")))); + } + #[test] fn urls_and_reset_lists_are_clipped_and_deduplicated() { let o = go( diff --git a/crates/js/src/xfa.rs b/crates/js/src/xfa.rs index 18013e001..8a60e8ba9 100644 --- a/crates/js/src/xfa.rs +++ b/crates/js/src/xfa.rs @@ -459,9 +459,9 @@ impl XHost { self.clipped_values += 1; } // The snapshot's copy and the effect's are charged together, before either is kept: - // past the byte budget the write is left out of both. + // past the byte budget or the effect cap the write is left out of both. let effect = XfaEffect::SetValue { som, value: text.clone() }; - if !self.room(text.len().saturating_add(payload(&effect))) { + if !self.reserve(&effect, text.len().saturating_add(payload(&effect))) { return true; } if let Some(n) = self.nodes.get_mut(i) {