Bounded XFA FormCalc and JavaScript
HotPDF evaluates XFA calculate scripts whilst flattening a form, with an always-available bounded FormCalc path and a broader QuickJS path that remains disabled until the application explicitly switches it on
Extended FormCalc
FormCalc expressions support arithmetic, strings, booleans, comparison operators, short-circuit And, Or and Not, plus the lazy If(condition, whenTrue, whenFalse) branch
Sum, Avg, Min, Max and Count accept mixed scalar and SOM node-set arguments using rooted, direct, indexed, wildcard or descendant paths such as $record.rows[*].amount; only the selected branch of If is evaluated, so an unused invalid branch does not reject the calculation
Nested calls can combine numeric, string and node-set results, with deterministic support for At, Choose, Concat, LTrim, RTrim, Str, Stuff, Null, Sign, Exp, Log, Sin, Cos, Tan, Deg2Rad, Rad2Deg, Within and Oneof
User-defined functions, loops, assignment, locale picture clauses and network functions remain outside the native subset and fail closed
InstanceAdd(name, count) and InstanceRemove(name, index) dispatch through OnXFAInstanceAction only after argument and operation-budget validation
Optional JavaScript
Set THotPDF.XFAJavaScriptEnabled to True before ApplyXFAAsAcroForm or FlattenLoadedXFA to run scripts whose contentType picks JavaScript
The runtime supports normal JavaScript control flow and native typed arrays such as Float64Array, but receives no file, process, network, browser or application object; fetch, XMLHttpRequest, WebSocket, require, process and Deno are unavailable
var
Budgets: THPDFXFAFormScriptBudgets;
begin
Budgets := THPDFXFAFormScriptBudgets.Default;
Budgets.MaxElapsedMilliseconds := 100;
Budgets.JavaScriptMemoryBytes := 8 * 1024 * 1024;
PDF.XFAFormScriptBudgets := Budgets;
PDF.XFAJavaScriptEnabled := True;
PDF.OnXFAInstanceAction := HandleXFAInstanceAction;
PDF.ApplyXFAAsAcroForm(XDPBytes, False);
end;
Script context
JavaScript receives a mutable this.rawValue, an event.value and a frozen xfa facade
xfa.get(name, index)reads one collected data valuexfa.values(name)returns a frozen copy of every repeated valuexfa.resolveNode(name)andxfa.resolveNodes(name)expose read-only raw-value viewsxfa.addInstance(name, count)andxfa.removeInstance(name, index)queue validated host callbacks
Budgets and telemetry
THPDFXFAFormScriptBudgets bounds script bytes, FormCalc operations, elapsed time, expression depth, repeated-array items, value bytes, instance operations, JavaScript memory, JavaScript stack use and interrupt checks
The stack budget provides the recursion boundary, whilst the time and interrupt budgets stop non-terminating loops; scripts that cross any boundary fail closed and append a diagnostic to XFAFlattenWarnings
XFAFlattenScriptsEvaluated, XFAFlattenScriptsRejected and XFAFlattenInstanceOperations report the latest flattening pass
Direct runtime integration
The extended HPDFXFAFlatten overload accepts TXFAFormScriptOptions and TXFAFormInstanceAction directly; assign TXFAFormScriptOptions.JavaScriptEvaluator to adapt the static QuickJS binding or another application-owned evaluator whilst retaining the same wrapper and budgets
See TXFAFormScriptOptions, TXFAFormScriptLimits, THPDFXFAFormScriptBudgets and THPDFXFAInstanceAction