Commit Graph
1626 Commits
Author SHA1 Message Date
dotCooCoo 5bd1bbf536 Scripts: File and Folder exists checks the kind, encode keeps slashes, every call is counted
- `File.encode` and `Folder.encode` leave `/` unescaped, as the File
  object reference lists it among the characters kept
  (https://extendscript.docsforadobe.dev/file-system-access/file-object/).
- `exists` is true for a `File` only when the path names something
  other than a folder, and for a `Folder` only when it names a folder.
- Fields of the records the app returns are read as own properties, so
  a property a script puts on `Object.prototype` does not turn a
  successful `open` into a failure.
- `File.encode`, `File.decode`, `File.isEncodingAvailable` and the
  `Folder` locations count as file calls and charge the host-call limit.
- On the web the locations are `null` and `File.tempName` names a file
  at the root, without asking the platform for a temporary folder.
2026-11-11 14:46:43 -08:00
BFlat dd6b00c228 Merge pull request #6653 from dotCooCoo/fix/script-throw-site-through-finally
Scripts: an uncaught error that passes through a finally block is reported where it was thrown
2026-11-12 02:53:22 +07:00
BFlat f9ff1caf54 Merge pull request #6648 from dotCooCoo/feat/dynamic-text-on-path
Type: Dynamic Text sizes type on a path to fill its brackets
2026-11-12 02:45:39 +07:00
BFlat 541f8beae7 Merge pull request #6643 from dotCooCoo/feat/pdf-large-pages-in-points
PDF: an option writes pages longer than 200 in at full size in points
2026-11-12 02:05:54 +07:00
dotCooCoo 1f835d94c4 Merge main into fix/script-throw-site-through-finally 2026-11-11 10:44:55 -08:00
dotCooCoo 8d094fc811 Scripts: an uncaught error that passes through a finally block is reported where it was thrown
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.
2026-11-11 10:44:16 -08:00
BFlat 6a4ef12091 Merge pull request #6603 from Messhias/feat/g5-brush-lib-energy-beams
G5: built-in Energy Beams brush library
2026-11-12 01:43:54 +07:00
dotCooCoo 2606b70604 Type: Dynamic Text sizes type on a path to fill its brackets
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.
2026-11-11 10:42:49 -08:00
BFlat 1e76791ae1 Merge pull request #6615 from dotCooCoo/feat/script-file-folder
Scripts: File and Folder read files in the script's own folder
2026-11-12 01:35:45 +07:00
BFlat f83d916d8a Merge pull request #6631 from Hassan1305/docs-6340-rotation-direction
Commands: every angle and rotation param says which way it turns (#6340)
2026-11-12 01:32:17 +07:00
BFlat 210e9ad7d0 Merge pull request #6632 from dotCooCoo/feat/ruler-guides-as-objects
Guides: ruler guides are document objects on their layers
2026-11-12 01:32:07 +07:00
dotCooCoo 3074560b07 PDF: an option writes pages longer than 200 in at full size in points
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.
2026-11-11 10:17:24 -08:00
Fabio William Conceição 72c7cb5a73 G5: built-in Energy Beams brush library
Six brush libraries; MCP docs list Energy Beams with the other generated brush libraries.
2026-11-11 18:07:54 +00:00
dotCooCoo 5ac7d97d85 Guides: ruler guides are document objects on their layers
Ruler guides were a list kept beside the layers. Each guide is now an
object of its layer or sublayer, always directly in it and above the
layer's art. These behave as on main:

- Guides draw on screen only. Exports (SVG, PDF, PNG, PSD), Fit All,
  Select All, the art bounds, clicks and marquees, and a layer's
  Pathfinder and Transform effects leave them out. The Layers panel
  lists them as guide rows of their layer, the highest guide.list
  index first.
- Deleting a layer deletes its guides, and merging layers keeps their
  guides in the merged layer.
- The guide commands number guides as guide.list does, in the order
  they were made.

New: each guide takes an id from the document's object ids. An object
command given a guide's id fails with an error, and node.move cannot
put a guide into a group or out of its layers. A guide made while an
opacity mask, a symbol or a pattern is edited moves to the top
visible, unlocked layer when editing ends.

File format: native files still save the guides in the document's
guides list, in every file version, so older builds read them. Each
entry may now also carry the guide's id, name, locked and hidden
flags; older builds ignore those fields. Opening a file puts each
saved guide on its layer (on the top visible, unlocked layer when the
file names none or a layer it does not have), and each saved guide
counts against the object limit for opening a file. A ruler guide node
that a file holds below a layer's art moves up to the layer's guides,
and one anywhere else (in a group or another object, beside the
layers, or in a symbol) is removed. Ruler guides read from an .ai file
become guide objects on the layer they were on, numbered in the order
the file lists them.
2026-11-11 09:52:28 -08:00
Fabio William Conceição f07c2f7e9c G5: built-in Skill Icons symbol library
Five symbol libraries; MCP docs list Skill Icons with the other generated symbol libraries.
2026-11-11 17:08:39 +00:00
BFlat 45246e9c9d Merge pull request #6551 from Messhias/fix/mcp-gaps-command-list
MCP: list UI_COMMANDS in command_list and close catalogue gaps (#6460)
2026-11-11 23:51:59 +07:00
HassanKhan b3860bf7d0 Commands: every angle and rotation param says which way it turns (#6340)
The params docs now state the direction (and the zero) of each angle or
rotation a command takes; behaviour is unchanged. Shape creation, text.create,
the grids, add-on shapes, saved views, Liquify, Puppet Warp pins, Mirror and
Radial Repeat and Vector Halftone turn clockwise; text character rotation,
gradients, the eraser tip and print screen angles turn counter-clockwise.

view.saved.new's rotation note changes its schema, so the API level goes to 3.

A test walks every command's params doc and fails when a param named like an
angle or rotation doesn't say clockwise or counter-clockwise.
2026-11-11 21:40:27 +05:00
BFlat b6b23703b0 Merge pull request #6608 from dotCooCoo/fix/inspect-pending-read-root
MCP: ui.inspect leaves out paths outside the read roots
2026-11-11 23:25:21 +07:00
Fabio William Conceição 3f26409d4a MCP: keep UI_COMMANDS mirror in sync via xtask
Add `cargo xtask ui-commands` (and `--check` in ci) so the headless
catalogue cannot drift from desktop UI_COMMANDS, and fix params-doc
escaping that printed literal backslashes.
2026-11-11 15:56:33 +00:00
Fabio William Conceição 13098fa9f4 MCP: list UI_COMMANDS in command_list and close catalogue gaps (#6460)
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.
2026-11-11 15:48:05 +00:00
dotCooCoo ba05554c64 Merge main into feat/script-file-folder 2026-11-11 07:47:42 -08:00
dotCooCoo b7a6196994 Scripts: File and Folder read files in the script's own folder
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.
2026-11-11 07:46:33 -08:00
dotCooCoo 774f7568da MCP: ui.inspect hides every loaded library path outside the read roots
Under --automation-read-root, ui.inspect and ui.docking hid a library's
path only when its panel was in ui.library_panels. A library used as the
Color Guide's limit, or named by a closed panel's place in
ui.docking_hidden, a workspace layout or the docking layout, still showed
its full loaded/<path> id.

The ids to hide now come from every place the UI state refers to a
library: the library panels, the Color Guide's limit, and the panel ids in
the docking layout, closed panels, icon and collapsed lists and workspace
layouts. Typed text such as a command palette query is not read as an id.

Two hidden libraries with the same file name no longer share one id, which
dropped one of them from an object keyed by panel id. They show as
loaded/<file name>, loaded/<file name> (2) and so on, in the order of
their full ids, and a library has the same id in ui.inspect and
ui.docking.

Docs: docs/mcp.md.
2026-11-11 07:40:36 -08:00
BFlat 9fc43f2a35 Merge pull request #6598 from dotCooCoo/fix/pasted-svg-filter-brush-names
Effects: a pasted SVG filter avoids brush effect names and is refused with no free name
2026-11-11 22:10:15 +07:00
dotCooCoo 5d7e2fa8e1 MCP: ui.inspect leaves out paths outside the read roots
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.
2026-11-11 06:13:33 -08:00
dotCooCoo e0e361a834 Effects: a pasted SVG filter avoids brush effect names and is refused with no free name
Follows #6592. Paste now also skips the names that effects in the
document's brush art use when it picks a free name for a pasted SVG
filter. When no free name keeps the filter within the 64 KB limit (a
one-letter name at the limit with every free letter and digit taken),
the paste is refused instead of keeping the name of the document's
filter. Clipboard::import_into and import_text_styles return a Result,
and their callers pass the error on before the document changes.
2026-11-11 06:08:58 -08:00
dotCooCoo 48e342f03b Merge main into feat/script-dollar-object 2026-11-11 05:55:39 -08:00
dotCooCoo f77fe0423f Merge main into fix/script-console-report-text 2026-11-11 04:58:29 -08:00
dotCooCoo ccf153dccc Merge main into feat/script-dollar-object 2026-11-11 04:52:37 -08:00
BFlat a2e34903e9 Merge pull request #6577 from dotCooCoo/fix/script-rethrown-error-place
Scripts: an error $.evalFile could not run, caught and thrown again, is reported where it was thrown again
2026-11-11 19:44:23 +07:00
BFlat 58c37a28e9 Merge pull request #6580 from dotCooCoo/fix/menu-list-recent-read-root
MCP: ui.menu.list leaves out recent files outside the read roots
2026-11-11 19:27:56 +07:00
BFlat dab8b9a494 Merge pull request #6584 from dotCooCoo/fix/web-plugin-budget-clock
Plug-ins: the web build times the first-view budget and each run's limit
2026-11-11 19:14:55 +07:00
BFlat e8a570cb0e Merge pull request #6578 from dotCooCoo/fix/print-bitmap-side-limit
Print: Print as Bitmap prints all of a page longer than 32,768 pixels
2026-11-11 19:05:50 +07:00
dotCooCoo c8475771b9 Merge main into fix/script-rethrown-error-place 2026-11-11 03:59:08 -08:00
dotCooCoo d50ea29772 Merge main into feat/script-dollar-object 2026-11-11 03:58:05 -08:00
dotCooCoo 2b88f31a7d Merge main into fix/script-console-report-text 2026-11-11 03:56:06 -08:00
BFlat c443a25016 Merge pull request #6569 from dotCooCoo/feat/script-strict-on
Scripts: #strict on runs the script with strict write checks instead of refusing it
2026-11-11 18:45:03 +07:00
dotCooCoo c03fe29ad8 Plug-ins: the web build times the first-view budget and each run's limit
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.
2026-11-11 03:41:05 -08:00
BFlat 7e9633e3cb Merge pull request #6573 from dotCooCoo/fix/rasterize-side-limit
Rasterize: art longer than 32,768 pixels at the resolution is refused, not cut off
2026-11-11 18:35:36 +07:00
dotCooCoo baf8056c5f Merge main into fix/script-console-report-text 2026-11-11 03:28:54 -08:00
BFlat 31971bc090 Merge pull request #6555 from dotCooCoo/feat/plugin-effect-open-budget
Plug-ins: live effects of a document's first view share a 2,000 ms budget
2026-11-11 18:22:28 +07:00
dotCooCoo 68f3095cfd Print: Print as Bitmap prints all of a page longer than 32,768 pixels
Print as Bitmap limited each page's image to 65,535 pixels a side, but the
renderer draws at most 32,768. A 9000 x 100 pt artboard at a 300 ppi raster
effects resolution printed as an image that stopped at 7,864 pt and was
placed as if whole. The resolution is now lowered until the longest side
fits.
2026-11-11 03:21:57 -08:00
dotCooCoo 56abc9685b Merge main into fix/menu-list-recent-read-root 2026-11-11 03:20:53 -08:00
dotCooCoo dfa6e6ea60 MCP: ui.menu.list leaves out recent files outside the read roots
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.
2026-11-11 03:20:14 -08:00
dotCooCoo 0bb923fc40 Scripts: $.sleep throws where the run cannot wait, and toSource checks its length as it escapes
A getter, a conversion, a callback of a built-in function or a file
$.evalFile runs is executed on native frames, so the run cannot stop at a
$.sleep there. Such a call used to only mark the run to pause, so the
code after it ran first and the wait came later. $.sleep with more than 0
milliseconds now throws an Error there, as alert, confirm and prompt do.

toSource checked the 16,777,216-unit length limit only after a whole
string was written. A long string of characters that are escaped could
reach the heap limit first, which ends the run instead of throwing a
RangeError. The limit is now checked before each part is added.
2026-11-11 03:18:55 -08:00
BFlat d5c75d3699 Merge pull request #6567 from dotCooCoo/fix/flatten-long-area-side-limit
Flatten Transparency: a long rasterized area is placed whole
2026-11-11 18:16:31 +07:00
dotCooCoo df5d061b30 Scripts: an error $.evalFile could not run, caught and thrown again, is reported where it was thrown again
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.
2026-11-11 03:14:42 -08:00
dotCooCoo ee40cc10d7 Rasterize: art longer than 32,768 pixels at the resolution is refused, not cut off
Object > Rasterize and the redrawn path of Crop Image allowed images up to
65,535 pixels a side, but the renderer draws at most 32,768. A 100 x 5569 pt
rectangle rasterized at 600 ppi came back 32,768 pixels tall, and the bottom
29% of the art was gone. Such an image is now refused like one over the
64 megapixel limit, and the art stays as it was.
2026-11-11 02:55:59 -08:00
BFlat 4e0e1c8af7 Merge pull request #6564 from dotCooCoo/fix/graph-unpainted-row-opacity
Docs: a series mark's row without paint leaves the stored paint, not its opacity
2026-11-11 17:55:48 +07:00
BFlat 6244ac54bf Merge pull request #6560 from dotCooCoo/fix/pasted-svg-filter-names
Effects: pasted art keeps an SVG filter whose name the document gives another filter
2026-11-11 17:37:26 +07:00