Commit Graph
4259 Commits
Author SHA1 Message Date
BFlat df41593465 Merge pull request #6772 from dotCooCoo/fix/e4x-xml-declaration-check
Scripts: E4X checks the XML declaration and takes fuel for every run the parser scans
2026-11-12 12:40:21 +07:00
BFlat 63bdfc1655 Merge pull request #6758 from dotCooCoo/test/select-skips-raster-effects
Selection: a click on a drop shadow or glow selects the object under it
2026-11-12 12:40:12 +07:00
BFlat 1f1e7354ea Merge pull request #6780 from dotCooCoo/fix/action-batch-param-types
Actions: Batch refuses options of the wrong type before it writes
2026-11-12 12:39:54 +07:00
BFlat fee2b1340a Merge pull request #6773 from dotCooCoo/perf/flatten-opaque-chain
Flatten Transparency: opaque art that touches only opaque art stays vector
2026-11-12 12:39:46 +07:00
BFlat 72adc36f55 Merge pull request #6767 from dotCooCoo/feat/document-setup-color
Document Setup: a Color tab sets the color mode and the assigned profiles
2026-11-12 12:39:38 +07:00
dotCooCoo d56e241a43 3D and Materials: Expand as Wireframes turns a 3D object into its edges as paths
Window > 3D and Materials > Quick Actions > Expand as Wireframes, and the
command effect.expandAsWireframes, replace each selected object that has a
visible 3D effect (Extrude & Bevel, Extrude & Bevel (Classic), Revolve,
Inflate or Rotate) with a group of paths: the edges of the faces the effect
draws for the object as it is turned and projected now.

- Each edge appears once. Edges that meet end to end form one path, closed
  where it comes back to its start, and curved edges stay curves. Geometry
  effects after the 3D effect reshape the edges as they reshape the drawn
  surface.
- The paths have a 0.5 pt black stroke with round joins and no fill. The
  group keeps the object's id, name, transparency, attributes, slice and
  text wrap, and is selected. A layer stays a layer holding the edges.
- It is one undo step. Nothing selected, no visible 3D effect, a solid that
  can't be built or is drawn as its source art, or more than 1,000,000 edges
  in one object is an error, and the document does not change.

Docs: docs/mcp.md, docs/three-d.md, docs/effects-parity.md,
docs/target-app-parity.md.

Fixes #6354
2026-11-11 21:30:45 -08:00
dotCooCoo 9fc4e3c5cf Swatch libraries: Patterns › Grit Textures adds seamless grain, speckle and stipple patterns
Window › Swatch Libraries › Patterns and the Swatches panel's library
menu gain a second built-in pattern library, Grit Textures, with eight
black textures on square grid tiles of 18 to 36 pt: Fine Grain, Coarse
Grit, Sand, Speckle, Stipple, Scratches, Sparse Flecks and Dense Flecks.
Each is drawn in code from a fixed seed, so it is the same every time.
Marks that reach past a tile edge are drawn on the next tile by the
tiling, so the tiles join without a seam.

Docs: docs/mcp.md, docs/target-app-parity.md, ROADMAP.
2026-11-11 21:30:00 -08:00
dotCooCoo 1e70274189 Swatch libraries: Gradients › Organic Fades adds soft multi-stop fades that thin out to transparent
Window › Swatch Libraries › Gradients gains Organic Fades, a gradient
library of fifteen fades (ten linear, five radial). Each runs through
three to five unevenly spaced stops with off-center midpoints, mixes
with the Perceptual method, and thins out to transparent at the end of
a linear fade or at the edge of a radial one. The colors are computed
from VectorCraft's own OKLCH anchors.

The library also lists in the Swatches panel's library menu, in
swatch.library.list (category "gradients") and in the Gradient panel's
Presets. swatch.library.add keeps each fade's stops, opacities,
midpoints and method in RGB and CMYK documents.

The other built-in libraries are unchanged: their gradients still mix
with Classic and keep centered midpoints, and a test checks it.

