Commit Graph
82 Commits
Author SHA1 Message Date
eliets2andeliets2 a2c6e63d0a Fuzz target for the JavaScript engine's script runner (#6304)
Co-authored-by: eliets2 <287273517+eliets2@users.noreply.github.com>
2026-11-05 20:11:15 +01:00
6427357fcb Forms: date fields name months in the date language, not always English (#5303) (#5464)
* Forms: date fields name months in the date language, not always English (#5303)

`AFDate_FormatEx("dd-mmm-yy")` wrote "18-Oct-26" in an Italian interface,
where a localized Acrobat writes "18-ott-26". Form date formats,
`util.printd` and `util.scand` now take their month and weekday names
from the date language (Preferences > Date format > Language, which
follows the interface language until one is picked), and still read
English names typed in. The names are process-wide, so their test runs
in its own binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: dates read back in every date language (#5303)

Trying every date language showed what a field wrote not always reading
back: names holding digits ("10月"), spaces ("tháng 10"), dots ("ม.ค.")
or combining vowel signs (Thai, Hindi, Telugu) fell apart word by word,
and Italian, Spanish, Romanian and Albanian share some short weekday and
month names ("mar"). The language's names are now found whole in the
text first, the longest at each place, and read as their English names;
the format's order of `mmm` and `ddd` settles a shared name. Both
AFDate parsing and util.scand do this, on text up to 1 KB. A test reads
back every language, each name format, and hostile text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: date names no field font can draw are drawn in English (#5303)

With the names in the date language, a Russian dd-mmm-yy field drawn in
Helvetica showed "18-????.-26": no /DR font held "окт." and the WinAnsi
stand-in drew each letter as ?. The same held for Japanese, Chinese,
Greek, Arabic, Thai and others, and for Latin names outside WinAnsi
(Czech "říj"). Before, the names were English and always drew. An
AFDate/AFTime field now formats its value again with English names for
a widget whose fonts can't draw the localized text; a custom Format
script is run again with util.printd writing English names for such a
widget, and its result kept only when it draws whole. A field whose
font holds the names keeps them, and scripts otherwise still print the
date language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: an English weekday before the month keeps the month (#5303)

With Italian dates, "Tue 17 Mar 2026" in a "ddd d mmm yyyy" field read
as no date: the language's names were found in the text, but not
English ones, so "Tue" left the format's weekday unfilled and "Mar",
which Italian shares between Tuesday and March, was taken as the
weekday. Both AFDate parsing and util.scand lost the month, and
Spanish, Romanian and Albanian ("mar") did the same. English names are
now found too and fill their field of the format as localized ones do.
A test reads English and mixed weekdays before the month in those
languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: an English date run is drawn even when it prints the value (#5303)

A Helvetica field storing "18-Oct-26" whose Format script prints it
again as dd-mmm-yy still showed "18-???.-26" in Russian. The English
run printed "18-Oct-26", but it was dropped for equalling the stored
value, which was how a failed run was told apart: a failing script
handed back the value unchanged. The English run now says whether it
ran (`None` when the script failed or the runner can't write English
dates), and what it made is drawn whenever it draws whole. A test
reprints the stored value under Russian, and checks that a failing
script keeps its text and is reported undrawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: a short weekday typed without its dot is the weekday (#5303)

With French dates, "mar 6 janv 2026" in a "ddd d mmm yyyy" field read
as no date through util.scand, and "mar 06/01/2026" in "ddd dd/mm/yyyy"
through AFDate too. French writes Tuesday as "mar.", which a name
search only found with its dot; since English names are found as well,
the English "Mar" (March) was the only name of that length, so the
weekday became a month. Romanian "mar" did the same. A short name
ending in a dot is now also found typed without it, as the same kind of
name, so the format's order of name fields decides between it and an
equal name of the other kind. Both copies of the name search change. A
test reads French and Romanian weekdays typed without their dot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: a shared name is the month when no weekday is typed (#5303)

With Italian dates, "17 mar 2026" in a "ddd d mmm yyyy" field read as
no date, nor did "mar 17, 2026" in "dddd, mmmm d, yyyy". AFDate leaves
weekdays out of what it reads (they are shown, not typed), but the name
search still expected the format's weekday first, so "mar", which
Italian shares between Tuesday and March, filled it and left no month.
Spanish and Albanian "mar" and Albanian "sht" (Saturday, September) did
the same, and the keystroke check refused those dates. Where such a
read finds no date, the names are now read again with no weekday
expected, so the shared name is the month; a typed weekday still comes
first ("mar 17 mar 2026"). util.scand reads its fields in order and
needs the weekday, so it is unchanged. A test types those dates with the
weekday left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: Turkish names typed in capitals are read (#5303)

With Turkish dates, "1 MAYIS 2026" and "1 EKİM 2026" in a d mmmm yyyy
field read as no date through AFDate and util.scand, and "SALI 6 OCAK
2026" through util.scand. Names were compared lower-cased, which turns
I into i, not the dotless ı of "Mayıs" and "Salı", and İ into i with a
combining dot above, which "Ekim" doesn't have. Names and typed text
are now folded alike, the capital I and the dotted and dotless i all as
i and the combining dot dropped, one piece for each char so positions
in the text stay aligned: in both copies of the name search, the AFDate
month reader and util.scand's name matcher. English reads as before. A
test types Turkish names in capitals and English ones as a check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Forms: Greek names typed in capitals are read again (#5303)

Folding names char by char turned a capital Σ into σ, so "ΙΑΝΟΥΆΡΙΟΣ"
no longer matched "Ιανουάριος", whose last letter is the final ς. The
fold now makes ς a σ on both sides, in the forms and JS parsers alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-05 16:12:04 +01:00
SSwansonandseanGSISG 97a9110533 M12: FormCalc prints numbers to at most 15 significant digits (#5819)
`num_text` printed every non-integer with twelve fixed decimals. A value with
six or more digits before the point then shows the binary noise of the double
that holds it: a FormCalc calculate `qty * price` with price 279893.88 gave
`279893.880000000005`, and a Sum() of five such amounts gave
`1466917.350000000093`. Real invoice forms (USACE ENG Form 93, a dynamic XFA
payment estimate) show these in their amount and total fields.

Print at most 15 significant digits (the most a double holds for every value)
and at most 12 decimals, as before for small values, so sums that should be
zero still print 0. Only a fraction loses trailing zeros: past 15 digits before
the point no decimals are left and the integer keeps its zeros.

Co-authored-by: seanGSISG <seanGSISG@users.noreply.github.com>
2026-11-03 00:32:38 -05:00
Eric Kaden 21f6c29d3e M6: form script messages keep their title, icon and buttons, and every one is shown (#4293, #4294) (#4306)
* M6: form script messages keep their title, icon and buttons, and every one is shown (#4293, #4294)

* M6: a form script message waits for a notice the toast already shows

* M6: form script messages past the queue's room are counted and reported

* M6: a sentence break in the merged parity note

* M6: an object that names no parameter is a message's text, as a String object or a caught error

* M6: the count of left-out script messages is said again if another notice replaces it before its time

* M6: a full stop between two sentences of the FormCalc parity note

* chore: re-run CI (a frame-budget timing test missed on a shared runner)
2026-10-28 17:46:11 -04:00
Dylan M. Taylor ef894ae6b8 Fix platform-gated imports for Windows and wasm builds 2026-10-28 00:14:57 +00:00
Dylan M. Taylor a0598816d2 Refactor js for strict Clippy checks 2026-10-27 23:12:51 +00:00
aiongg f022ef0671 style: cargo fmt on moved files 2026-10-27 00:34:32 +00:00
aiongg 8e50dcd0a3 refactor(js): split xfa.rs into xfa/
New modules: model, host, nodes, instances, globals, run.
2026-10-26 22:18:50 +00:00
aiongg 68aa5313c2 refactor(js): split formcalc.rs into formcalc/
New modules: lexer, ast, parser, value, access, eval, dates, words, builtins.
2026-10-26 22:18:50 +00:00
aiongg 1c5873cfb5 refactor(js): split lib.rs into model, host, document, format, globals, run
New modules: model.rs, host.rs, document.rs, format.rs, globals.rs, run.rs. Old crate:: paths keep working through use aliases in lib.rs.
2026-10-26 22:18:50 +00:00
.CooCoo 0db7d57619 Tests: XFA calculation tests no longer fail when the machine is busy (#4535)
Five XFA tests failed at random on a busy machine. The scripts of an
opening or a change share a 3 s wall-clock budget (a click's share 5 s),
each script has 1 s or 3 s, and the engine has 10 s to start; under load
the tests went past one of them, and the scripts they check were skipped
or did not start.

Session::with_xfa_time_scale (and Automation::with_xfa_time_scale)
multiplies each of these limits for a test; the default stays 1. The
script session counts the engine threads it starts on the calling thread
(xfa_session::engines_started).

The hundreds-of-calculations tests run with the limits raised, and the
engine's test now checks that opening starts one engine and a change one
more. A new test sets the factor to 0 and checks that the budget skips
all 210 calculations and says so. Three more tests that failed the same
way under load run with the limits raised.
2026-10-25 10:02:00 -04:00
NetterSilverandClaude Haiku 5.5 538eb1624b Fix FormCalc Round overflowing to infinity for large values (#4508)
Found while testing crates/js/src/formcalc.rs:2114-2119

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-25 10:00:02 -04:00
NetterSilverandClaude Haiku 5.5 4f9b16fa14 Reject '+' as a hex digit in FormCalc url Decode escapes (#4586)
Found while testing crates/js/src/formcalc.rs:2280-2284

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-25 09:59:59 -04:00
aiongg 06959df890 Integration: execMenuItem requests go through the request cap (#3580)
A script looping on app.execMenuItem could queue unlimited requests; they now follow the same count and byte limits as other requests.
2026-10-24 08:15:46 +00:00
aiongg f017ca3b78 Merge PR #3580: M6: form buttons show the side panels (app.execMenuItem)
crates/js/src/lib.rs: module doc app/util list has execMenuItem and scand; install() doc comment from main.
crates/js/src/tests.rs, crates/engine/src/tests.rs: both sides' appended tests kept.
parity/acrobat-features.toml: js notes: execMenuItem wording plus scand wording.
2026-10-24 06:23:47 +00:00
aiongg 5990381c9c Merge PR #3549: M6: util.scand reads dates as another viewer does 2026-10-24 06:22:59 +00:00
aiongg 3f622963f0 Merge PR #4299: Omit minus sign when FormCalc Format() rounds to zero 2026-10-24 06:22:56 +00:00
aiongg c24e90b59c Merge PR #3985: M6: a document script that throws no longer stops the form's other scripts (#3940)
crates/automation/src/tools.rs: js_run description: both sides' wording merged.
2026-10-24 06:22:15 +00:00
a047c6ba09 chore: resolve SonarCloud maintainability issues (#4356)
* chore: resolve SonarCloud maintainability issues

* fix(packaging): use verify_sha256 helper function

* style: cargo fmt

* fix: restore wildcard imports and fix method-reference type errors

Revert the glob-import expansions (they missed SomIndices and left unused
imports), revert char::is_ascii_digit where the iterator yields char by
value, and pass the content slice to prune_doomed_xobjects as &[Vec<u8>].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep XObject decodability check without binding content in interp

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:18 -04:00
NetterSilverandClaude Haiku 5.5 afcc54fddc Omit minus sign when FormCalc Format() rounds to zero
Found while testing crates/js/src/formcalc.rs:2328-2330 ("format" number-picture branch, `if num < 0.0 { text = format!("-{text}") }`)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 20:53:02 +02:00
Eric Kaden 44b7e0a40f Merge remote-tracking branch 'upstream/main' into fix/exec-menu-attachments
# Conflicts:
#	crates/js/src/lib.rs
#	crates/js/src/tests.rs
#	parity/acrobat-features.toml
2026-10-23 10:43:34 -04:00
Eric Kaden c141c94c06 Merge remote-tracking branch 'upstream/main' into fix/util-scand
# Conflicts:
#	crates/js/src/lib.rs
#	crates/js/src/tests.rs
#	parity/acrobat-features.toml
2026-10-23 10:27:32 -04:00
mtlcl410andClaude Opus 5.5 994ce63099 M6: a document script's error is told apart by where it came from, not its wording (#3940)
Review follow-up on #3985: JsOutput deduplicated document-script errors by
their text (document script N: ...), so a field script that threw the
same words was dropped by append, and a document script's error was
dropped by absorb when a field script had already reported that text.
JsOutput now records which errors came from document scripts
(doc_errors) and deduplicates only those; pdfcraft_js::is_doc_error,
which guessed from the wording, is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0175FWj4xFhMhSH3UpMU8DSC
2026-10-23 22:25:57 +08:00
mtlcl410andClaude Opus 5.5 a7afaacbb9 M6: merged script output reports a document script's error once too (#3940)
Review on #3985 (benandez): JsOutput::absorb reported a failing document script once, but append
added every error again, so merging two outputs repeated it. pdfcraft_js now says whether an
error is a document script's (is_doc_error, next to the doc_error format), and append skips one
already reported; each field script error is still its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:25:57 +08:00
mtlcl410andClaude Opus 5.5 a8beb90ccf M6: a document script refused before running is skipped and reported too (#3940)
CodeRabbit on #3985: a document script over the size or nesting limit made `run`
return before any script ran, so the field script failed as before. It is now
skipped (never evaluated, as the limits require), reported in its place in
doc_errors, and the other scripts and the field script still run. The field
script's own limits still refuse it outright.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:25:57 +08:00
mtlcl410andClaude Opus 5.5 77db1bd27f M6: parity note for document scripts that throw (#3940)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:25:57 +08:00
mtlcl410andClaude Opus 5.5 e76ebb9ea3 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>
2026-10-23 22:25:57 +08:00
Eric Kaden 8f292c66ae M6: scripts see xfa_version, and xfa_installed in XFA forms (#4142) 2026-10-23 10:19:09 -04:00
NetterSilverandClaude Haiku 5.5 3ee6a83e09 Accept long unit names in FormCalc UnitValue (#4116)
Found while testing crates/js/src/formcalc.rs:2526-2532 (UnitValue per_in table; UnitType at :2510-2516)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-23 10:18:55 -04:00
NetterSilverandClaude Haiku 5.5 c32c2ce09f Fix FormCalc Str() printing small negative numbers as "-0" (#4108)
Found while testing crates/js/src/formcalc.rs:716-720 (fixed), used by Str at :2216

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-23 10:18:45 -04:00
Eric Kaden 8f82bfccec Merge remote-tracking branch 'upstream/main' into fix/exec-menu-attachments
# Conflicts:
#	crates/engine/src/tests.rs
2026-10-22 23:09:22 -04:00
aiongg d67c4b3059 fix(js): an XFA value past the effect cap leaves the field unchanged 2026-10-22 21:41:50 +00:00
aiongg e541151389 fix(js): XFA presence and access change the snapshot only when their effect is kept 2026-10-22 21:41:01 +00:00
aiongg fd2e13f332 M8: XFA instance changes reserve their effect before changing the snapshot 2026-10-22 21:35:52 +00:00
aiongg 2ece498ffc fix(js): charge both copies of a written XFA value before keeping either
set_value charged the snapshot's copy, changed the field, then charged the
effect's copy in push. When only the first fit, the effect was dropped while
later reads in the script saw the new value. Both copies are charged at once
before the field changes.
2026-10-22 20:21:21 +00:00
Eric Kaden 6c0fd0f353 Merge remote-tracking branch 'upstream/main' into fix/util-scand
# Conflicts:
#	crates/js/src/lib.rs
2026-10-22 13:23:32 -04:00
aiongg 72fd2a1b24 fix(js): bound the text an XFA script's effects and values hold
The XFA script host capped the number of effects but not their size: URLs,
focus targets and resetData lists were kept whole, a resetData list kept
every repeated name, and values written to fields were each cut but not
counted together. A loop repeating one long script-built string kept a copy
per effect or field. URLs, focus targets and reset names are cut to a
message's length, reset lists name each field once, and every effect,
console line and value written charges a byte budget for the run; past it
they are left out and noted. FormCalc charges an assignment to many fields
once per field copied.
2026-10-22 17:22:50 +00:00
aiongg a5cfc3eec4 fix(js): cap a form script's alerts, console lines and requests
The AcroForm script host kept every alert, console line and request a
script made, each as long as the script made it. A loop printing a long
script-built string held a copy per iteration. The host applies the XFA
host's limits: message and console counts, the effect count for requests,
each message, URL and field name cut to a line, and a byte budget across
all of them, with a closing console line saying how many were left out.
2026-10-22 17:22:50 +00:00
aiongg 2e9b247f3f fix(js): read printd literals in linear time
util.printd measured the run of identical characters at every position of
the format, literals included, but copied a literal one character at a time.
A format with a long stretch of one literal character rescanned the rest of
that stretch at every step: quadratic work from one script-built string.
Only the date letters are read as runs now.
2026-10-22 17:22:50 +00:00
aiongg a525cf1d42 fix(js): refuse code compiled from strings that skipped the script checks
eval and the Function constructors compiled code built at run time, which never
passed the size and nesting checks a script passes before it runs, so a short
form script could hand boa's recursive parser a deeply nested string and
overflow the stack. Form scripts now refuse to compile code from strings. XFA
scripts, which the runner itself starts through eval, hold such code to the
same checks as the script.
2026-10-22 13:18:26 -04:00
Eric Kaden ae69aea627 M6: doc comments on every Panel variant 2026-10-22 09:22:27 -04:00
Eric Kaden 4665685446 Merge remote-tracking branch 'upstream/main' into fix/exec-menu-attachments
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/js/src/tests.rs
#	crates/ui-egui/tests/forms.rs
2026-10-22 03:19:20 -04:00
Eric Kaden 82115ed65c Merge remote-tracking branch 'upstream/main' into fix/util-scand
# Conflicts:
#	crates/js/src/tests.rs
2026-10-22 03:15:57 -04:00
aiongg dcf2802f96 Merge r2 track t15: mixed: accessibility-tags, dialogs-prefs, javascript, organize-pages
# Conflicts:
#	crates/edit/src/tests.rs
#	crates/engine/src/tests.rs
2026-10-22 02:23:22 +00:00
aiongg a0a9e3370e Merge PR #3408: M12: an XFA script that fails partway keeps what it changed before the error
crates/engine/src/tests.rs: union of #2624's tests and #3408's test.
parity/acrobat-features.toml: form.xfa evidence lists unioned, notes take both sides' insertions.
2026-10-22 01:47:22 +00:00
aiongg ae9cd9f623 Merge PR #3004: Zero-pad required integer digits in FormCalc Format() 2026-10-22 01:45:13 +00:00
aiongg c83be3002a Merge PR #3718: Return empty WordNum result when cents rounding carries to 1e12 2026-10-22 01:45:12 +00:00
aiongg 6e2a449bf7 Merge PR #3318: M6: Optimize AcroForm JavaScript snapshots and diffs
parity/acrobat-features.toml: form calculation order entry keeps main's commands, tools and notes; evidence is the union of both sides.
2026-10-22 01:44:59 +00:00
aiongg 9cb8f52294 Merge PR #3782: M6: XFA formattedValue shows a date in the field's display picture 2026-10-22 01:44:53 +00:00
aiongg be1b2bb882 Merge PR #2963: Keep seconds in FormCalc Time2Num/IsoTime2Num for ISO 8601 times 2026-10-22 01:44:49 +00:00