Bounded XFA FormCalc and JavaScript

HotPDF evaluates XFA calculate scripts while flattening a form, with an always-available bounded FormCalc path and a broader QuickJS path that remains disabled until the application explicitly enables it

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 selects 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

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, while 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 while retaining the same wrapper and budgets

See TXFAFormScriptOptions, TXFAFormScriptLimits, THPDFXFAFormScriptBudgets, and THPDFXFAInstanceAction