PdfScriptRunner
Runs the JavaScript a PDF carries: its document scripts, the actions of its pages and buttons, and the four scripts a form field runs while it is filled.
Scripts see the objects Acrobat defines and Chrome's PDF engine implements: the document's own members as globals, getField, event, app, util, color, console, and the AF helper library every form tool calls. A script that works in Chrome's viewer is meant to work here.
val state = PdfFormState(doc)
PdfScriptRunner(doc, state, onAlert = { alert -> showDialog(alert.message); 1 }).use { runner ->
runner.runDocumentOpen() // document scripts, then the open action
runner.setFieldValue("price", "12") // keystroke, validate, calculate, format
state.value("total") // what the form's own script worked out
}Nothing here touches the file. Values land in formState, which a viewer draws and the editor saves. One runner belongs to one document.
A runner can be called from any thread. A KiteJS engine belongs to the thread that opened it, so the runner opens its engine on a thread of its own and runs every call there, one at a time and in order. close stops that thread. The callbacks below run on it too. On JavaScript and WebAssembly the engine loads before its first use: call prepare once and wait for it, as KiteDocView does. There, a long script that a suspend event method runs pauses now and then so the page can draw, and the next call waits for it (#489).
Scripts are untrusted input, so policy decides whether they run at all and how long they may take, and anything that reaches outside the document arrives at onRequest for the host to allow or refuse.
Constructors
Types
What a keystroke script decided: whether the change is allowed, and what the field would hold if it is.
Properties
The page the reader is on, which this.pageNum reports to scripts.
How many failures failures no longer holds, because newer ones took their place (#960).
The scripts that failed since the runner opened, newest last: the last MAX_FAILURES of them, each message cut to MAX_FAILURE_MESSAGE characters and with no cause, so a timer that throws a large message every frame cannot fill the heap (#960). droppedFailures counts the older ones.
Where field values live while the reader has the file open.
What the document's scripts are allowed to do.
Functions
Runs only the selection-change event; deferred selection remains outside the live state.
One choice change follows the Acrobat Field event sequence without flattening its values.
The text a field shows, after its format script has had it. The stored value does not change: a formatted total still calculates as a number.
The viewer's keystroke: the value the field should show, or null when a script refused it.
Runs a field's keystroke script for one edit, without committing it (ISO 32000-1 §12.6.3). A viewer calls this for each character the reader types, so a script can refuse it.
Runs a widget's mouse down script, which is how an on-screen button reports a press.
Runs the mouse down script of one widget of the field, such as one button of a radio group.
Reports each timer a script sets or clears, from the script thread (#368).
Runs the timers a script set with app.setInterval or app.setTimeOut that are due, and returns how long to wait before the next one, or null when none is waiting.
Runs one JavaScript action, such as a link's or a button's.
Runs every calculate script, in the order of the form's /CO array (ISO 32000-1 §12.7.2). A form with no order runs them in the order its fields appear.
Runs every document-level script in the order of their names (ISO 32000-1 §7.7.4). A script that fails is recorded and the ones after it still run.
Runs the page's close script, its /AA /C entry.
Runs the page's open script, its /AA /O entry (ISO 32000-1 §12.6.3, Table 195).
Performs one action of a widget's /A chain. A script runs as the field's mouse up event, which is where Acrobat keeps a button's mouse up script, and a form reset is followed by a calculation round, as MuPDF does after one.
Commits a value to a field the way a viewer does when the reader leaves it: the keystroke script sees the whole value, then validate, then the value is stored, then every calculate script runs in the form's own order, then the format scripts decide what is shown (ISO 32000-1 §12.6.3 for the triggers and §12.7.2 for the calculation order).