- Gradient previews in the Swatch Libraries panel, the Gradient
  panel's Presets menu, swatch tiles and the toolbar drew every stop
  opaque. Each chip vertex now takes the sampled opacity as its alpha
  (freeform points too), and a chip with any translucent vertex draws
  a white and gray checkerboard under the gradient. Opaque gradients
  draw as before.
- When the preferences are applied, a saved gradient preset whose name
  matches a built-in preset, or an earlier saved preset, in any case,
  is renamed to the first free "<name> N" (N from 2), so a saved
  preset named like a new built-in fade stays listed and can be
  applied and deleted.
2026-11-11 21:26:11 -08:00
dotCooCoo 832fad16e0 Merge main into feat/hang-report 2026-11-11 21:17:30 -08:00
dotCooCoo 880cdea33c Brushes: a built-in Dry Media library of grainy chalk, pencil, crayon and charcoal art brushes
Window > Brush Libraries > Dry Media (`dry-media`) holds four art brushes:
Chalk Grain, Graphite Pencil, Wax Crayon and Charcoal Dust. Each is 100 pt
of filled vector paths generated from a fixed seed with integer steps and
plain arithmetic, at most 80 paths and 500 anchors, stretched along the
path with Tints colorization. The chalk and crayon art has even-odd gaps
cut out of its band.

The names, sizes and art are VectorCraft's own. A new i18n test checks
that every complete catalog names each built-in brush library.
2026-11-11 21:16:20 -08:00
dotCooCoo f82a31045c Blend: the Blend panel's Create Spine menu sets whether new blends get a spine
The Blend panel gets a Create Spine menu (Auto, Always, Never) under Make,
and object.blend.createSpine {mode?} sets or reads it. It is kept with the
preferences, is not an undo step and leaves blends already made as they are.
object.blend.make takes createSpine to choose for one new blend.

Auto and Always give every new blend a straight spine, as before. Never
makes a blend without one: its steps sit where a straight spine puts them,
object.blend.info reports hasSpine: false, easing is refused and dimmed,
Reverse Spine and the spine point commands refuse it, Release gives back
no spine path, and Replace Spine gives it a spine. A blend taking more keys
keeps whether it has a spine. Native files save noSpine; older files open
with their spines.

Builds on #5177 by adambelis.
2026-11-11 21:11:12 -08:00
dotCooCoo c4ace05dbf Graphic Styles: a built-in Painted and Sketched library adds watercolor, charcoal and ink styles
The Graphic Styles library menu lists nine libraries. Painted and
Sketched follows Hand-Drawn and holds Washed Blue, Bristle Ochre,
Pastel Heather, Charcoal Shade, Ink Contour, Wet Ink and Fine Pen. Each
style is a solid fill, two with a 1 pt stroke, under one watercolor,
dry brush, rough pastels, charcoal, ink outlines, sumi-e or graphic pen
effect with every setting given. The library and style names have rows
in all 27 catalogs, and docs/mcp.md describes the library.
2026-11-11 21:11:09 -08:00
dotCooCoo f1251af6e4 DXF: export options leave placed images and fill hatches out, and CNC / CAM turns both off
DXF Options gets Include Placed Images and Include Fill Hatches, and
document.exportDxf and document.export {format: dxf} take
includeImages and includeHatches. Both are VectorCraft's own options
and default to true, so Custom exports write what they wrote before.

- includeImages: false writes no IMAGE entity, IMAGEDEF, reactor or
  linked file for a placed image, and does not decode its pixels.
- includeHatches: false writes each filled area's outlines without the
  solid HATCH after them.
- Each adds one note to warnings when it left something out. R12,
  which has neither, keeps its own notes.
- The CNC / CAM preset sets both to false, so its drawing holds the
  cutting paths alone; the options given still override it, and
  changing either checkbox shows Custom.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 21:10:30 -08:00
