## crystal-lang/crystal — v1.20.3…v1.21.0

_178+ commits._

### Features
- **Support OpenSSL 4.x on Windows** — Updated Windows OpenSSL library linking to dynamically use the major version number from OpenSSL, allowing support for both OpenSSL 3.x and 4.x DLLs instead of hardcoding version 3. (f52a365)
- **Add `without_main` flag (#17074)** (e805a1d)
- **Add `Crystal::EventLoop::FileDescriptor#pread` (#17068)** (e1c32ba)
- **Add `compiler-cli` test suite (#17033)** (ce17a8a)
- **Add `URI::Params::Field(ignore:)`, `ignore_serialize`, `ignore_deserialize`  (#17029)** (9ed3112)
- **Add `%W` percent string array literals with interpolation (#16919)** (72d7e6e)
- **Support nested `root` properties in `JSON::Field` (#17016)** (d048e40)
- **Add specs for `Iterator.empty` (#17014)** (6c74cdc)
- **Add `UUID.v6` and `.v8` generators (#17010)** (4d0deff)
- **Add `Process::Status.[]` constructor (#17003)** (9a5513a)
- **Add `HTTP::WebSocket#receive` as a synchronous call (#16689)** (871629b)
- **Add splat overloads for `Process.capture`, `.run` and `.new` (#16975)** (e785a1d)
- **Add interpreter `upcast_distinct` for `Pointer` to `Pointer` (#16962)** (aba45d7)
- **Add specs for HTTP request params media type parsing [fixup #16934] (#16971)** (a8187e6)
- **Add support for OpenSSL 4.0 (#16839)** (a9cef1f)
- **Add `TypeNode#all_methods` that includes the type's ancestor's methods (#16902)** (1cfa816)
- **Add `String#present?` (#16930)** (abe049c)

### Fixes
- **Fix endianness detection in ELF** — Fixed how the system detects endianness when validating ELF (Executable and Linkable Format) file headers by using the proper `IO::ByteFormat` API instead of a compiler flag. This ensures correct validation on systems with different byte orders. (382a7df)
- **Fix DragonFly compiler flag name** — Corrected a compiler flag from `dragonflybsd` to `dragonfly` in the socket implementation to properly target DragonFly BSD systems. (02f4e0e)
- **Fix sysctl CPU detection command** — Corrected the sysctl parameter name from 'hw.cpu' to 'hw.ncpu' in the system CPU detection logic. This fixes how the library queries the number of processors on certain systems. (e8e357a)
- **Skip invalid Windows MIME types** — Fixed a crash when Windows registry contains MIME type entries with invalid Content Type values. The system now safely skips those entries instead of crashing. (bb42a39)
- **Fix execution context flag logic** — Corrected a conditional flag check in the Windows file descriptor module to properly handle multithreading and execution context configurations after a recent merge. (a641a91)
- **Fix `IO::Encoder#write` when operating on long strings (#16797)** (a36577b)
- **Fix short block setter call end location (#17039)** (d04e32a)
- **Fix: Fiber::ExecutionContext.current? (#17092)** (5a0e847)
- **Fix: `fdlock#try_close?` must release ref after yielding to the block (#17089)** (45d79d7)
- **rumdl: Fix MD077: Continuation line over-indented (#17085)** (15b2af4)
- **Revert "Fix: cross-compile crashes when combined with emit llvm-bc or obj (#17060)" (#17080)** (6c38396)
- **Fix: underperforming unlock conditions in `Sync::MU` (#17070)** (19e9dfd)
- **Fix: cross-compile crashes when combined with emit llvm-bc or obj (#17060)** (f38c6d9)
- **Fix: Crystal 1.0.0 is confused by file private types (#17067)** (d163881)
- **Fix swapped atomic orderings in `Sync::MU` fast paths (#17063)** (499d003)
- **Fix: thread safety of the libevent event loop (#17031)** (486db2b)
- **Fix: memory leak in `XML::Node#each_namespace` (#17038)** (21db722)
- **Fix formatter strip empty lines in heredoc (#17034)** (ce3649d)
- **Fix: `EventLoop::IoUring#open` musn't set `O_NONBLOCK` when blocking (#17035)** (20ec093)
- **Fix violations reported by ameba 1.7 (#17021)** (05c5400)
- **Fix use line 0 for unknown debug location (#17013)** (71b9076)
- **Fix summary wrapping condition in OptionParser (#16915)** (972eb75)
- **Fix `HTTP::Client` to retry for connection recovery only (#16981)** (583a23a)
- **Fix: `Fiber::ExecutionContext::Monitor` compat with old Crystal releases (#17007)** (d6f2574)
- **Fix format annotations of splat parameter (#16987)** (e55d903)
- **Fix interpreter multidispatch cache collision (#16958)** (ac82b6b)
- **Fix parser allow `/` and `//` immediately after `self`, `nil`, `true`, `false` (#16942)** (ef65943)
- **Fix parser silently ignoring `&(...)`, `&[...]`, `&{...}` in assignment (#16960)** (09b94a4)
- **Fix codegen treating distinct lib `type` aliases as the same type (#16961)** (38c3113)
- **[CI] Fix tags for nightly docker images (#16973)** (1e4b98c)
- **Fix `HTTP::Request.form_params?` to recognize `Content-Type` and `charset` (#16934)** (4714184)
- **Fix `Iterator#compact_map` with non-nilable compactor proc (#16927)** (3b756f0)
- **Fix formatter on empty string literal continuation (#16817)** (5700440)
- **Fix `Iterator#compact_map` with `EmptyIterator` (#16928)** (266d0ea)
- **Fix macro argument errors for path receiver calls (#16923)** (768aee5)
- **Fix `sizeof`, `offsetof` as generic type argument in inferred ivar type (#16811)** (995a5cb)
- **Fix auto-indentation in the REPL when typing classes. (#16910)** (7647a93)
- **Fix formatting whitespace in ternary `if` with trailing comments (#16880)** (23ae0d1)
- **Fix parse parenthesized expression in block arg assignment (#16894)** (c328dd6)
- **Fix parsing macro var without exps followed by macro expression (#16879)** (f4c50cd)

### Backend
- **Version 1.21.0 released** — Repo Wrapped version 1.21.0 is now available. This release includes changelog updates, version bumps, and build script improvements. (57cf7da)
- **Simplify OpenBSD event loop** — OpenBSD 7.8 now supports EVFILT_USER, allowing the event loop to use it directly instead of falling back to a custom pipe-based workaround. This simplifies the code by removing conditional compilation paths and reducing complexity in interrupt handling. (edd8336)
- **OpenBSD now uses kqueue event loop** — OpenBSD systems will now default to using the kqueue event loop instead of libevent, improving performance based on testing with OpenBSD 7.8. (7f44e4b)
- **Revert unused yield block optimization** — Removed a previous optimization that prevented materializing unused yield block values in debug builds. This reverts changes to how block values are handled during code generation. (952418a)
- **Updated development dependencies** — Updated the development environment lock file with newer versions of devenv, git-hooks.nix, and nixpkgs dependencies. Also removed an unused gitignore dependency from the git-hooks configuration. (c9d4dec)
- **Updated GitHub Actions dependencies** — Bumped versions of multiple GitHub Actions workflows including backport-action (v4.5 → v4.6), AWS credentials (v6.2.0 → v6.2.2), Nix installer (v31.10.6 → v31.10.7), typos spell-checker (v1.47.2 → v1.48.0), and cache actions (v5 → v6) across Windows, macOS, and Linux CI pipelines. (1bdd912)
- **Fix unused yield block values in debug** — Improved code generation to avoid creating unnecessary memory allocations for unused yield block values when building with debug symbols. This reduces memory overhead in debug builds while maintaining correct behavior. (48ec573)
- **Global IOCP for file and socket operations** — Windows systems now use a single global I/O completion port to manage all file and socket operations across event loops, preventing context conflicts and ensuring operations are routed to the correct event loop. This fixes issues where operations started in one context could become orphaned or block other contexts when the original context shuts down. (7225831)
- **Added missing_option example to docs** — Updated the OptionParser documentation to include an example showing how to handle cases when a command-line flag is missing its required argument. (706208b)
- **Upgrade Crystal bootstrap to 1.20.3** — Updated the Crystal compiler version used for bootstrapping and testing from 1.20.2 to 1.20.3 across all CI/CD workflows, build containers, and development environment configurations. (c7aea41)
- **Add YAML security protections** — Added protections to the YAML parser to prevent denial-of-service attacks: a maximum nesting depth limit (512 levels) to prevent stack overflows from deeply nested structures, and an alias/anchor ratio check to prevent billion-laugh attacks where documents use excessive aliasing to expand exponentially. The anchor name is now cached for efficiency. (b4bcf9f)
- **Release: Execution Contexts (#17100)** (abd23b8)
- **Deprecate `spawn(same_thread:)` (#17097)** (2720853)
- **Update `devenv.lock` (#17084)** (2cb6c1e)
- **Consolidate `#overlapped_connect` and `#overlapped_accept` into `EventLoop::IOCP` (#17090)** (9908861)
- **Refactor `run_git` spec helper to use `Process.capture_result?` (#17079)** (70b433d)
- **Split branches on `when Bar, Baz` (#17072)** (8102e35)
- **Replace `.markdownlint.yaml` with `rumdl.toml` (#17078)** (f1418c8)
- **Update GH Actions (#17076)** (06d3c54)
- **Update `devenv.lock` (#17075)** (21a3c0e)
- **Remedy short-flag conflict for `crystal spec -p` (#17062)** (1b3574b)
- **Disable transport read-ahead for kTLS sockets (#17053)** (9b4365e)
- **Replace `markdownlint` with `rumdl` (#17069)** (299ac42)
- **[CI] Upgrade nixpkgs 26.05 in `Lint` workflow (#17066)** (3b363a7)
- **infra: devenv input for `git-hooks` follows `nixpkgs` (#17064)** (34b8b70)
- **Preallocate correct size for hash in `Hash.zip` (#17054)** (2186d2f)
- **Avoid `Process.exec` on Windows and explicitly spawn subprocess (#17049)** (a534600)
- **Update `devenv.lock` (#17057)** (14fb46f)
- **Align long-only options in OptionParser help (#16914)** (893994d)
- **Drop unused `IO::Evented` and `Crystal::ThreadLocalValue` (#17032)** (f65603e)
- **Update `devenv.lock` (#17040)** (86499ca)
- **Update GH Actions (#17042)** (7fd15e7)
- **[CI] Upgrade windows runners to VS 2026 (#17043)** (eeb52a8)
- **Document `String` is not inheritable (#17000)** (22a5895)
- **Symmetric `common_descendent` for two generic class types (#10831) (#16999)** (7fdca33)
- **[CI] Upgrade library dependencies for Windows CI (#17025)** (3ce9a1f)
- **Classify compiler exit reasons (#17028)** (70137bd)
- **Internalize `IO::Evented` into `Crystal::EventLoop::Wasi` (#17030)** (e3bb1ad)
- **[CI] Update `macos-15` runners to `macos-26` (#17022)** (f203446)
- **Refactor formatter, remove internal `delimited_pair(advance)` (#17023)** (0fd9282)
- **Apply `mbake` formatter for `Makefile` (#17024)** (6591f0d)
- **Replace backticks with `Process.capture` (#17012)** (68ca6ab)
- **Update GH Actions (#17011)** (79cb189)
- **Allow chaining `#should`, `#should_not` expectations (#17020)** (945d7be)
- **Apply `shfmt` (#17015)** (45d183a)
- **Merge `release/1.20` into master** (3b7e1cc)
- **Hide platform-specific `Process::Status` constructor (#16997)** (de0c148)
- **Update `devenv.lock` (#17006)** (c8a6807)
- **Improve LLDB collection formatters (#16832)** (8365f55)
- **Keep wider subclass observer when call owner narrows (#16947) (#16990)** (457bd42)
- **Refactor compiler code to raise `CompilerError` instead of `abort` (#16995)** (79cf0d3)
- **Makefile: Build manpages for `install` target (#16991)** (957e5dc)
- **Format asciidoc (#16992)** (aa63cce)
- **Set `optsize` and `minsize` fun attributes for the `-Os` and `-Oz` optimization modes (#16983)** (a534941)
- **Disable automatic fallback to legacy `PCRE` (#16924)** (6424595)
- **Update `release-update` script (#16977)** (3e31090)
- **Split error helper for compiler CLI into independent methods (#16984)** (8c632e8)
- **Makefile: Split `install` target into subcomponents (#16980)** (ed9179c)
- **Preserve `nil_if_read?` across while cond filters (#16963)** (eb95c03)
- **Update crate-ci/typos action to v1.46.2 (#16986)** (5008ba0)
- **Update `devenv.lock` (#16979)** (aef052c)
- **Detect uninitialized ancestor ivars through macro_def initializers (#16959)** (c9e867a)
- **Drop separate `aarch64` workflow (#16965)** (2c20151)
- **Do not merge nested `Expression` and `ExceptionHandler` (#16852)** (882f42f)
- **Refactor bubbling exceptions from user code in `HTTP::Client#exec(&)` (#16969)** (c417a3d)
- **Extract spec helpers `close_connection` and `client_for` for HTTP client specs (#16968)** (5b02db4)
- **Update previous Crystal release 1.20.2 (#16954)** (baf78be)
- **Extract `CRYSTAL_BOOTSTRAP_VERSION` in `bin/ci` (#16966)** (a81cd38)
- **Update `devenv.lock` (#16935)** (084d21d)
- **Update changelog script (#16946)** (24d832a)
- **Update GH Actions (#16944)** (16e6f20)
- **Use Crysbot token in `update-devenv` workflow to trigger CI (#16938)** (4bc624e)
- **Document null-termination on `String#to_unsafe` (#16869)** (6f515bc)
- **Refactor internal `Process` constructor to receive `Crystal::System::Process` (#16933)** (8eeb542)
- **Refactor whitespace branch in `Lexer#next_macro_token` [follow-up #16771] (#16776)** (d956792)
- **Improve wording in warning about doc generator without LibXML2 (#16926)** (d2ac9e3)
- **Make `Channel(T)` an `Iterator(T)` (#16916)** (dd0f6e7)
- **Update `devenv.lock` (#16819)** (94e029c)
- **Drop `format_binary` parameter `alternative` (#16912)** (2c6e918)
- **Expose `Path#kind` (#16917)** (0df2819)
- **Simplify `Sync::Mutex#synchronize` proc type constraints (#16904)** (6c6c9ef)
- **Standardize parsing of symbol and string array literals (#16748)** (a9cca95)
- **Replace `not_nil!` with `should_not(be_nil)` in spec suite (#16906)** (5d1e89a)
- **Refactor `Dir::Globber` to a struct with instance methods (#16899)** (aa45eb9)
- **Update GH Actions (#16836)** (943ab17)
- **Reapply "Refactor `Formatter` code for simplification" (#16885) [fixup #16744] (#16908)** (1a9e445)
- **Parse parens in type grammar into `Union#parens` (#16744)** (9faf49b)
- **Merge `release/1.20`@`1.20.1` into master** (73dbbfd)
- **Merge `release/1.19` into master** (bc789c6)
- **Update previous Crystal release 1.20.1 (#16901)** (35bf27a)

### Chore
- **Refactor: `Process#wait` on Windows (#17099)** (29af2a0)
- **Refactor: simplify read console (windows) (#17098)** (66d7a8f)
- **Refactor: dont parse but mmap ELF, Mach-O, PE files and some DWARF sections (#16939)** (1ea5da7)

_Recap by [Repo Wrapped](https://repowrapped.com/gh/crystal-lang/crystal?utm_source=github-action)._