mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
M6: calculations read their notation only from a comment, and a regex after a condition as a regex (#3993)
* M6: calculations read their notation only from a comment, and a regex after a condition as a regex Two findings from CodeRabbit's review of #3550, both reproduced first: - parse_calculate and calculation_sites found BVCALC and EVCALC anywhere in the script, so `var s = "BVCALC a EVCALC";` read as the notation `a`: renaming `a` rewrote the string, and the form calculated `a` instead of running the script. The lexer now keeps the text of each comment, and the notation is read from the first comment that holds BVCALC and the EVCALC after it (notation_range), by both the Calculate tab and a rename. A line comment counts, and a comment that never ends runs to the end of the script, as before. - A `/` after any `)` divided, so after the condition of `if`, `while`, `for` or `with` a regular expression was read as code: renaming `a` rewrote `if (flag) /getField("a")/.test(x)`, and in `if (flag) /"/.test(x)` the quote started a string that hid the script's real getField calls. The lexer now notes which `(` opened such a condition (not a method of that name, `o.if(x)`), and a `/` after its `)` starts a regular expression. af::tests::notation_is_read_only_from_a_comment, af::tests::a_regex_after_a_condition_is_not_read_as_code and tests::a_script_that_spells_the_markers_in_a_string_runs_as_a_script fail without the fix. Parity, ROADMAP.md and docs/roadmap.md updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BfMGHQNgdq5yf5tKZHGR3z * M6: form.props-calculate notes that a regex right after a brace is still read as code From CodeRabbit's review of this PR. The lexer still divides after `}`, which ends a block as often as an object literal, so in `if (x) { } /"/.test(s); event.value = getField("a").value;` the quote starts a string and the getField is hidden from a rename and from the calculation order. Checked with a scratch test before writing it down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BfMGHQNgdq5yf5tKZHGR3z * M6: a line comment ends at any line terminator, so code after `\r` is still read From CodeRabbit's review of this PR. A `//` comment ran to the next `\n`, so with `\r` line endings it hid the rest of the script: a rename missed the getField calls after it (since #3550), and a string after it that spells BVCALC ... EVCALC read as the notation. A `/` taken for the start of a regular expression likewise looked past `\r` for its end, and could swallow the next line's code. Both now stop at any of JavaScript's line terminators (`\n`, `\r`, U+2028, U+2029; line_ends_at), and U+2028 and U+2029 between tokens are skipped rather than read as the start of a word. af::tests::a_line_comment_ends_at_any_line_terminator fails without each of the three changes: with `\r`, the string read as notation `a`; with the comment fixed but not the regex scan, `i++ / 2;\r` swallowed the getField after it; without skipping U+2028, the getField after it was not a call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BfMGHQNgdq5yf5tKZHGR3z * M6: a word, number or regex's flags end at U+2028 and U+2029 From CodeRabbit's review of this PR. The scans for an identifier, a number and a regular expression's flags took every byte past ASCII as part of a word, U+2028 and U+2029 included, so in `x\u{2028}getField("a")` the getField was part of one word and not a call: a rename missed it, and the calculation order didn't read it. `word` now takes a position and is false where line_ends_at is true, so the three scans share one rule. The arm that skips U+2028 and U+2029 between tokens stays: without it, the punctuation arm would step one byte into the character. af::tests::a_token_ends_at_a_line_separator fails without the fix, for a word, a number and a regex's flags alike; it and a_line_comment_ends_at_any_line_terminator fail without the skipping arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BfMGHQNgdq5yf5tKZHGR3z * M6: the `while` that ends a `do` loop counts as a condition, said and tested A `/` after the `)` of a do-while starts the next statement, so it starts a regular expression there too. The comment on BEFORE_CONDITION says so, and a_regex_after_a_condition_is_not_read_as_code covers it (from review). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BfMGHQNgdq5yf5tKZHGR3z --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7169160df9
commit
ba01244987
@@ -207,6 +207,7 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md
|
||||
|
||||
- **2026-10-17 (M8, gap 6, #2662):** A filled cover over a long line counts when it hides half of any one word, not only 40% of the line's words or box, so a black box over one number in a long line — or an unapplied redaction mark over it — no longer audits clean while the number is still extractable; a sliver under half of every word it touches and under 40% of the line is still not flagged
|
||||
- **2026-10-13 (M10, #1757):** Office export keeps each dotted-leader contents entry in one paragraph, with its page number, instead of inferring table cells from its separate text objects.
|
||||
- **2026-10-22 (M6, calculation scripts):** The Calculate tab and a rename read simplified field notation only from a comment, where Acrobat writes it: a string that spells `BVCALC … EVCALC` is no longer taken for the notation, or rewritten by a rename. A `/` after the condition of `if`, `while`, `for` or `with` starts a regular expression, so a rename no longer rewrites a name inside one, and a quote inside one no longer hides the `getField` calls after it. Both found in review of #3550. A `//` comment ends at `\r`, U+2028 or U+2029 as well as `\n`, so in a script with `\r` line endings the code after one is no longer hidden from a rename, or taken for the notation. Estimates unchanged.
|
||||
- **2026-10-20 (M6, calculation order page):** Prepare a form ▸ Calculation order, a page of its own, lists the calculated fields in the order they calculate with their formulas and values, moved with Up/Down arrows (as Acrobat's Set Field Calculation Order), Alt+↑/↓ or by dragging. A card says what is wrong with the order and holds Fix order; a loop has a card of its own that opens one of its formulas. On the page, each calculated field shows its step, and arrows show what the field in focus reads and what reads it. Estimates unchanged.
|
||||
- **2026-10-20 (M6, calculation order):** The order a form's fields calculate in (`/CO`) is read, checked, fixed and set headlessly with `form_calculation_order`: it says which fields read one calculated later (they show stale values), which read each other in a loop, and which the PDF's order leaves out; Fix order moves only what must move, in one undo step, and the form recalculates. Editing a formula no longer moves its field to the end of the order, and a field the order lists twice calculates once. Estimates unchanged.
|
||||
- **2026-10-20 (M2, #3574):** Forms without Resources use page Properties for ActualText and layer visibility. Synthetic tests cover boundaries, nested/shared forms, and save/reopen. Estimates unchanged.
|
||||
|
||||
Reference in New Issue
Block a user