dotCooCoo e83c36785e Commands: pointer events refuse pen values and spaces of the wrong type
ui.pointer and the headless pointer call read a pointer event's pressure,
holdMs, tiltX, tiltY and rotation with a default for any value that was not a
number, and treated any space other than screen as document space. Each event
is now checked before the packet runs: those values must be numbers and space
must be doc or screen, with null keeping the default. docs/mcp.md says so.
2026-11-11 21:04:01 -08:00
dotCooCoo d9a47bcb46 Merge main into feat/brushes-bristle-library
# Conflicts:
#	docs/target-app-parity.md
2026-11-11 21:01:54 -08:00
dotCooCoo 2f7c3854c7 Merge main into fix/script-sleep-reads-doc-cancel
# Conflicts:
#	docs/target-app-parity.md
2026-11-11 21:01:53 -08:00
dotCooCoo f526c5310c JS: XML and XMLList xpath evaluates XPath 1.0 expressions
xml.xpath(expression[, variables]) evaluates an XPath 1.0 expression
(https://www.w3.org/TR/1999/REC-xpath-19991116/) with the XML value as
the context node and returns the selected nodes as an XMLList, in
document order and without repeats. On an XMLList the expression runs
on each element in turn, and the results are joined.

- All 13 axes and the 27 core functions. id() selects nothing, since
  E4X trees carry no DTD data.
- Each property of `variables` binds the variable of its name. A
  prefix in a name test resolves through the context element's
  in-scope namespaces; `xml` is always bound.
- An expression that breaks the grammar gives a SyntaxError. An
  unknown function, a wrong argument count, an unbound prefix or
  variable, a result that is not a node-set, and a result that holds
  the root or a namespace node give a TypeError.
- The parser and the evaluator keep their state on their own stacks,
  so expressions of any depth use no native stack; nesting past
  Options::max_depth gives "nesting too deep". Traversal stacks, node
  lists, strings and the values that string functions build count
  against the heap limit, and every node visited and string read takes
  fuel.

Docs: docs/target-app-parity.md (E4X line), crate doc in lib.rs.
2026-11-11 21:01:32 -08:00
dotCooCoo 8e6a9e5b71 Merge main into fix/inspect-library-ids-whole 2026-11-11 20:54:59 -08:00
dotCooCoo 651041fc0c Merge main into fix/options-dialog-menus
# Conflicts:
#	docs/mcp.md
2026-11-11 20:48:58 -08:00
makesomethingshit 88894ef27c Merge latest main and retain Live Paint and Eyedropper evidence 2026-11-12 13:48:23 +09:00
dotCooCoo 35be7952c8 Save and Export: the status bar's hover lists every note
A save or an export with several notes named only the first of them in
the status bar, with the count, and the others could not be seen. The
status bar now keeps every note of a save or an export for the status
message's hover, as it does for an open's notes since #6752: resting
the pointer on the message lists them in the order the reply gives them
(a save's notes start with what the format loses), and screen readers
receive the list after the message. The status text is unchanged.

This covers Save, Save As, Save a Copy, Save as Template, Save a
Timestamped Copy, Save as PDF, Export As, Export Selection, Export for
Screens, Asset Export, Save for Web, Preview in Browser, Save for Office
Documents, Text Export Options, a print to a file and the CSS Properties
panel's export. The open, the saves and the exports read a reply's notes
through one helper.

Docs: docs/mcp.md and the css.exportFile params text,
docs/control-protocol.md, docs/target-app-parity.md.
2026-11-11 20:44:53 -08:00
dotCooCoo 987dd18aff File formats: HP-GL (.plt) plots export for pen plotters and cutters
VectorCraft could open and place HP-GL plot files but not write them,
so art for a pen plotter or a vinyl cutter had to go through another
program.

Export As, document.export and Export Selection now write HP-GL.
vectorcraft_cad::hpgl::export draws each visible path once along its
own line: a filled shape is its closed outline and a stroked path its
center line. Type is drawn as glyph outlines, a gradient mesh as its
outline, and a symbol instance as its art with its effects and the
instance's stain. Clipping masks cut the art they clip, and the art is
cut at the artboard's edges. Hidden and non-printing layers, hidden objects,
objects at 0% opacity, template layers, guides and placed images are
left out. Coordinates are plotter units (1016 to the inch, y up) from
the artboard's bottom-left corner or its center, and art more than
8,388,607 units from the origin is cut off.

Each color is a pen, in the order the plot first draws in it (up to
255), or a pen table maps each path to the pen of the nearest color.
With Use Artboards every file of the export uses the same numbering.
The pens draw in turn, each in paint order or, with sortPaths, nearest
path first. Curves are flattened to curveTolerance (0.1 pt by default).
hpglVersion "hpgl" writes IN, SP, PU and PD; "hpgl2" also writes the
palette (NP, PC) and each pen's paths as one encoded polyline (PE).
Options are checked, and Export As writes the file with the defaults.
Plots read back by the HP-GL reader give the same lines.

Docs: docs/mcp.md, docs/control-protocol.md, docs/file-format-parity.md,
docs/target-app-parity.md.
2026-11-11 20:44:32 -08:00
BFlat aa4657e1ce Merge pull request #6704 from dotCooCoo/fix/shape-tool-handles-scale
Shape tools: a drag on a bounding-box handle scales the selection
2026-11-12 11:43:06 +07:00
dotCooCoo cd262fa6e8 MCP: save, export and package replies leave out paths outside a confined client's read roots
A client confined with --automation-read-root could learn paths it was
not given and may not read from the replies of several commands. Each
one now names such a path only when no read roots are in force or the
path is inside them:

- document.save and file.save, file.saveAs, file.saveCopy and
  file.saveAsTemplate (app.save and engine.execute) without a path:
  the document's own file, the files of separate artboards and linked
  files are left out or named by file name, and the folder a save
  suggests is left out.
- document.exportForScreens with the folder of an exportPreset: the
  ZIP path is left out and files are relative to that folder.
- document.exportSettings, document.exportPresets.list and
  document.exportPresets.export: a kept folder outside the read roots
  is left out of the reply and of the presets file the export writes.
- file.package: warnings, missingLinks and the report name a file
  outside the read roots by its file name. A link's stored path, read
  from the document's folder when it is relative, decides, also when
  its file was found under another path.
- document.info: an image linked to a file outside the read roots has
  link null, and its Linked Images row names the file alone.

docs/mcp.md and the params text describe the rule.
2026-11-11 20:42:57 -08:00
BFlat dec6717379 Merge pull request #6726 from dotCooCoo/feat/hpgl-import
File formats: HP-GL (.plt) plot files open and place
2026-11-12 11:42:46 +07:00
BFlat b93b6d6a4f Merge pull request #6729 from dotCooCoo/feat/control-bar-align-to
Control bar: an Align To menu follows the Align buttons
2026-11-12 11:42:38 +07:00
BFlat b945662f75 Merge pull request #6700 from dotCooCoo/fix/script-files-followups
Scripts: File and Folder exists checks the kind, encode keeps slashes, every call is counted
2026-11-12 11:42:26 +07:00
BFlat 3baa943174 Merge pull request #6693 from dotCooCoo/fix/pdfa-14-long-pages
PDF: a PDF/A-2b file at PDF 1.4 writes long pages as PDF 1.6 with a UserUnit
2026-11-12 11:42:17 +07:00
BFlat cd92345707 Merge pull request #6759 from dotCooCoo/fix/js-tosource-property-flags
Scripts: toSource refuses read-only, non-configurable and non-extensible data it cannot write back
2026-11-12 11:42:09 +07:00
BFlat d843a4f1ec Merge pull request #6670 from dotCooCoo/fix/plugin-put-back-result
Plug-ins: an update left in the store by a failed put-back turns a disabled plug-in on
2026-11-12 11:42:01 +07:00
BFlat 5e181e2aec Merge pull request #6699 from dotCooCoo/fix/links-read-roots
MCP: links.list, links.check, links.info and document.open leave out paths outside the read roots
2026-11-12 11:41:52 +07:00
BFlat 95325e8ef0 Merge pull request #6694 from dotCooCoo/feat/char-style-options-tcy-offsets
Type: Character Style Options sets Tate-chu-yoko Up/Down and Left/Right
2026-11-12 11:41:41 +07:00
BFlat d349c4b586 Merge pull request #6775 from dotCooCoo/feat/image-remove-background
Image Tools: Remove Background clears an image's background in its pixels
2026-11-12 11:41:32 +07:00
BFlat 3ba9ae2b47 Merge pull request #6738 from christianlappin/codex/fix-6404-eyedropper-text-scale
Fix Eyedropper font size and horizontal scale on transformed text
2026-11-12 11:41:23 +07:00
BFlat ea3a4ec373 Merge pull request #3145 from adambelis/feat/width-smooth-profile
Width profiles run smooth between their points
2026-11-12 11:41:15 +07:00
makesomethingshit 7a5486d15d Merge upstream main into Live Paint Bucket fix 2026-11-12 13:39:41 +09:00
dotCooCoo 8b768bb27b Merge main into fix/inspect-library-ids-whole 2026-11-11 20:32:17 -08:00
dotCooCoo 66d21471ae Gradients: diamond gradients run the stops from the center out to a square
A new gradient kind, `diamond`, runs its stops from the center (the
start) out to a square with a corner at the end of the vector; the
aspect stretches the square across the vector into a rhombus. The
Gradient panel's Type row has a Diamond button, the Gradient tool draws
the square with the aspect handle and center ring, and a gradient
fitted to an object covers its box.

- Model and canvas: the level is |x| + |y| in the square's frame; a
  square with no area (no vector, an aspect of 0, numbers out of range)
  paints the last stop. The canvas draws it as pixels, out to a
  stroke's miters, caps and arrowheads. Transforms keep the vector and
  take the mapped size across it as the aspect.
- Commands: `paint.setFill`, `paint.editGradient` and
  `paint.setGradientGeom` take `kind: "diamond"`; a negative aspect or
  a focal point is an error. A conic or diamond gradient that a plug-in
  returns with a focal point loses the focal point.
- Gradient tool: dragging the aspect handle of a radial or diamond
  gradient whose file gave it a negative aspect now sets a positive
  aspect; only a conic's negative aspect mirrors it.
- Export: PDF, SVG, EPS and legacy .ai write four linear gradients, one
  for each quarter of the square, clipped to the shape (PDF as axial
  shadings). PDF and SVG write an image for translucent stops, a
  dithered fill or a flat square, and for the Perceptual method unless
  PDF writes the stops as spot color shadings. SVG writes a diamond on
  type characters as a radial gradient through the corners, and so
  does CSS. A swatch library saved as CSS gets four corner layers, a
  value for the `background` property (a circle when the swatch is
  turned by an angle that is not a multiple of 90 degrees). The .ai
  editing data holds a radial gradient through the corners. The
  document exports give a warning.
- SVG export: a stroke drawn as an image, as conic wedges or as diamond
  quarters now covers the miters, caps and arrowheads that reach past
  its paint box.
- PDF import reads a function-based shading whose color is the same
  along each square about the origin of its space as a diamond.
- Object > Expand gives nested squares or a mesh of rings.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-11 20:27:48 -08:00
dotCooCoo eff5765b07 Docs: Flatten Transparency's evidence line states when opaque art joins a group in its first sentence 2026-11-11 20:12:22 -08:00
dotCooCoo 69c3da175c Actions: Batch refuses options of the wrong type before it writes
action.batch read its true/false options with a fallback, so
{"stopOnError": "false"} kept stopping on the first error, and a
number for a string option such as label or datasetFileNaming was
dropped or turned into an empty string. The source check also ran
after the destination folder was made.

includeSubdirs, overrideOpen, overrideSave, overrideExport and
stopOnError now take only true or false, and source, folder,
destination, destinationFolder, datasetFileNaming and label take only
a string. Any other value is an error naming the key, given before the
destination folder is made or a file is opened. A null reads as a key
left out. The params text and docs/mcp.md say so.
2026-11-11 20:11:50 -08:00
dotCooCoo 8bd437687a Scripts: a canceled request stops a sleeping or waiting run at its next slice
script_pump read vectorcraft_doc::cancel only after the guard that keeps
a run waiting, so a run asleep in $.sleep went on waiting until its wake
time (up to 1,000 ms), and a run waiting at a dialog or for approval to
grow waited until someone answered. The check now runs before that
guard, after the dialog-failure check, so a canceled request ends the
run at the next slice and every document goes back.
2026-11-11 20:01:25 -08:00
dotCooCoo a9e7dfb2f8 Merge main into fix/options-dialog-menus 2026-11-11 19:59:50 -08:00
dotCooCoo f3b089f83f Merge main into feat/styles-textures-library 2026-11-11 19:59:30 -08:00
dotCooCoo 7c28138ce3 Commands: pointer packets are read whole before any event runs
A headless or control channel pointer packet now checks every event's kind,
coordinates and mods before it sends any of them, so a malformed later event
no longer leaves the earlier ones applied. A mods value that is not an object,
such as an array, is refused. Rotate View takes null mods as omitted. The MCP
docs name the params that refuse null.
2026-11-11 19:57:39 -08:00
dotCooCoo d151f3f5d0 JavaScript: source that eval and Function compile takes fuel before it is parsed
Direct and indirect eval, Function and host evaluators parsed and compiled
their source before taking any fuel or checking the heap, so a script with a
small fuel limit could make the interpreter parse megabytes of source in a
handful of instructions. Interp::prepare_source now takes one unit of fuel for
each UTF-16 code unit and checks that the source text fits in the heap before
the source is flattened, parsed or compiled. A host evaluator's string takes
the fuel for a third of its bytes before it is encoded, and the rest after.

Limits::fuel and the maxFuel row in docs/mcp.md say so.
2026-11-11 19:52:06 -08:00
dotCooCoo f65f3029a6 Image Tools: Remove Background clears an image's background in its pixels
A new built-in add-on, Image Tools (Object › Plug-ins › Image Tools),
adds Remove Background… (`addon.image.removeBackground`). It makes the
background of the selected images transparent by lowering the alpha of
their own pixels, in one undo step, with no service or model. The
background is the most common color along the image's edges, the
average of the image's corners, or colors the user picks. Contiguous
(on by default) clears it only where it reaches in from an edge; off,
it is cleared wherever it is. Tolerance and Softness (0 to 100, 10 by
default) set how near a color must be to be cleared and the band over
which pixels fade out. Match measures that nearness as the RGB
distance or as the largest difference on one channel. It is a
VectorCraft addition.

- The image stays an image: an embedded PNG with alpha, the source's
  ICC profile and resolution, and 16 bits or gray when the source is.
  A linked image is embedded and keeps its Placement Options.
- When the edges hold at least as many clear pixels as pixels of their
  most common color, edge mode clears nothing, so a second run leaves
  the subject alone. Corner mode leaves clear corners out of the
  average and clears nothing when all four are clear.
- With Match set to Each Channel, a tolerance of t / 255 × 100 clears
  the colors within t 8-bit steps on every channel.
- A CMYK image, a linked image that shows its preview, an image that
  would need more than the decode allowance (checked from its header)
  and a result with no pixel left are refused, and the document stays
  as it was. When no pixel changes, no undo step is added. The result
  reports `cleared`, the pixels made fully clear.
- Picked colors are hex colors, with or without `#`, or black, white,
  red, green or blue.
- The dialog opens with Preview off; with Preview on, the canvas shows
  the result, and Cancel puts the image back. While the dialog
  previews, the session keeps the images' decoded pixels (at most
  128 MiB, 32 MiB in the web app) so each preview step does not decode
  them again, and releases them when the dialog closes with OK or
  Cancel. A run that is not a preview step keeps nothing.

Docs: docs/mcp.md (Image Tools add-on), docs/target-app-parity.md.
2026-11-11 19:47:28 -08:00
dotCooCoo 9d9cb52017 MCP: hidden library paths are matched before the paths a request sent
A sent path whose text overlapped part of a hidden library's path could
keep that path from being hidden; the hidden libraries' ids and paths
are now matched first. A hidden relative path is also hidden where a
reply shows the absolute path it reads as from the working folder, and
a hidden library sent by that other form shows as the sent path does.
2026-11-11 19:44:43 -08:00
dotCooCoo e609b26a95 Warp: bend each style as one Bézier patch, and keep saved warps' look
Each of the fifteen Warp styles now bends the bounds as one Bézier patch.
The style sets the patch's control points from the bend and the size of
the bounds, the horizontal distortion scales each column of control
points about its middle, and the vertical distortion scales each row.
The Warp effects and warp envelopes share the map (`WarpNet`). Content
with no width or no height takes the middle of the patch along that
side.

A warp carries the map it draws with as `version`. New warps, the
built-in graphic styles' Warps and warps opened from .ai files get 1.
Warps in .vectorcraft documents saved before the version existed read
as 0 and keep the earlier map, so those documents keep their look.
Edits keep a warp's version, and Warp Options editing several objects
keeps each one's own. effect.apply, effect.setParams and the warp
envelope commands take `version` 0 or 1 (`1.0` counts as 1) and refuse
any other value. An .ai file holds a warp's settings and not its
version, so a version 0 warp saved to .ai opens again with version 1.
The .ai writer compares a style's settings without the version, so
saved warps still export as editable effects.

Docs: docs/mcp.md (Envelopes), docs/effects-parity.md (Warp),
docs/target-app-parity.md.
2026-11-11 19:40:01 -08:00
dotCooCoo db97cc1a8f JavaScript: a bare E4X name inside with or a filter can be assigned
With Options::e4x set, an E4X name standing alone (@a, @ns::a, @[expr],
ns::a, *) is now a valid target for =, compound assignment, ++, --,
delete and for/for each loops, as well as a read. The target is the
nearest XML or XMLList value in scope whose [[HasProperty]] accepts the
name (ECMA-357 section 11.1). The name is evaluated once, and the
target resolves before the right-hand side runs.

When no XML value in scope holds the name, a read or write throws a
ReferenceError and creates no child or attribute. A read no longer
falls back to the first XML value in scope, so a filter such as
list.(@id == '1') throws when an item has no @id and no outer XML
value holds one, instead of treating that item as not matching.
2026-11-11 19:35:59 -08:00
dotCooCoo 781357921e Scripts: E4X checks the XML declaration and takes fuel for every run the parser scans
An XML declaration at the start of XML or XMLList text was skipped up to
the next "?>" without being read. It is now checked against XML 1.0's
grammar (https://www.w3.org/TR/xml/#NT-XMLDecl): a version of "1." and
digits, then an optional encoding name and an optional standalone "yes"
or "no", in that order, with optional white space before "?>". Any other
declaration gives "SyntaxError: invalid XML declaration", and a character
XML does not allow gives "invalid character in XML text". White space
before the declaration is still accepted.

The parser now takes fuel for the length of the declaration and the
white space before it, element and attribute names, white space in open
and closing tags, and the text it searched when an attribute value, CDATA
section, comment or processing instruction is not closed, or when "]]>"
or "<" stops a text run or attribute value. A long run in any of these
used the same fuel as a short one.
2026-11-11 19:35:39 -08:00