When the interface thread stays in one part of a frame for 3 s, a
watching thread writes a hang report to the log and to
logs/hang-report-<process id>.txt. The report gives the part of the
frame (input hook, logic, interface, or the renderer after a frame in
which any window had input), a system clipboard call in progress, the
last 8 different command ids, the last 16 frame times, the platform,
window system, desktop and session type, Flatpak, graphics adapter, the
present mode and frame latency the app asks for, the running time and
the number of open documents. It holds no document contents, file paths
or command parameters. The interface thread marks its stages with a few
atomic stores a frame, and the watching thread reads those marks without
waiting on it.
The process keeps the report file locked until the interface answers
again, then removes it. A file nobody holds at a later launch was left
by a session that was closed while it did not answer: the launch writes
the report to the log, moves the file to logs/hang-report.1.txt and,
unless another start-up message is showing, says so in the status bar.
Help › Copy Troubleshooting Info puts the platform facts, the recent
commands and frame times and both sessions' reports on the clipboard for
a bug report. An in-line file dialog, an open menu of the macOS menu bar,
and the time after a frame that minimizes or hides the window or starts
moving or resizing it are not timed.
The menu label and the two status messages have rows in every catalog.
An error a finally block passed on unchanged was reported at the end of
that block, in script.run's report and in the Script Console, because the
block's end raised the error again at a new site. The interpreter now keeps
the site of the exception each finally block runs for, keyed by the stack
slot that holds it, and the block's end throws the exception on from that
site. This holds through nested finally blocks, called functions, resumed
runs and marked host errors. An error the finally block throws is reported
at that throw, and one its return, break or continue discards is not
reported.
Type › Dynamic Text (`type.dynamicText`, also on the Contextual Task Bar
for type on a path) scales the text by one factor so it fills the span
between its start and end brackets, and the layout fits it again after
each edit to the text, the path or a bracket. The first character's
size moves in 0.1 pt steps within 0.1 to 1,296 pt. Turning it off, or
threading the type, keeps the sizes it was drawn at.
- The model saves `dynamicText` only when on.
- SVG, the legacy .ai writer and the .ai editing data write the drawn
sizes through `vectorcraft_text::drawn`; the editing data warns that
the setting is not written.
- Shrink Text to Fit and Dynamic Text step the size the Character panel
shows when a size measures the cap height, x-height or ICF box.
Docs: docs/mcp.md, docs/type-parity.md, docs/target-app-parity.md.
Part of #4134.
vectorcraft_plugins exports FUEL_SLICE and BYTES_COPIED_PER_FUEL (hidden
from the docs), and the bulk memory fuzz cases use them for the passes
around one slice, the lengths around one unit of fuel and the fuel
estimate, in place of the copied 20,000,000 and 64.
The Save PDF dialog's General section gets "Write pages longer than 200 in
at full size in points" (longPagesInPoints in document.exportPdf,
document.export, presets and document.pdfSettings), off by default. When it
is on, a page with a side longer than 14,400 pt is written with its media
box in points and no /UserUnit at every PDF version, and a PDF 1.5 file
stays PDF 1.5. The export's warning for such a page then says it is written
in points. With the option off, and for pages of 14,400 pt or less, the
file is the same as before.
Docs: docs/mcp.md, docs/target-app-parity.md. The new label has a row in
every catalog that lists the dialog's other options.
The status message already ends in an ellipsis and shows its full text
on hover when it is clipped. The Help Bar's hint and the tool name in
the status bar ran past the window edge instead; the Dimension tool's
hint is wider than an 800-point window. Both now end in an ellipsis and
show their full text in a tooltip on hover. Screen readers receive the
full text, and text that fits shows no tooltip.
In a narrow status bar the tool name now ends in an ellipsis before it
takes the status message's room. Before, the tool name could leave the
message almost no width.
The tooltips of the clipped hint, tool name and message wrap to fit
inside the window. egui's tooltips are 500 points wide, which is wider
than an 800-point window at UI Scaling 1.6 or more.
The hint and tool name tests fail without the change. The status
message test covers its existing ellipsis and tooltip.
Check Script read names with Rust's alphabetic and alphanumeric tests, so it
split names at U+2118, U+203F, U+00B7 and the zero width non-joiner and joiner,
and took U+00B2 and U+2E2F into names. It now uses the Unicode 16.0 ID_Start
and ID_Continue rule that vectorcraft-js uses, with `$` and `_`
(https://www.unicode.org/reports/tr31/,
https://tc39.es/ecma262/#sec-names-and-keywords).
A `\uXXXX` escape is part of a name only when it stands for a character the
name may hold where it is: `\u0030abc` no longer becomes `0abc`, and malformed
escapes end the name.
The engine's lexer comparison test now checks that both crates take the same
characters into names, written out and as escapes.
Headless command_list exposes the desktop UI catalogue with ui: true, docs
clarify effect vs command ids, and prompts cover spelling, variables and path tools.
Scripts get the File and Folder classes as built-ins of the script
engine. A script run from a file can test whether files exist, read
their properties, list folders with getFiles (a mask or a function),
and open files to read them with read, readln, readch, seek and tell.
- Reads stay inside the script's folder and, when automation read
roots are set, inside them too. A script given as text reads no
files. Network and device paths, and paths outside the folder by
their names, are refused before anything is looked up. Links and
junctions that lead out are refused, and getFiles leaves them out.
- The encoding comes from the byte order mark, then the encoding the
script set, then UTF-8 when the bytes are valid, then CP1252.
- Limits: 8 MiB a file, 32 MiB a run, 256 files open at once, 2,048
getFiles entries and 65,536 names looked at, and paths of at most
32,767 characters.
- Writing, the file dialogs and execute are not available yet: they
return false or null and set error.
The report's hostCallCounts gains fileCalls and fileExecutes.
Docs: docs/mcp.md, docs/target-app-parity.md.
Under --automation-read-root, ui.inspect returned the paths of documents
still opening, the recent files, library panels' files and the folder
preferences even when they lay outside the read roots. The reply now
leaves them out, checked with file_access::check_read as ui.menu.list
checks recent files and listed scripts:
- opening and ui.recent_files keep only the readable paths, in order.
- A library panel keeps its row without its path; a library loaded from
outside the roots shows as loaded/<file name> in its id and panel id,
in ui.inspect and ui.docking.
- The folder preferences in ui.engine_prefs and in an open Preferences
dialog are left out; an empty folder and the scratch disk choices
Startup and None stay.
The app's own state is not changed. Without roots the replies are as
before.
Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
main lines a moved selection's edges and centre up with ruler guides
(snap_moved_to_rulers, #5746) but not when Shift keeps the move to its line. The
bounds now slide along that line onto a ruler guide the same way
(snap_moved_along_to_rulers), when nothing else lined up and the grabbed point is
not on a guide, within twice the Snap to Point distance along the line.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The web build had no clock for plug-in runs, so its first view deferred
every plug-in live effect until Effect > Refresh Deferred Effects, and a
run's wall-clock limit was not enforced there. The deferrals clock and
the run deadline now read `web_time::Instant`, which is the system's
monotonic clock on the desktop and the page's `performance.now()` in the
web build. The web's first view now shares the same 2,000 ms budget, and
its runs stop at the 5 s, 60 s and 300 s limits as on the desktop.
Docs: docs/plugins.md, docs/mcp.md, docs/target-app-parity.md.
Under --automation-read-root, a control client's ui.menu.list (and
ui.contextMenu.list, which shares the listing) left every File › Open
Recent Files row in, so the client saw the names of recent files it may
not read. file.recentFiles returned their full paths, and
file.openRecentN for such a file answered with a refusal naming the path.
Now the listing leaves out a recent file outside the read roots, as it
already leaves out listed scripts outside them. The other rows keep their
ids, so file.openRecent3 still opens the third file. file.recentFiles
returns only the files inside the roots, in order, and file.openRecentN
for a file outside them ends with "no such recent file", as an empty slot
does. The person's own menus and Home screen are unchanged.
Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
A failure $.evalFile raised for a file it could not run was placed by
matching the uncaught error's message against the last such failure. A
script that caught the failure and threw it again later, or threw a new
error whose message held its text, was reported at the failed file's line
instead of the second throw.
The failure now carries a mark (HostError::Marked) with the exception.
A catch clause drops the mark, a throw raises the value without one, and
a finally block that ends normally throws it on with its mark, nested
finally blocks included. Realm::error_mark gives the mark of the error a
run ended with, and the engine looks up the file, line and column by it.
While an envelope's contents are edited, the editing data keeps its mesh
in the envelope's dictionary. In some users' files that mesh lies away
from the drawn art by a plain move, the contents sitting with the drawn
art, as if the mesh hadn't followed the envelope when it moved. The
envelope then drew its contents elsewhere, failed the drawn-art check
and kept its drawn art. Nothing in the dictionary records the move, and
no envelope saved outside Edit Contents was found displaced.
A mesh or top object saved in Edit Contents (and a warp of type tried
on its saved grid) whose mesh draws the contents as large as the drawn
art, within half a point over width and height together, but further
from it than that, is now tried again after every other way, with one
more of the import's checks, its mesh moved by as far as the drawn
art's box lies from the box of what it draws. The drawn-art check, the
budget and the page comparison decide as before, so an envelope that
opened live before opens the same way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>