flat_charged and the property-key path now root the rope itself, so a string held only by
native code (a getter's result for ++o.x, a valueOf result, a toString key) still counts
what it holds when the reservation collects. The per-call roots for these cases are removed.
When the flattened copy of a String object's concatenated string would pass the heap limit
before a collection can run, the indexed read walks the rope to the unit instead, taking a
unit of fuel for each node it visits, so no copy is made.
- wrapping a string no longer flattens it, so Object(s).length and new String(s) on a large concatenated string make no copy and cannot collect while a call's operands are off the stack
- reading a String object's character by index, `in` and hasOwnProperty count the flattened copy at the next limit check, and the run ends before the copy when the fuel for it is not left
- unary plus on an object whose valueOf returns a concatenated string, and a property key from toString, keep that string rooted while its copy is reserved
- the unshift comment cites step 6 of section 15.4.4.13
Boxing the string receiver of a non-strict function flattens it, and reserving the copy can
collect. The callee, receiver and arguments are already off the stack at that point, so they
stay in the temporary roots until the frame holds them; before, an argument object could be
freed and its cell reused by the wrapper. new String(value) roots the converted string the
same way, so what the rope holds is still counted while its copy is reserved.
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.
In distance mode, each pixel took a square root for every background color.
The nearest color is now found by squared distance, and only that distance is
converted to a percentage. The levels do not change.
- the relational operators root both strings while flattening them, so the first copy still counts when the second one starts a collection
- join roots its separator for the whole join and each element while it is written, and JSON.stringify roots a string while it writes it
- a String object flattens its string when it is made, with the copy counted, so reading one of its characters copies nothing
Affinity: read native documents with craft-affinity from craft-libs
* Affinity: read native documents with craft-affinity from craft-libs
crates/affinity's reader moved to craft-libs as craft-affinity (#914).
The crate keeps its name and re-exports it, so the engine, the corpus
tests and fuzz targets, and the Affinity corpus CI job are unchanged.
Its integration tests take craft-libs' versions; the one signature that
changes is patchy-shapes-2.af, whose special shapes now have outlines.
* Affinity: pin craft-affinity to craft-libs 228f6d0c (no change to the crate)
cached_frames_keep_their_scale_during_resize_rotation_and_dpi_changes
delivered the worker's frame with a 1 ms render time. The canvas key
carries the process-wide placed-document generation, so when another
test in the same run made a placed bitmap between the delivery and the
next frame, the key no longer matched. With a 1 ms last frame, the next
frame rendered on the UI thread over the delivered one, and the
"the worker's frame arrived" assertion failed.
The delivered frame now reports 50 ms, as the frames before it do, so a
moved generation queues the next frame on the controlled worker and the
delivered frame stays shown.
drop_left forgot a copy in an area the session left before removing it, so a copy whose removal failed (the area read-only for a moment) could later be offered back to the same session as a crash's copy. The entry now stays until both files are removed, and the next heartbeat tries again.
Convert to Artboards found the highest artboard id twice for each object it
converted: once for the new artboard's name and once in
Document::next_artboard_id. Converting N objects read about N^2 artboards.
The command now keeps the highest id as it adds artboards, and
Document::next_artboard_id_above gives the next id from it. When an artboard
has id u32::MAX, it falls back to next_artboard_id, which takes the smallest
free id. The ids and names it gives are unchanged.
The fuel and heap checks for a host evaluator's source were split into a third
before encoding and the rest after, so a source whose whole UTF-16 text did not
fit in the heap could still be encoded and parsed. The whole encoded size is now
reserved before encoding. A source over the source limit is still refused as a
syntax error.