Skip to content

Releases

IronRuby 4.0.5

Choose a tag to compare

@github-actions github-actions released this 11 Nov 09:35
a21b4ad

IronRuby 4.0.5 is the first release built for .NET 10 and .NET 11, and the first without .NET 8. .NET 8 reached the end of Microsoft support on 10 November 2026, and 4.0.4 was the last release for it. Each download now comes in two builds: one on .NET 10, an LTS release and the default download, which keeps the names earlier releases used, and one on .NET 11, named -net11-. Both carry their runtime, so neither needs .NET installed. On .NET 11.0.0, multiplying and dividing big Integers is several times slower than on .NET 10; most other code runs a few percent faster there. Apart from the move to the new runtimes, it has one fix, which .NET 11 made necessary: an Integer too large for .NET's BigInteger raises NoMemoryError on every runtime.

.NET 10 and .NET 11

  • .NET 8 is gone. The source builds for net10.0 and net11.0
    (IronRubyTargetFrameworks in Directory.Build.props), and the code that only .NET 8
    needed is removed (#198). A program that hosts IronRuby, or loads its assemblies, needs
    .NET 10 or later. Scripts run with the self-contained downloads are not affected: the
    downloads bring their own runtime.
  • Two downloads for each platform. The archives named as before,
    ironruby-4.0.5-<platform>, and the Windows installer are built on .NET 10 and carry the
    .NET 10 runtime. .NET 10 is supported until 14 November 2028
    (.NET support policy).
    The ironruby-4.0.5-net11-<platform> archives are the same IronRuby built on .NET 11
    and carry its runtime. Their launchers run the .NET 11 build. There is no .NET 11
    installer.
  • Why .NET 10 is the default. On .NET 11.0.0, BigInteger multiplication and division
    are 3 to 6 times slower than on .NET 10, in plain C# too: a 3,000-digit a * b takes
    176 µs instead of 37 µs. Code that works on big Integers runs slower on the .NET 11
    download; TruffleRuby's pidigits benchmark takes 3.3 times as long (#198).
  • Elsewhere, .NET 11 is a little faster (#198, Release builds measured side by side on
    Linux x64). Startup is about 5% shorter: ir -e 1 takes 430 ms instead of 456 ms, and
    require "json" 502 ms instead of 530 ms. TruffleRuby's bench/ (136 benchmarks) runs
    3.5% faster by geometric mean, and a 10-benchmark subset of ruby-bench 3.9% faster.
    AWFY is unchanged (+0.2%). Among the issue #89 micro-benchmarks, a raise rescued in
    place is 15% faster and Thread.new { }.join 17% faster, while is_a? is 25% slower.

Changed

  • No Integer can be wider than about 2**31 bits (#198). .NET's BigInteger holds at
    most 2**31 - 64 bits on .NET 9 and later. The 4.0.4 downloads ran on .NET 8, where
    1 << 2**31 built the Integer; on the 4.0.5 downloads it raises NoMemoryError, as
    CRuby does when an allocation fails.
  • On Windows, zlib runs on .NET 10's or .NET 11's zlib-ng (#198), the zlib inside
    .NET, where 4.0.4 ran on .NET 8's fork of zlib 1.2. Zlib::ZLIB_VERSION is
    "1.3.1.zlib-ng" instead of "1.2.13", and compressed bytes may differ from 4.0.4's.
    They inflate the same.

Fixed

  • Too-large Integers on .NET 11 raise NoMemoryError (#198). .NET 11's BigInteger
    shifts no longer check its maximum length, while its other operations still do
    (dotnet/runtime#137327). So on .NET 11
    1 << 2**31 succeeded, and the next operation on the result, such as x | 1, raised a
    raw System::OverflowException. IronRuby now checks the limit itself, in left shifts,
    Integer#**, right shifts by a negative count and on negative Integers, and raises
    NoMemoryError as it does on .NET 10.

For contributors

  • CI tests .NET 11 on every pull request and push, and .NET 10 before a release (#198).
    ci.yml runs net11.0 only on pull requests and pushes. net10.0 runs as well on a pull
    request from a release/* branch, on a run by hand (workflow_dispatch, tfms input:
    both, net10.0 or net11.0) and in release.yml when a v* tag is pushed. There,
    ci.yml's whole test set runs on both frameworks, and nothing is published unless it
    passes.
  • Util/package-release.sh takes the framework from IR_TFM (net10.0 by default). A
    net11.0 archive is named ironruby-<version>-net11-<rid>, and its launchers default to
    that build. release.yml packages every platform on both frameworks.
  • The startup library (Util/aot) is built for both frameworks (#198). A Linux Release
    build now installs IronRuby.Startup.dll in the net10.0 and the net11.0 ReadyToRun
    host. Before, it built for neither.
  • ir.sh, ironruby(.cmd), the Makefile, default.mspec and the Util scripts default to
    net10.0; IR_TFM=net11.0 picks the .NET 11 build.

Download

Self-contained: unpack one and run ./ironruby, ./iirb.sh and ./igem.sh - on Windows
ironruby.cmd, iirb.cmd and igem.cmd. No .NET to install. Or, on Windows, run the
installer.

On .NET 10 (LTS, the default):

  • Windows x64 installer: ironruby-4.0.5-win-x64-setup.exe, the zip below, installed
    into C:\IronRuby40-x64 and put on the PATH
  • Windows x64: ironruby-4.0.5-win-x64.zip, with Windows Forms, WPF, ironrubyw.exe
    and Samples\Notepad\notepad.cmd
  • Linux x64: ironruby-4.0.5-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.5-osx-arm64.tar.gz, built in CI, not tested there

On .NET 11:

  • Windows x64: ironruby-4.0.5-net11-win-x64.zip, with the same contents as the
    .NET 10 zip
  • Linux x64: ironruby-4.0.5-net11-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.5-net11-osx-arm64.tar.gz, built in CI, not tested there

SHA256SUMS lists the checksums of all of them. Each file and SHA256SUMS has a signed
build provenance attestation, which says which workflow built it, from which commit, in
which run:

gh attestation verify ironruby-4.0.5-net11-linux-x64.tar.gz --repo Largo/ironruby

What's Changed

  • Drop .NET 8, add .NET 11 by @Largo in #198
  • Release 4.0.5 by @Largo in #199
  • Release workflow: publish only the archives; retry the flaky macOS publish by @Largo in #200

Full Changelog: v4.0.4...v4.0.5

IronRuby 4.0.4

Choose a tag to compare

@github-actions github-actions released this 10 Nov 23:43
6db3960

IronRuby 4.0.4 is mostly about speed. Most of the performance gaps listed in #89 are closed or much narrowed across the core: exceptions, strings, Integers, Ranges, Arrays, Hashes, IO, Rational and Complex; the ones still open are listed at the end. ruby-bench's lobsters runs 31-38% faster and protoboeuf drops from 81 s to 1.3 s. A rescued exception costs a quarter of what it did, and copying a long String takes constant time. Startup is shorter, and the method JIT compiles more code. Deep recursion raises a rescuable SystemStackError instead of ending the process, and Ruby programs on Windows get 8 MB stacks. Ruby 4.0's Ractor API and CRuby 4.0's error reports are new. The release also fixes a long list of differences from CRuby, in JSON, BigDecimal, multibyte encodings, signals, threads and CLR interop. It is the last IronRuby release that supports .NET 8.

The last release for .NET 8

.NET 8 reached the end of Microsoft support on 10 November 2026
(.NET support policy).
IronRuby 4.0.4 is the last release that supports it:

  • What 4.0.4 ships: the 4.0.4 downloads are built for net8.0 and carry the .NET 8
    runtime with them, as every 4.0 release has. Microsoft no longer patches that runtime.
    The source still builds for both net8.0 and net10.0 (IronRubyTargetFrameworks in
    Directory.Build.props), and CI tests both.
  • From the next release, IronRuby targets .NET 10 only. The self-contained downloads
    will be built on .NET 10 and carry its runtime. The net8.0 target framework will be
    dropped from the build and from CI. A program that hosts IronRuby, or loads its
    assemblies, will need .NET 10. .NET 10 is an LTS release, supported until
    14 November 2028.

Nothing changes for scripts run with the self-contained downloads: they bring their own runtime.

Download

Self-contained: unpack one and run ./ironruby, ./iirb.sh and ./igem.sh - on Windows
ironruby.cmd, iirb.cmd and igem.cmd. No .NET to install. Or, on Windows, run the
installer.

  • Windows x64 installer: ironruby-4.0.4-win-x64-setup.exe, the zip below, installed
    into C:\IronRuby40-x64 and put on the PATH
  • Windows x64: ironruby-4.0.4-win-x64.zip, with Windows Forms, WPF, ironrubyw.exe
    and Samples\Notepad\notepad.cmd
  • Linux x64: ironruby-4.0.4-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.4-osx-arm64.tar.gz, built in CI, not tested there

SHA256SUMS lists the checksums. Each file and SHA256SUMS has a signed build
provenance attestation, which says which workflow built it, from which commit, in which run:

gh attestation verify ironruby-4.0.4-win-x64-setup.exe --repo Largo/ironruby

New

  • Ractor, with Ruby 4.0's API (#119). Ractors run on CLR threads. Each one isolates
    globals, class variables, class-level instance variables, constants that hold
    unshareable values, its own $stdout and $VERBOSE, and isolated procs. 146 of the 153
    checks in CRuby's bootstraptest/test_ractor.rb pass. A program that starts no Ractor
    pays nothing for these checks. Also new from Ruby 4.0: IO#timeout,
    Thread#set_trace_func, ObjectSpace.count_objects, GC.stat_heap,
    Enumerator::Producer and Process::Waiter.
  • Error reports as CRuby 4.0 prints them (#119). error_highlight is on by default.
    did_you_mean loads only when it is needed, and it suggests local variables too. A
    SyntaxError report says "syntax errors found" and shows prism's annotated snippet, and
    syntax_suggest is on. In every case checked, the report is byte for byte CRuby's.
  • File.link, File.symlink and File.readlink on Windows (#110), which raised
    NotImplementedError. They behave as CRuby's win32.c does. A directory target gets a
    directory link. Symlinks are created without admin rights where Windows allows it.
    readlink reads a symbolic link or a junction. File.symlink?, File.lstat(...).symlink?
    and File.ftype now recognise links on Windows.
  • The json gem's API (#108).
    • Parse options: allow_nan, allow_trailing_comma, decimal_class,
      object_class, array_class, create_additions, freeze and max_nesting.
    • Generate options: ascii_only, script_safe/escape_slash and allow_nan.
    • Methods: JSON.load of an IO, nil, "" or a proc; unsafe_load,
      load_file(!), parse!, Kernel#JSON, j, jj and JSON::NestingError.
      json/add/symbol works.
  • BigDecimal methods from bigdecimal 4 (#109): scale, precision_scale,
    n_significant_digits, save_rounding_mode, save_exception_mode and save_limit.
  • Integers wider than 2**31 bits on .NET 8 (#171, #188). 1 << 2**31 now builds the
    Integer, as CRuby does; IronRuby used to raise RangeError. 2 ** (2**31) now computes
    in 4.5 s; it raised ArgumentError, and CRuby takes 91 s. Right shifts and
    Integer#[] reach bits past index 2**31. On .NET 9 and later, a BigInteger stops at
    about 2**31 bits. There these operations raise NoMemoryError, as CRuby does when an
    allocation fails, instead of a CLR OverflowException.
  • Two opt-in fast starts for source builds on Linux (#76). Neither does anything unless
    you ask for it.
    • IR_CONFIG=R2R IR_SERVER=start ./ir.sh starts a pool of processes that are already
      initialized, and IR_SERVER=1 ./ir.sh ... runs a program in one of them. ir -e 1
      then takes about 0.016 s instead of about 0.76 s. A program the pool cannot run
      exactly as a fresh process would runs cold instead.
    • A NativeAOT build (-p:IronRubyNativeAot=true) starts in about 0.48 s. It only
      interprets, and it can call only the CLR types kept in the image.

Changed

  • A CLR exception that derives from System.Exception directly is a StandardError
    (#73). A custom C# exception (class MyAppException : Exception), AggregateException
    and ApplicationException used to get past rescue => e and x rescue y, although an
    InvalidOperationException was caught. System::Exception itself is still Ruby's
    Exception. A bare rescue now also catches an AggregateException or
    TargetInvocationException that wraps a SystemExit or Interrupt.
  • Rational and Complex are written in C# (#120, #121). Each is a frozen CLR type with
    two fields, and #instance_variables is empty, as in CRuby. Arithmetic, comparison,
    #hash, #to_f, Kernel#Rational and Kernel#Complex follow rational.c and
    complex.c for Integer and Float operands. Other operands still go through Ruby code,
    so coercion happens in the same order as before. The speed-up is under Performance.
  • On Windows, a Ruby program and its threads get 8 MB stacks (#154). Windows gives a
    main thread 1 MB, so recursion went about a seventh as deep as in CRuby. ir now runs
    the program on an 8 MB STA thread, and Thread.new threads get 8 MB on every platform.
    A JIT-compiled method on the Windows main thread now recurses 17,247 levels deep instead
    of 1,586; CRuby 4.0.5 manages 10,916.
  • Signal.list on Windows is CRuby's (#162). It used to list all 33 Linux signals.
    It now lists the eight the C runtime has: EXIT, INT, ILL, ABRT, FPE, KILL, SEGV and TERM.
    Other signals raise CRuby's errors: trap(:HUP) is an ArgumentError: unsupported signal, and Process.kill(1, pid) is Errno::EINVAL.
  • CLR calls that cannot bind name the conversions that would have worked (#74, #155).
    • System::Math.abs(nil) says no implicit conversion of nil into Integer or Float,
      not ... into System::SByte.
    • A call that no overload can take raises a TypeError instead of
      AmbiguousMatchException.
    • A type argument that breaks a generic constraint raises an ArgumentError that names
      the constraint.
    • Generic overloads tie-break as in C#, so LINQ's max and min with a Func
      selector bind.
    • An argument with only one of the possible conversions picks that overload:
      StringBuilder.new(Rational(5, 2)) takes the capacity constructor.
  • BasicObject#equal? is identity, apart from #== (#122). Before, redefining ==
    changed equal? too. Integers, Floats, true and false still compare by value.
  • instance_exec and block instance_eval no longer make a singleton class (#75). CRuby
    has made one only when a def needs it since 3.2. A NoMethodError on such an object
    says "an instance of C", and #clone no longer copies an empty singleton class.
  • Hash#fetch, Monitor, Comparable#clamp, Array#hash and Hash#hash are C#, as in
    CRuby's core
    (#75, #94). Hash#fetch no longer calls a subclass's #[] or #key?.
    Monitor is owned per fiber. MonitorMixin::ConditionVariable#wait returns false on
    timeout. Marshal.dump(Monitor.new) raises TypeError.
  • Method#arity and #parameters match CRuby for all but 46 of 2,111 core methods
    (#115, #119). 41 of those 46 are in Set. Arity errors for methods with keywords use
    CRuby's wording.
  • In a host's scope, a top-level def is also a private method of Object (#174, #179),
    as in CRuby. The same holds for top-level alias, undef, public/private with names,
    and main.define_method. Before, these acted only on the scope's main object, so a class
    calling such a method raised NameError. def self.x on main is labelled x in
    backtraces, as in CRuby.
  • Long ASCII Strings hash differently (#195). A String of 128 or more ASCII characters
    now hashes its bytes, so its #hash value is not the one 4.0.3 gave. For such strings,
    MutableString.GetHashCode() no longer equals System.String.GetHashCode(); a C# host
    that uses both as keys of one .NET dictionary will see the difference.
  • 1.8/1.9-era features are gone (#119). Taint, untrust, $SAFE and -save/-load
    are removed. About 55 prelude constants are gone, and so are the internal instance
    variables of Set, ...
Read more

IronRuby 4.0.3

Choose a tag to compare

@github-actions github-actions released this 30 Oct 10:04
0695d9a

IronRuby 4.0.3 comes with a Windows installer, and its irb works on Windows as CRuby's
does: it starts, completes with TypeCompletor, shows colours in a classic console window
and writes non-ASCII text as written. ironruby at a terminal starts irb. Calling .NET gains
using System::Linq, which brings CLR extension methods into one file as C#'s using
directive does, and DLLs required by path find the DLLs they reference. A refinement no
longer slows down the calls it cannot change, and error messages quote names 'like this',
as CRuby 4.0's do.

Download

Self-contained: unpack one and run ./ironruby, ./iirb.sh and ./igem.sh - on Windows
ironruby.cmd, iirb.cmd and igem.cmd. No .NET to install. Or, on Windows, run the
installer.

  • Windows x64 installer: ironruby-4.0.3-win-x64-setup.exe, the zip below, installed
    into C:\IronRuby40-x64 and put on the PATH
  • Windows x64: ironruby-4.0.3-win-x64.zip, with Windows Forms, WPF, ironrubyw.exe
    and Samples\Notepad\notepad.cmd
  • Linux x64: ironruby-4.0.3-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.3-osx-arm64.tar.gz, built in CI, not tested there

SHA256SUMS lists the checksums. Each file and SHA256SUMS has a signed build
provenance attestation, which says which workflow built it, from which commit, in which run:

gh attestation verify ironruby-4.0.3-win-x64-setup.exe --repo Largo/ironruby

New

  • A Windows installer, in the style of RubyInstaller. It installs the win-x64 zip's
    tree, unchanged, into C:\IronRuby40-x64 by default, or a directory you choose, for you
    alone (no admin rights) or for all users, and puts that directory first on the PATH, so
    ironruby, ir, iirb and igem work from a new terminal, while irb and gem stay
    CRuby's. igem install writes into
    the install tree, which is why the default is a directory you can write to and has no
    space in its path: Bundler's RUBYOPT, the Rails templates and mspec break on one.
    Running .rb files with IronRuby is an option, off by default. The uninstaller removes
    the files, the gems installed since, and the PATH entry. It is built in CI with Inno
    Setup 6.7.3 from Util/installer/ironruby.iss, and installed, run and uninstalled there
    before it is published.

  • irb completes as CRuby's does (#68). irb's default completor on Ruby 3.4 and later is
    TypeCompletor, from the bundled gem repl_type_completor. IronRuby did not ship it, so
    irb fell back to RegexpCompletor without a word and offered other candidates, in
    another order. IronRuby now ships repl_type_completor 0.1.16 and rbs 4.0.0.dev.5, the
    rbs release IronRuby's rbs extension is built from; both come from rubygems.org, each
    pinned by SHA-256. CRuby 4.0.9 bundles repl_type_completor 0.1.12 and rbs 3.10.0, but
    repl_type_completor before 0.1.14 does not accept rbs 4. The candidates for Stri,
    1.ti, "abc".up and [1,2].ma are CRuby's.

  • irb 1.18.0, with its startup banner (#70). irb 1.18 opens with a small Ruby logo, a
    line naming irb and the Ruby, a tip and the current directory; CRuby shows it once irb
    1.18 is installed over the 1.16.0 it bundles. On IronRuby the line names the interpreter,
    as RUBY_DESCRIPTION does: IRB v1.18.0 - IronRuby 4.0.3 (4.0.0). irb 1.18 finds open
    nestings with Prism instead of Ripper; reline stays at 0.6.3, which irb 1.18 accepts.

  • using System::Linq (#50, #60). using_clr_extensions System::Linq turns LINQ's
    extension methods on for every call in the runtime, so a gem that calls it changes what
    list.select means in every other file. using now also takes a CLR namespace and brings
    its extension methods into the rest of the file, class body or eval string - where a
    refinement would be active - as C# brings them into the files that say
    using System.Linq;. using System::Linq::Enumerable brings in one static class's, as
    C#'s using static does. Inside that scope a call resolves as it does under
    using_clr_extensions, so moving code from one form to the other means changing only
    the using line:

    using System::Linq
    list = System::Collections::Generic::List[Integer].new([3, 1, 2])
    list.where { it > 1 }.order_by { -it }.to_a   # => [3, 2]

    The 101 LINQ samples run in CI and print their expected output.

  • More gems with C extensions (#47). As JRuby does, IronRuby leaves the installed gem's
    Ruby code as it is and provides only the extension: markly and rbs with the gems' own C
    libraries, built from pinned sources and giving CRuby's output byte for byte; strptime,
    yajl-ruby, zstd-ruby and cool.io ported to C#. pty is new in the standard library, and
    sqlite3 has SQLite3::Backup. With them, 34 of ruby-bench's 36 macro benchmarks run,
    instead of 20; lobsters, shipit, fluentd and ruby-lsp run for the first time.

Changed

  • ironruby at a terminal starts irb, as python starts its interactive interpreter:
    with no script and no -e, and stdin a terminal, ironruby is iirb. From a pipe or a
    file it still reads the program from stdin, as ruby does, and so do ironruby -,
    -n, -p, -c and -x.
  • No more irb.cmd and irb.sh; IronRuby's irb is iirb. On a PATH, irb is CRuby's;
    ironruby -S irb still runs IronRuby's.
  • IronRuby no longer uses a CRuby's gems. It used to offer the gem directory of a CRuby
    4.0 found on the PATH for third-party gems. That loaded CRuby's code into IronRuby: with
    CRuby on the PATH, igem install loaded CRuby's rdoc plugin over the rdoc IronRuby ships
    ("already initialized constant RDoc::VERSION") and then failed generating the gem's
    documentation. IronRuby now reads only its own gem directories; a gem it needs is
    installed for it, with igem install or Bundler. IRONRUBY_NO_HOST_GEMS is gone with it.
  • igem install builds no documentation unless asked, as on TruffleRuby: generating ri
    and rdoc takes longer than installing most gems. igem install --document (or
    gem: --document in ~/.gemrc) builds it with the rdoc IronRuby ships, and uninstalling
    the gem removes it again.
  • Error messages quote names 'like this' (#62), as CRuby has since 3.4:
    undefined method 'foo' for an instance of Integer, where IronRuby still wrote
    `foo'. IronRuby's own messages, about CLR interop or command-line options, use
    straight quotes too. Some messages also got CRuby's wording: super with no superclass
    method names its receiver and sets NoMethodError#name and #receiver, and an ndigits
    too large for round and its kin gets CRuby's "too big to convert" text. 89 messages are
    checked against CRuby 4.0.7's.
  • Mutex, Queue, SizedQueue and ConditionVariable are Thread::Mutex and so on
    (#44), as in CRuby. They were defined at the top level and aliased into Thread, so
    Mutex.name, #inspect and the error messages naming the class said Mutex. The
    top-level names are now the aliases, as in CRuby, and still name the same classes.
  • using_clr_extensions warns that it is deprecated (#50, #60), once per runtime, and
    names the using line to write instead. It still works as before.
  • The bundled gems are CRuby 4.0.9's, except repl_type_completor and rbs (above) and
    irb 1.18.0, which is newer than the irb CRuby 4.0.9 bundles.

Fixes

  • irb starts on Windows again. In 4.0.2 it stopped at once with unknown symbol "FillConsoleOutputCharacter". reline asks Fiddle for Win32 functions by their bare
    names, and Fiddle now also looks for the A export, as CRuby's does. In a console, irb
    then crashed: reline hands the console API its buffers as [str].pack("p"), and on
    IronRuby that was an index, not an address. It is a real address now, of a block holding
    the String's bytes, and what C writes there through Fiddle comes back into the String, as
    with CRuby - so reline runs as Ruby ships it.
  • irb shows results on Windows. After the first result it stopped with
    Errno::ENOTTY from IO#winsize: IronRuby's io/console asked only termios for the
    terminal size, which Windows does not have. It now asks the console, as CRuby does, and
    raises Errno::EBADF off a console, as CRuby does on Windows.
  • require 'ripper' gives Ripper::Filter, as in CRuby. rdoc's Ruby parser subclasses
    it, and generating a gem's documentation failed with uninitialized constant Ripper::Filter.
  • irb starts about a quarter of a second sooner. tmpdir.rb, which irb loads, does
    require 'etc.so'; IronRuby had no such file, so the require failed, after RubyGems had
    searched every installed gem for it. A C extension required by its library name now loads
    IronRuby's implementation of it (etc.rb), as JRuby loads its own; Dir.tmpdir's system
    candidate is then the Windows temporary folder rather than /tmp, and Etc.systmpdir
    answers as CRuby's does. Every require also skipped a regular expression that only an
    assembly name can match. IRONRUBY_STARTUP_TRACE=1 shows where a process's startup goes.
  • irb's colours show in a classic console window (#68). CRuby turns on
    ENABLE_VIRTUAL_TERMINAL_PROCESSING for a console it writes to; IronRuby did not, so in a
    classic conhost window irb's colours and reline's cursor movements came out as literal
    escape sequences. IronRuby now sets the flag on stdout and stderr when they are a console.
  • Text outside ASCII shows in the Windows console as written (#70). $stdout and
    $stderr handed Ruby's UTF-8 bytes to the console, which read them in its output code
    page, 850 or 437 on most machines: "ä" came out as two characters. As CRuby does,
    IronRuby now writes to a console with WriteConsoleW, decoding the bytes as UTF-8; a
    character split across two writes waits for its last byte. Redirected to a file or a
    pipe, the bytes go out unchanged, as before.
  • ConditionVariable#wait (#42). A wait that raised `...
Read more

IronRuby 4.0.2

Choose a tag to compare

@github-actions github-actions released this 28 Oct 14:14
99711fd

IronRuby 4.0.2 runs a Rails 8.1 app with SQLite on Windows, is about 1.2 times as fast
across IronRuby's micro benchmarks and starts in 1.25 s instead of 1.86 s, serves TLS through
net/http and Puma, and calls .NET the way Ruby 4 code is written. The legacy parser and the
Ruby 1.9 library are gone. The interpreter is now called ironruby, as JRuby's is jruby,
and every download comes with a signed build provenance attestation.

Download

Self-contained: unpack one and run ./ironruby, ./irb.sh and ./igem.sh - on Windows
ironruby.cmd, irb.cmd and igem.cmd. No .NET to install. ir.sh and ir.cmd still
work.

  • Windows x64: ironruby-4.0.2-win-x64.zip, with Windows Forms, WPF, ironrubyw.exe
    and Samples\Notepad\notepad.cmd
  • Linux x64: ironruby-4.0.2-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.2-osx-arm64.tar.gz, built in CI, not tested there

SHA256SUMS lists the checksums. Each archive and SHA256SUMS has a signed build
provenance attestation, which says which workflow built it, from which commit, in which run:

gh attestation verify ironruby-4.0.2-linux-x64.tar.gz --repo Largo/ironruby

New

  • Rails 8.1 with SQLite on Windows (#34). gem install rails, rails new,
    bundle install, a scaffold, migrations, importmap with Turbo and Stimulus, and
    bin/rails server on Puma and sqlite3, as a Windows user would run them. It took
    File#flock on Windows, IO readiness without libc, Bundler's platforms: for IronRuby,
    binstubs that start IronRuby, and a dozen more fixes, listed in
    Docs/rails-on-windows.md.
    In a sweep of popular gems on Windows, 81 give the same output as CRuby byte for byte,
    among them rubocop, standard, rspec, pry, prawn, sprockets and listen.
  • Faster (#22). IronRuby's 50 micro benchmarks run in 11.2 s instead of 26.1 s (geometric
    mean 1.21x): switching fibers is 7.1x as fast, raise/rescue 5.5x, keyword arguments
    about 9x, near CRuby's time. ironruby -e 1 starts in about 1.25 s instead of 1.86 s.
  • TLS (#28, #32, #33). OpenSSL::SSL::SSLSocket is non-blocking, so net/http's open,
    read and write timeouts work unmodified, for RubyGems too; certificates are verified
    against the context's CAs, with verify_callback. Puma serves ssl://.
  • Calling .NET (#26, #31, #25). Keyword arguments bind to parameters by name, a block
    goes to the trailing delegate parameter (list.Sort { |a, b| b <=> a }, Task.Run { }),
    and the split .NET libraries load on demand, so System::Console just works. super in
    initialize runs the .NET base constructor. Stores into a boxed struct's field stick,
    zlib works on Windows, and so do Process.kill and File::NULL.
  • Ruby 4.0 (#23, #30). Many core classes now behave as CRuby 4.0's, found by running
    IronRuby and CRuby side by side and by ruby/spec. Rational and Complex are ports of
    CRuby 4.0's, and Pathname is CRuby 4.0's own.
  • prism 2.0 (#27). IronRuby follows ruby/prism's new serialization, and deeply nested
    code runs instead of overflowing the stack.

Changed

  • The interpreter is ironruby (#35), and so is RbConfig's ruby_install_name: the
    binstubs Bundler and Rails write start #!/usr/bin/env ironruby, a line Ruby runs as
    Ruby. ir, ir.sh and ir.cmd stay as its short name. On Windows, ironrubyw.exe is
    the same interpreter without a console window, as rubyw.exe is CRuby's; the Notepad
    sample starts with it.
  • ironruby with no script reads the program from stdin (#35), as ruby does, at a terminal
    too, and $0 is "-". It used to start the DLR's interactive console; irb is irb or
    iirb.
  • Prism is the only parser (#34). -X:UsePrism is still accepted and does nothing.
  • Gems written for prism 1.x or bigdecimal 2.x and 3.x activate with the built-in
    prism 2.0 and bigdecimal 4.0 (#34): rubocop, standard, minitest 6 and prawn among them.
  • Windows: file names, ENV, ARGV and the default external encoding are UTF-8, as in
    CRuby; Dir.pwd keeps a short 8.3 path as it was given; Dir.home uses /; local time
    follows daylight saving time (#19).
  • The Ruby 1.9 library is removed (#29, #30), including its cgi code with known
    vulnerabilities and a win32/sspi that wrote past its buffers on 64-bit Windows.

Security and auditing

  • Signed build provenance for every published file, made by GitHub's actions/attest in
    the job that built it (#36).
  • The repository holds no programs any more: 18 test fixtures and sample DLLs from 2016,
    which nothing built or shipped, are gone, and CI fails if one comes back (#36). The
    upstream checkouts the build uses are pinned (#29).

Thanks

@khasinski for File#flock on macOS (#17) and for
ir -S <gem executable> finding RubyGems' binstubs (#18).

Known limits

  • The release targets .NET 8, whose support ends on 10 November 2026.
  • macOS is built, not tested. The full status is in the
    README.

What's Changed

  • prism: follow ruby/prism cd76b0d1 (attach_comments) - fixes red CI by @Largo in #21
  • Time: follow daylight saving time on Windows by @Largo in #19
  • ir.cmd: put RubyGems' bindir on RUBYPATH, so ir -S <gem executable> finds its binstub by @Largo in #20
  • File#flock: offer flock(2) on macOS, where the rest of Posix is not by @khasinski in #17
  • ir.sh: put RubyGems' bindir on RUBYPATH, so ir -S <gem executable> finds its binstub by @khasinski in #18
  • Speedup: method JIT, calls, blocks, exceptions and library fast paths by @Largo in #22
  • Align IronRuby with Ruby 4.0 behavior: core class fixes, CI prism pin, loader fix by @Largo in #23
  • Windows and CLR interop fixes: boxed struct fields, zlib, File::NULL, Process.kill, JSON control characters by @Largo in #25
  • Test: a symbol in a prism-skimmed method body by @Largo in #24
  • prism: follow ruby/prism 30a25553 (post-order serialization); run deeply nested code by @Largo in #27
  • Dependency audit: pin upstream checkouts, drop obsolete and vulnerable 1.9-era code by @Largo in #29
  • net/http over TLS: non-blocking SSLSocket, timeouts, and the context's CAs by @Largo in #28
  • Replace the Ruby 1.9 library tree with Ruby 4.0 implementations by @Largo in #30
  • CLR interop gaps: super into CLR constructors, CLR constants, strings for Object parameters by @Largo in #31
  • CLR interop for modern Ruby: keywords, blocks and delegates, pattern matching, on-demand BCL loading by @Largo in #26
  • puma: serve TLS - Puma::MiniSSL::Engine on SslStream by @Largo in #32
  • SSLSocket#write_nonblock: hand over up to 1 MB, convert only that (flaky NetHttp_Tls1) by @Largo in #33
  • Remove the legacy parser; run Rails 8.1 + SQLite and popular gems on Windows by @Largo in #34
  • Call the interpreter ironruby, as JRuby's is jruby; ir stays its short name by @Largo in #35
  • Release: signed build provenance for every published file by @Largo in #36
  • IronRuby 4.0.2 by @Largo in #37

New Contributors

Full Changelog: v4.0.1...v4.0.2

IronRuby 4.0.1

Choose a tag to compare

@github-actions github-actions released this 02 Oct 08:07
1672d83

IronRuby 4.0.1 fixes pipes and sockets on macOS, where Puma could not start,
IO#write_nonblock on sockets, which cut large responses short, and a SQLite crash on
Linux. All of them were found by @rubys while serving Rails
apps that Roundhouse transpiles to plain Ruby.

Download

Self-contained: unpack one and run ir.sh / ir.cmd, irb, igem. No .NET to install.

  • Windows x64: ironruby-4.0.1-win-x64.zip, with Windows Forms, WPF and
    Samples\Notepad\notepad.cmd
  • Linux x64: ironruby-4.0.1-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.1-osx-arm64.tar.gz

SHA256SUMS lists the checksums.

Fixes

  • Pipes to child processes work on macOS (#12). Backticks, %x(), IO.popen and
    Open3 failed with Errno::EINVAL: IronRuby passed Linux's value of O_CLOEXEC to
    pipe2, and macOS numbers the flag differently. On macOS, core/io/pipe_spec,
    core/kernel/backtick_spec and library/open3 now pass.
  • Socket addresses on macOS and the BSDs (#13). Every address the kernel returned
    (getsockname, accept, recvfrom) raised unknown address family: 528, because a BSD
    sockaddr starts with a length byte; Puma could not bind. On macOS, ruby/spec
    library/socket errors fall from 838 to 178.
  • IO#write_nonblock on a socket returns what the kernel took (#14). It claimed the
    whole string even when the kernel accepted only part of it, and the rest was lost: Puma
    responses larger than the socket's send buffer arrived truncated, on Linux and macOS.
    CI now checks that what write_nonblock claims is what the peer receives, on Linux and
    Windows (#15); Winsock takes a non-blocking send whole or refuses it, so Windows did not
    lose bytes.
  • SQLite no longer crashes on Linux once another library has loaded the system SQLite
    (SQLitePCL.raw#682), libvips
    through ruby-vips for one. SQLitePCLRaw's libe_sqlite3.so is linked without
    -Bsymbolic, so its calls into itself could bind to the other copy, and
    SQLite3::Database.new segfaulted. The Linux archive now carries a libe_sqlite3.so
    built from the same SQLite 3.53.3 with the same compile options, linked -Bsymbolic.
    The release build checks that SQLite reports the same version and options from both, and
    that the rebuilt one still answers with the system's libsqlite3 preloaded. Windows and
    macOS were not affected.

Linux and Windows behave as in 4.0.0 apart from #14. The full status is in the
README.

Also new

  • Issues are open.
  • The launch video
    has music now, and plays inline in the README as a teaser.

Music in the launch video: Edvard Grieg, In the Hall of the Mountain King, played by the
Czech National Symphony Orchestra for Musopen; public domain, from
classicals.de.

What's Changed

  • README: the launch video plays inline by @Largo in #10
  • Launch video: In the Hall of the Mountain King by @Largo in #11
  • IO#write_nonblock on a socket returns what the kernel took by @rubys in #14
  • Socket: read a packed sockaddr's family where macOS and the BSDs keep it by @rubys in #13
  • Process: O_CLOEXEC is 0x1000000 on macOS, so pipes to a child open there by @rubys in #12
  • CI: write_nonblock on a socket claims only what the peer receives (#14) by @Largo in #15
  • IronRuby 4.0.1 by @Largo in #16

New Contributors

  • @rubys made their first contribution in #14

Full Changelog: v4.0.0...v4.0.1

IronRuby 4.0.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 22:00
00b5e2a

IronRuby is back: Ruby 4.0 on .NET 8 and 10. The last release of IronRuby was 1.1.3,
for Ruby 1.9.2 on .NET Framework 4, in 2011. 4.0.0 implements Ruby 4.0, parses it with
prism (CRuby's own parser), and runs on Linux, Windows and
macOS.

IronRuby 4.0, the 55-second launch video

Download

The archives below are self-contained: unpack one and run ir.sh / ir.cmd, irb,
igem. No .NET to install.

  • Windows x64: ironruby-4.0.0-win-x64.zip, with Windows Forms, WPF and
    Samples\Notepad\notepad.cmd, a Windows Notepad written in Ruby
  • Linux x64: ironruby-4.0.0-linux-x64.tar.gz
  • macOS arm64: ironruby-4.0.0-osx-arm64.tar.gz (untested)

SHA256SUMS lists the checksums; ironruby-4-launch.mp4 is the launch video.

What is in it

  • Ruby 4.0 syntax, read by prism: pattern matching, endless methods, it, keyword
    arguments, ... forwarding. prism's syntax tree is decoded by a generated C# loader
    (152 node classes) and lowered onto IronRuby's AST and the DLR.
  • ruby/spec at CRuby 4.0.6: spec/language 2,934 examples and spec/library 6,398,
    both with 0 failures; spec/command_line and spec/security at 0 as well; spec/core
    21 of 23,136, 20 of them ObjectSpace.each_object.
  • A method JIT and OSR, on by default, specializing on the types a program uses:
    integer and float loops, fib and mandelbrot run in 0.27–0.74× CRuby's time. The
    geomean over all 50 benchmarks is 3.25×: method calls, strings and arrays are 2–4×, and
    raise and fibers are far behind.
  • irb 1.16.0 and reline 0.6.3, the ones CRuby 4.0 ships, with highlighting, completion
    and history. RubyGems 4.0.16 and Bundler, installing over real TLS. Ruby 4.0's standard
    library and its pure-Ruby bundled gems ship in the box.
  • Rails 8.1 boots and serves requests through Rack, with nokogiri, a C extension,
    stubbed; ActiveRecord has no adapter yet, as sqlite3, pg and mysql2 are native.
  • .NET is right there: require "System.Windows.Forms" or "PresentationFramework".
    Samples/Notepad is
    Windows Notepad in 1,365 lines of Ruby, with a test that drives it in CI.
  • irubyc packages a Ruby program as an application, as one executable
    (--single-file), or as a plugin DLL a .NET host loads (--library).

Not yet

zlib, Win32OLE and readline on Windows, C extensions in general (no nokogiri, no
database drivers), and macOS is built but untested. The
README has the full status.

Thanks to everyone who built IronRuby at Microsoft and in IronLanguages, and to the prism
and ruby/spec projects, without which none of this would be measurable.

Music in the launch video: Edvard Grieg, In the Hall of the Mountain King, played by the
Czech National Symphony Orchestra for Musopen; public domain, from
classicals.de.

What's Changed

  • A Ruby string prefers System::String over System::Byte[] in overload resolution by @Largo in #4
  • A Ruby string prefers System::String over System::Boolean in overload resolution by @Largo in #5
  • Clear the CI build warnings (142 compiler warnings, NuGet, Node 20) by @Largo in #6
  • Time: a zone name loaded from a dump is dumped again and printed by %Z by @Largo in #7
  • Windows Forms and WPF on .NET 8: ship the Windows Desktop runtime by @Largo in #3
  • Samples/Notepad: Windows Notepad in Ruby, on Windows Forms, with a test CI runs by @Largo in #8
  • IronRuby 4.0.0: version, downloads, social card and launch video by @Largo in #9

Full Changelog: v4.0.0-preview1...v4.0.0

IronRuby 4.0.0-preview1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 30 Sep 08:51
4be4022

What's Changed

  • Binary releases: self-contained archives for Linux, Windows and macOS by @Largo in #1
  • IronRuby 4.0: the version follows the Ruby version it implements by @Largo in #2

New Contributors

  • @Largo made their first contribution in #1

Full Changelog: https://github.com/Largo/ironruby/commits/v4.0.0-preview1