# Crystal 1.21.0 - Product: Crystal (https://whatsnew.fyi/product/crystal) - Vendor: Crystal Language - Date: 2026-07-16 - Version: 1.21.0 - Original notes: https://github.com/crystal-lang/crystal/releases/tag/1.21.0 - Permalink: https://whatsnew.fyi/product/crystal/releases/1.21.0 What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. Reuse: the summaries, labels and curation here are © What's New. Quote freely with attribution and a link back; wholesale republication of the corpus is not permitted — terms: https://whatsnew.fyi/terms. The vendors' own release notes remain their publishers'. --- - **removed** — Disable automatic fallback to legacy PCRE - **changed** — Release Execution Contexts - **added** — Add %W percent string array literals with interpolation - **added** — Add TypeNode#all_methods that includes the type's ancestor's methods - **added** — Align long-only options in OptionParser help - **added** — Make Channel(T) an Iterator(T) - **added** — Add support for OpenSSL 4.0 - **added** — Support OpenSSL 4.x DLLs on Windows MSVC - **added** — Add Socket#sendfile (and Crystal::EventLoop::Socket#sendfile) - **added** — Add HTTP::WebSocket#receive as a synchronous call - **added** — Add Crystal::EventLoop::FileDescriptor#pread - **added** — Add without_main flag - **changed** — OpenBSD: use kqueue event loop by default - **added** — Support nested root properties in JSON::Field - **added** — Add URI::Params::Field(ignore:), ignore_serialize, ignore_deserialize - **added** — Allow chaining #should, #should_not expectations - **added** — Expose Path#kind - **added** — Add splat overloads for Process.capture, .run and .new - **added** — Add Process::Status.[] constructor - **added** — Add String#present? - **added** — Add UUID.v6 and .v8 generators ###### Breaking changes ###### stdlib - _(runtime)_ Release: Execution Contexts ([#17100], [#17104], thanks @ysbaddaden) - _(text)_ Disable automatic fallback to legacy `PCRE` ([#16924], thanks @straight-shoota) [#16924]: https://github.com/crystal-lang/crystal/pull/16924 [#17100]: https://github.com/crystal-lang/crystal/pull/17100 [#17104]: https://github.com/crystal-lang/crystal/pull/17104 ###### Features ###### lang - Add `%W` percent string array literals with interpolation ([#16919], thanks @straight-shoota) - _(macros)_ Add `TypeNode#all_methods` that includes the type's ancestor's methods ([#16902], thanks @Blacksmoke16) [#16902]: https://github.com/crystal-lang/crystal/pull/16902 [#16919]: https://github.com/crystal-lang/crystal/pull/16919 ###### stdlib - _(cli)_ Align long-only options in OptionParser help ([#16914], thanks @kojix2) - _(collection)_ Make `Channel(T)` an `Iterator(T)` ([#16916], thanks @jgaskins) - _(crypto)_ Add support for OpenSSL 4.0 ([#16839], thanks @straight-shoota) - _(crypto)_ Support OpenSSL 4.x DLLs on Windows MSVC ([#17116], thanks @HertzDevil) - _(networking)_ **[experimental]** Add `Socket#sendfile` (and `Crystal::EventLoop::Socket#sendfile`) ([#16665], [#17133], thanks @ysbaddaden, @straight-shoota) - _(networking)_ Add `HTTP::WebSocket#receive` as a synchronous call ([#16689], thanks @jgaskins) - _(runtime)_ Add `Crystal::EventLoop::FileDescriptor#pread` ([#17068], thanks @ysbaddaden) - _(runtime)_ Add `without_main` flag ([#17074], thanks @kojix2) - _(runtime)_ OpenBSD: use kqueue event loop by default ([#17123], thanks @ysbaddaden) - _(serialization)_ Support nested `root` properties in `JSON::Field` ([#17016], thanks @tcoatswo) - _(serialization)_ Add `URI::Params::Field(ignore:)`, `ignore_serialize`, `ignore_deserialize` ([#17029], thanks @trypsynth) - _(specs)_ Allow chaining `#should`, `#should_not` expectations ([#17020], thanks @straight-shoota) - _(system)_ Expose `Path#kind` ([#16917], thanks @Sija) - _(system)_ Add splat overloads for `Process.capture`, `.run` and `.new` ([#16975], thanks @straight-shoota) - _(system)_ Add `Process::Status.[]` constructor ([#17003], thanks @straight-shoota) - _(text)_ Add `String#present?` ([#16930], thanks @Sija) - _(text)_ Add `UUID.v6` and `.v8` generators ([#17010], thanks @trypsynth) [#16665]: https://github.com/crystal-lang/crystal/pull/16665 [#16689]: https://github.com/crystal-lang/crystal/pull/16689 [#16839]: https://github.com/crystal-lang/crystal/pull/16839 [#16914]: https://github.com/crystal-lang/crystal/pull/16914 [#16916]: https://github.com/crystal-lang/crystal/pull/16916 [#16917]: https://github.com/crystal-lang/crystal/pull/16917 [#16930]: https://github.com/crystal-lang/crystal/pull/16930 [#16975]: https://github.com/crystal-lang/crystal/pull/16975 [#17003]: https://github.com/crystal-lang/crystal/pull/17003 [#17010]: https://github.com/crystal-lang/crystal/pull/17010 [#17016]: https://github.com/crystal-lang/crystal/pull/17016 [#17020]: https://github.com/crystal-lang/crystal/pull/17020 [#17029]: https://github.com/crystal-lang/crystal/pull/17029 [#17068]: https://github.com/crystal-lang/crystal/pull/17068 [#17074]: https://github.com/crystal-lang/crystal/pull/17074 [#17116]: https://github.com/crystal-lang/crystal/pull/17116 [#17123]: https://github.com/crystal-lang/crystal/pull/17123 [#17133]: https://github.com/crystal-lang/crystal/pull/17133 ###### compiler - _(cli)_ Classify compiler exit reasons ([#17028], thanks @straight-shoota) - _(debugger)_ Improve proc debug metadata ([#16830], thanks @skuznetsov) - _(debugger)_ Emit debug metadata for constants and class vars ([#16831], thanks @skuznetsov) - _(debugger)_ Improve LLDB collection formatters ([#16832], thanks @skuznetsov) - _(parser)_ Add `ASTNode#inspect` ([#16699], thanks @straight-shoota) - _(parser)_ Parse `MacroVar` with empty expressions: `%var{}` ([#16772], thanks @straight-shoot _[Truncated at 4000 characters — full notes: https://github.com/crystal-lang/crystal/releases/tag/1.21.0]_