@@ -7,6 +7,87 @@ first stable `1.0.0` tag; pre-1.0 `alpha` / `rc` tags may still change surfaces.
77
88## [ Unreleased]
99
10+ ## [ 1.15.4] - 2026-10-23
11+
12+ ### Added
13+
14+ - ** ` java.time.format ` : ` DateTimeFormatter ` , ` DateTimeFormatterBuilder ` ,
15+ ` ChronoField ` , ` ZoneId ` and ` ZoneOffset ` .** Pattern letters
16+ ` G u y M L d D F E a h K k H m s S n A N V X x Z O ` , optional sections,
17+ SMART and STRICT resolvers and the 12 ` ISO_* ` constants. Letters cljw does
18+ not implement raise ` not_implemented ` instead of formatting wrong text. This
19+ was the last blocker for ` malli.transform ` .
20+ - ** Primitive arrays cross ` cljw.ffi ` and wasm memory at memcpy speed
21+ (ADR-0204).** ` byte ` /` short ` /` int ` /` long ` /` float ` /` double ` /` char ` /` boolean `
22+ arrays hold raw native elements. A ` :pointer ` argument passes the array's
23+ storage with no copy, ` :bytes ` is one memcpy, ` wasm/mem-write! ` accepts a
24+ primitive array and the new ` wasm/mem-read-array ` returns one. ` bytes? ` is
25+ true only for a byte array.
26+ - ** ` bench/vs_bb ` :** 14 workloads that compare cljw with bb and JVM Clojure,
27+ with a non-blocking CI report.
28+ - ** ` docs/examples/zig-native ` :** one Zig source used both as a wasm guest and
29+ as a ` cljw.ffi ` library.
30+
31+ ### Changed
32+
33+ - ** Core sequence functions are much faster (ADR-0205).** The seq of a vector
34+ is now chunked by leaf, as clj's ` PersistentVector$ChunkedSeq ` is, and
35+ ` map ` , ` filter ` , ` into ` , ` mapv ` and ` reduce ` go through one chunked-seq
36+ boundary and the Zig ` reduce ` . On an 8000-element vector,
37+ ` (reduce + (map inc v)) ` went from 19271 us to 718 us and
38+ ` (count (filter even? v)) ` from 19646 us to 490 us. ` (first (map f v)) ` now
39+ realizes 32 elements, as clj does.
40+ - ** Protocol calls hit a per-function dispatch cache (ADR-0206).** Each
41+ protocol function remembers the method it resolved for the last receiver
42+ type; every ` extend ` , ` extend-type ` , ` extend-protocol ` and type redefinition
43+ invalidates it.
44+ - ** A Clojure fn call no longer memsets its scratch buffers.** ReleaseSafe
45+ filled about 2 KB of locals with 0xAA on every call. Skipping it cuts 18%
46+ of instructions from ` seq_dot ` , 38% from ` lazy_chain ` , 35% from multimethod
47+ dispatch and 10% from startup.
48+ - ** String and vector hot paths:** ` clojure.string/join ` , ` upper-case ` ,
49+ ` lower-case ` and ` split ` , ` subvec ` , ` str ` , keyword interning and
50+ ` dorun ` /` doall ` take native fast paths. The ` string_ops ` bench went from
51+ 9.3x bb to 2.3x bb.
52+ - ** Cold start does less work.** Deserializing the core image no longer maps
53+ a page per quoted list. ` cljw -e nil ` takes 27.3 ms of CPU, against 38.8 ms
54+ before and 29.1 ms for bb.
55+ - ** The GC returns freed memory and reuses it.** Small cells live in 64 KiB
56+ pages that are unmapped once empty, and String, array, transient-vector and
57+ BigInt payload bytes now count toward the collect trigger, so long-lived
58+ processes no longer hold their high-water mark.
59+
60+ ### Fixed
61+
62+ - ** ` clojure.edn ` reads the EDN dialect.** It used the permissive Clojure
63+ reader and accepted EDN-invalid input; it now matches JVM Clojure's
64+ ` EdnReader ` on 59 of 59 cases.
65+ - ** wasm ` i64 ` arguments and results cross exactly over the full range.**
66+ Values past 2^47 came back as a lossy Double or were refused, and an
67+ integral float of 2^63 crashed the host.
68+ - ** A BigInt, Ratio or BigDecimal past about 1233 digits prints its digits.**
69+ It printed the literal ` (BigInt) ` .
70+ - ** A long-running server that reads stdin now gives memory back.** The
71+ ` *in* ` and ` System/in ` readers kept every byte they had ever read; they now
72+ drop what has been consumed. While the main thread waits on stdin, each idle
73+ second runs a collect (when at least 1 MiB was allocated since the last one)
74+ and returns freed memory to the OS, so garbage left by ` future ` s and worker
75+ threads no longer waits for the next request. Socket and ` StringBuilder `
76+ buffers now count toward the collect trigger. A bb-mcp-shaped probe (20
77+ ` future ` s each building 4 MB of JSON, then idle) settles at 129 MB instead
78+ of holding 955 MB.
79+
80+ - ** A ` wasm/call ` on the JIT no longer costs time proportional to the
81+ module.** zwasm resolved the export by re-parsing the module on every call;
82+ it now reads the export table built at compile. A trivial export of a 47 KB
83+ module went from about 5.9 us to 0.8 us a call, the same as a tiny module.
84+ ` bench/wasm_percall.clj ` gains ` big-* ` cells that measure it.
85+ - ** A wasm handle called from a ` future ` no longer traps on the interpreter.**
86+ zwasm's interpreter cached the first calling thread's native-stack limit on
87+ the instance, so a handle warmed on the runtime thread and then called from
88+ another thread whose stack lay below that limit trapped
89+ ` CallStackExhausted ` . The limit is now per calling thread (zwasm 79f3d63a).
90+
1091## [ 1.15.3] - 2026-10-22
1192
1293### Added
0 commit comments