Вышел Ruby 3.2.0
Опубликовал naruse 25-12-2022
Перевел: ablzh
Мы рады сообщить о выпуске Ruby 3.2.0. В Ruby 3.2 добавлено множество новых функций и улучшений производительности.
Поддержка WebAssembly на базе WASI
Это начальный порт поддержки WebAssembly на базе WASI. Он позволяет использовать бинарный файл CRuby в веб-браузере, в среде Serverless Edge или других типах встраиваемых систем WebAssembly/WASI. В настоящее время этот порт проходит базовые и загрузочные (bootstrap) наборы тестов без использования Thread API.

История вопроса
WebAssembly (Wasm) изначально был представлен для безопасного и быстрого запуска программ в веб-браузере. Но его цель — эффективное и безопасное выполнение программ в различных средах — давно востребована не только для веба, но и для обычных приложений.
WASI (The WebAssembly System Interface) разработан для таких случаев использования. Хотя таким приложениям необходимо взаимодействовать с операционными системами, WebAssembly работает на виртуальной машине, у которой не было системного интерфейса. WASI стандартизирует его.
Поддержка WebAssembly/WASI в Ruby призвана задействовать эти проекты. Она позволяет Ruby-разработчикам писать приложения, которые работают на этих перспективных платформах.
Варианты использования
Эта поддержка побуждает разработчиков использовать CRuby в среде WebAssembly. Примером использования является поддержка CRuby в песочнице TryRuby. Теперь вы можете попробовать настоящий CRuby прямо в своем веб-браузере.
Технические подробности
В современных WASI и самом WebAssembly отсутствуют некоторые функции для реализации Fiber, исключений и GC, так как они все еще развиваются, а также по соображениям безопасности. Поэтому CRuby восполняет этот пробел, используя Asyncify — технику преобразования бинарных файлов для управления выполнением в пространстве пользователя.
Кроме того, мы создали VFS поверх WASI, чтобы можно было легко упаковывать приложения Ruby в один файл .wasm. Это немного упрощает распространение Ruby-приложений.
Полезные ссылки
Готовый к промышленной эксплуатации YJIT

- YJIT больше не является экспериментальным
- Он тестировался на рабочих нагрузках в течение года и доказал свою стабильность.
- YJIT теперь поддерживает процессоры x86-64 и arm64/aarch64 на Linux, MacOS, BSD и других UNIX-платформах.
- В этот релиз вошла поддержка Apple M1/M2, AWS Graviton, Raspberry Pi 4 и других.
- Для сборки YJIT теперь требуется Rust 1.58.0+. [Feature #18481]
- Чтобы гарантировать, что CRuby собран с YJIT, пожалуйста, установите
rustc>= 1.58.0 перед запуском скрипта./configure. - Пожалуйста, свяжитесь с командой YJIT, если у вас возникнут какие-либо проблемы.
- Чтобы гарантировать, что CRuby собран с YJIT, пожалуйста, установите
- Релиз YJIT 3.2 быстрее, чем 3.1, и имеет примерно на треть меньше накладных расходов на память.
- В целом YJIT на 41% быстрее (среднее геометрическое), чем интерпретатор Ruby на yjit-bench.
- Физическая память для JIT-кода выделяется лениво. В отличие от Ruby 3.1, RSS процесса Ruby минимизирован, так как страницы виртуальной памяти, выделенные через
--yjit-exec-mem-size, не будут отображаться на физические страницы памяти до тех пор, пока они действительно не будут использованы JIT-кодом. - Представлен Code GC, который освобождает все кодовые страницы, когда потребление памяти JIT-кодом достигает значения
--yjit-exec-mem-size. RubyVM::YJIT.runtime_statsвозвращает метрики Code GC в дополнение к существующим ключамinline_code_sizeиoutlined_code_size:code_gc_count,live_page_count,freed_page_countиfreed_code_size.
- Большинство статистических данных, генерируемых
RubyVM::YJIT.runtime_stats, теперь доступны в релизных сборках.- Просто запустите ruby с параметром
--yjit-stats, чтобы вычислить и вывести статистику (это влечет за собой небольшие накладные расходы во время выполнения).
- Просто запустите ruby с параметром
- YJIT теперь оптимизирован для использования форм объектов (object shapes). [Feature #18776]
- Используется более мелкозернистая инвалидация констант, чтобы инвалидировать меньше кода при определении новых констант. [Feature #18589]
- Значение по умолчанию для
--yjit-exec-mem-sizeизменено на 64 (МиБ). - Значение по умолчанию для
--yjit-call-thresholdизменено на 30.
Улучшения Regexp для защиты от ReDoS
Известно, что сопоставление с регулярным выражением может занимать неожиданно много времени. Если ваш код пытается сопоставить потенциально неэффективное регулярное выражение с ненадежными входными данными, злоумышленник может использовать это для организации отказа в обслуживании (так называемый Regular expression DoS, или ReDoS).
Мы представили два улучшения, которые значительно снижают риск ReDoS.
Улучшенный алгоритм сопоставления регулярных выражений
Начиная с Ruby 3.2, алгоритм сопоставления Regexp был значительно улучшен благодаря использованию техники мемоизации.
# Это сопоставление занимает 10 сек. в Ruby 3.1 и 0.003 сек. в Ruby 3.2
/^a*b?a*$/ =~ "a" * 50000 + "x"

Улучшенный алгоритм сопоставления позволяет выполнять большинство проверок регулярных выражений (около 90% в наших экспериментах) за линейное время.
Эта оптимизация может потреблять память, пропорциональную длине входных данных для каждого сопоставления. Мы не ожидаем возникновения практических проблем, так как это выделение памяти обычно откладывается, а обычное сопоставление Regexp должно потреблять не более чем в 10 раз больше памяти, чем длина входных данных. Если в реальном приложении у вас закончится память при сопоставлении регулярных выражений, пожалуйста, сообщите об этом.
Оригинальное предложение: https://bugs.ruby-lang.org/issues/19104
Таймаут Regexp
Вышеупомянутая оптимизация не может быть применена к некоторым типам регулярных выражений, например, содержащим расширенные функции (такие как обратные ссылки или просмотры вперед/назад) или с огромным фиксированным количеством повторений. В качестве резервной меры также введена функция таймаута для сопоставлений Regexp.
Regexp.timeout = 1.0
/^a*b?a*()\1$/ =~ "a" * 50000 + "x"
#=> Через одну секунду будет вызвано исключение Regexp::TimeoutError
Обратите внимание, что Regexp.timeout — это глобальная настройка. Если вы хотите использовать разные настройки таймаута для определенных регулярных выражений, вы можете использовать ключевое слово timeout в Regexp.new.
Regexp.timeout = 1.0
# Это регулярное выражение не имеет таймаута
long_time_re = Regexp.new('^a*b?a*()\1$', timeout: Float::INFINITY)
long_time_re =~ "a" * 50000 + "x" # никогда не прерывается
Оригинальное предложение: https://bugs.ruby-lang.org/issues/17837.
Другие заметные новые функции
SyntaxSuggest
-
Функция
syntax_suggest(ранееdead_end) интегрирована в Ruby. Она помогает найти местоположение ошибок, таких как отсутствующие или лишниеend, чтобы вы могли быстрее вернуться к работе, как показано в следующем примере:Unmatched `end', missing keyword (`do', `def`, `if`, etc.) ? 1 class Dog > 2 defbark > 3 end 4 end
ErrorHighlight
- Теперь он указывает на соответствующие аргументы для TypeError и ArgumentError
test.rb:2:in `+': nil can't be coerced into Integer (TypeError)
sum = ary[0] + ary[1]
^^^^^^
Язык
-
Анонимные аргументы rest и keyword rest теперь можно передавать в качестве аргументов, а не только использовать в параметрах метода. [Feature #18351]
def foo(*) bar(*) end def baz(**) quux(**) end -
Proc, принимающий один позиционный аргумент и ключевые слова, больше не будет выполнять autosplat. [Bug #18633]
proc{|a, **k| a}.call([1, 2]) # Ruby 3.1 и ранее # => 1 # Ruby 3.2 и позже # => [1, 2] -
Порядок вычисления при присваивании констант для констант, заданных в явных объектах, приведен в соответствие с порядком вычисления при присваивании одного атрибута. В этом коде:
foo::BAR = bazfooтеперь вызывается передbaz. Аналогично, для множественных присваиваний константам используется порядок вычисления слева направо. В этом коде:foo1::BAR1, foo2::BAR2 = baz1, baz2Теперь используется следующий порядок вычисления:
foo1foo2baz1baz2
-
Find-паттерн больше не является экспериментальным. [Feature #18585]
-
Методы, принимающие параметр rest (например,
*args) и желающие делегировать аргументы-ключевые слова черезfoo(*args), теперь должны быть помечены какruby2_keywords(если это еще не сделано). Иными словами, все методы, желающие делегировать аргументы-ключевые слова через*args, теперь должны быть помечены какruby2_keywordsбез исключений. Это облегчит переход на другие способы делегирования, когда библиотека сможет требовать Ruby 3+. Ранее флагruby2_keywordsсохранялся, если принимающий метод принимал*args, но это было ошибкой и непоследовательностью. Хороший способ найти потенциально отсутствующиеruby2_keywords— запустить набор тестов, найти последний метод, который должен получать именованные аргументы для каждого места, где тесты не проходят, и использовать тамputs nil, caller, nil. Затем проверьте, что каждый метод/блок в цепочке вызовов, который должен делегировать ключевые слова, правильно помечен какruby2_keywords. [Bug #18625] [Bug #16466]def target(**kw) end # Случайно работало без ruby2_keywords в Ruby 2.7-3.1, ruby2_keywords # требуется в 3.2+. Точно так же (*args, **kwargs) или (...) потребуется # и в #foo, и в #bar при переходе от ruby2_keywords. ruby2_keywords def bar(*args) target(*args) end ruby2_keywords def foo(*args) bar(*args) end foo(k: 1)
Улучшения производительности
MJIT
- Компилятор MJIT переписан на Ruby как
ruby_vm/mjit/compiler. - Компилятор MJIT теперь выполняется в форкнутом процессе, а не в нативном потоке, называемом MJIT-воркером. [Feature #18968]
- В результате Microsoft Visual Studio (MSWIN) больше не поддерживается.
- MinGW больше не поддерживается. [Feature #18824]
- Переименован параметр
--mjit-min-callsв--mjit-call-threshold. - Значение по умолчанию
--mjit-max-cacheвозвращено с 10000 к 100.
PubGrub
-
Bundler 2.4 теперь использует резолвер PubGrub вместо Molinillo.
- PubGrub — это алгоритм решения следующего поколения, используемый пакетным менеджером
pubдля языка программирования Dart. - После этого изменения результаты разрешения зависимостей могут отличаться. Пожалуйста, сообщайте о таких случаях в RubyGems/Bundler issues
- PubGrub — это алгоритм решения следующего поколения, используемый пакетным менеджером
-
RubyGems в Ruby 3.2 все еще использует резолвер Molinillo. Мы планируем заменить его на PubGrub в будущем.
Другие заметные изменения по сравнению с 3.1
- Data
-
Новый базовый класс для представления простых неизменяемых объектов-значений. Этот класс похож на Struct и частично разделяет его реализацию, но имеет более лаконичный и строгий API. [Feature #16122]
Measure = Data.define(:amount, :unit) distance = Measure.new(100, 'km') #=> #<data Measure amount=100, unit="km"> weight = Measure.new(amount: 50, unit: 'kg') #=> #<data Measure amount=50, unit="kg"> weight.with(amount: 40) #=> #<data Measure amount=40, unit="kg"> weight.amount #=> 50 weight.amount = 40 #=> NoMethodError: undefined method `amount='
-
- Hash
Hash#shiftтеперь всегда возвращает nil, если хеш пуст, вместо того чтобы возвращать значение по умолчанию или вызывать proc по умолчанию. [Bug #16908]
- MatchData
- Добавлен метод
MatchData#byteoffset. [Feature #13110]
- Добавлен метод
- Module
- Добавлен метод
Module.used_refinements. [Feature #14332] - Добавлен метод
Module#refinements. [Feature #12737] - Добавлен метод
Module#const_added. [Feature #17881]
- Добавлен метод
- Proc
Proc#dupвозвращает экземпляр подкласса. [Bug #17545]Proc#parametersтеперь принимает ключевое слово lambda. [Feature #15357]
- Refinement
- Добавлен метод
Refinement#refined_class. [Feature #12737]
- Добавлен метод
- RubyVM::AbstractSyntaxTree
- Добавлена опция
error_tolerantдляparse,parse_fileиof. [Feature #19013] С этой опцией:- SyntaxError подавляется
- AST возвращается для некорректного ввода
endдополняется, когда парсер доходит до конца ввода, ноendне хватаетendобрабатывается как ключевое слово на основе отступа
# Без опции error_tolerant root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY) def m a = 10 if end RUBY # => <internal:ast>:33:in `parse': syntax error, unexpected `end' (SyntaxError) # С опцией error_tolerant root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true) def m a = 10 if end RUBY p root # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-4:3> # `end` обрабатывается как ключевое слово на основе отступа root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true) module Z class Foo foo. end def bar end end RUBY p root.children[-1].children[-1].children[-1].children[-2..-1] # => [#<RubyVM::AbstractSyntaxTree::Node:CLASS@2:2-4:5>, #<RubyVM::AbstractSyntaxTree::Node:DEFN@6:2-7:5>] -
Добавлена опция
keep_tokensдляparse,parse_fileиof. [Feature #19070]root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true) root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...] root.tokens.map{_1[2]}.join # => "x = 1 + 2"
- Добавлена опция
- Set
- Set теперь доступен как встроенный класс, без необходимости вызова
require "set". [Feature #16989] В настоящее время он подгружается автоматически через константуSetили вызовEnumerable#to_set.
- Set теперь доступен как встроенный класс, без необходимости вызова
- String
- Добавлены
String#byteindexиString#byterindex. [Feature #13110] - Unicode обновлен до версии 15.0.0, а Emoji — до версии 15.0. [Feature #18639] (также относится к Regexp)
- Добавлен метод
String#bytesplice. [Feature #18598]
- Добавлены
- Struct
-
Класс Struct теперь также может быть инициализирован именованными аргументами без
keyword_init: trueвStruct.new. [Feature #16806]Post = Struct.new(:id, :name) Post.new(1, "hello") #=> #<struct Post id=1, name="hello"> # Начиная с Ruby 3.2 следующий код также работает без keyword_init: true. Post.new(id: 1, name: "hello") #=> #<struct Post id=1, name="hello">
-
Проблемы совместимости
Примечание: Исключая исправления ошибок в функциях.
Удаленные константы
Следующие устаревшие константы были удалены.
FixnumиBignum[Feature #12005]Random::DEFAULT[Feature #17351]Struct::GroupStruct::Passwd
Удаленные методы
Следующие устаревшие методы были удалены.
Dir.exists?[Feature #17391]File.exists?[Feature #17391]Kernel#=~[Feature #15231]Kernel#taint,Kernel#untaint,Kernel#tainted?[Feature #16131]Kernel#trust,Kernel#untrust,Kernel#untrusted?[Feature #16131]
Проблемы совместимости со стандартной библиотекой
Сторонние исходные коды больше не поставляются в комплекте
-
Мы больше не поставляем в комплекте сторонние исходные коды, такие как
libyaml,libffi.-
Исходный код libyaml был удален из psych. Вам может потребоваться установить
libyaml-devв Ubuntu/Debian. Имя пакета отличается для каждой платформы. -
Входящий в комплект исходный код libffi также удален из
fiddle.
-
-
Psych и fiddle поддерживали статические сборки с конкретными версиями исходников libyaml и libffi. Вы можете собрать psych с libyaml-0.2.5 следующим образом:
$ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5И вы можете собрать fiddle с libffi-3.4.4 следующим образом:
$ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
Обновления C API
Обновленные C API
Следующие API были обновлены.
- Обновление PRNG
rb_random_interface_tобновлен и получил версию. Библиотеки расширений, использующие этот интерфейс, должны быть собраны для старых версий. Также необходимо определить функциюinit_int32.
Удаленные C API
Следующие устаревшие API были удалены.
- Переменная
rb_cData. - Функции “taintedness” и “trustedness”. [Feature #16131]
Обновления стандартной библиотеки
-
Bundler
- Добавлена поддержка
--ext=rustвbundle gemдля создания простых гемов с расширениями на Rust. [GH-rubygems-6149] - Ускорена клонирование git-репозиториев [GH-rubygems-4475]
- Добавлена поддержка
-
RubyGems
- Добавлена поддержка mswin для cargo builder. [GH-rubygems-6167]
-
ERB
ERB::Util.html_escapeтеперь работает быстрее, чемCGI.escapeHTML.- Он больше не выделяет объект String, если не требуется экранирование символов.
- Он пропускает вызов метода
#to_s, если аргумент уже является строкой. ERB::Escape.html_escapeдобавлен как псевдоним дляERB::Util.html_escape, который не подвергался monkey-patching со стороны Rails.
-
IRB
- Добавлены команды интеграции с
debug.gem:debug,break,catch,next,delete,step,continue,finish,backtrace,info.- Они работают, даже если в вашем Gemfile нет гема
debug. - Смотрите также: Что нового в IRB в Ruby 3.2?
- Они работают, даже если в вашем Gemfile нет гема
- Добавлено больше команд и функций в стиле Pry.
- Добавлены команды
editиshow_cmds(аналогhelpв Pry). lsпринимает опции-gили-Gдля фильтрации вывода.show_sourceявляется псевдонимом для$и принимает ввод без кавычек.whereamiявляется псевдонимом для@.
- Добавлены команды
- Добавлены команды интеграции с
-
Следующие встроенные гемы были обновлены.
- RubyGems 3.4.1
- abbrev 0.1.1
- benchmark 0.2.1
- bigdecimal 3.1.3
- bundler 2.4.1
- cgi 0.3.6
- csv 3.2.6
- date 3.3.3
- delegate 0.3.0
- did_you_mean 1.6.3
- digest 3.1.1
- drb 2.1.1
- english 0.7.2
- erb 4.0.2
- error_highlight 0.5.1
- etc 1.4.2
- fcntl 1.0.2
- fiddle 1.1.1
- fileutils 1.7.0
- forwardable 1.3.3
- getoptlong 0.2.0
- io-console 0.6.0
- io-nonblock 0.2.0
- io-wait 0.3.0
- ipaddr 1.2.5
- irb 1.6.2
- json 2.6.3
- logger 1.5.3
- mutex_m 0.1.2
- net-http 0.3.2
- net-protocol 0.2.1
- nkf 0.1.2
- open-uri 0.3.0
- open3 0.1.2
- openssl 3.1.0
- optparse 0.3.1
- ostruct 0.5.5
- pathname 0.2.1
- pp 0.4.0
- pstore 0.1.2
- psych 5.0.1
- racc 1.6.2
- rdoc 6.5.0
- readline-ext 0.1.5
- reline 0.3.2
- resolv 0.2.2
- resolv-replace 0.1.1
- securerandom 0.2.2
- set 1.0.3
- stringio 3.0.4
- strscan 3.0.5
- syntax_suggest 1.0.2
- syslog 0.1.1
- tempfile 0.1.3
- time 0.2.1
- timeout 0.3.1
- tmpdir 0.1.3
- tsort 0.1.1
- un 0.2.1
- uri 0.12.0
- weakref 0.1.2
- win32ole 1.8.9
- yaml 0.2.1
- zlib 3.0.0
-
Следующие поставляемые гемы были обновлены.
- minitest 5.16.3
- power_assert 2.0.3
- test-unit 3.5.7
- net-ftp 0.2.0
- net-imap 0.3.3
- net-pop 0.1.2
- net-smtp 0.3.3
- rbs 2.8.2
- typeprof 0.21.3
- debug 1.7.1
Подробности о встроенных или поставляемых гемах смотрите в релизах на GitHub, например, релизы logger на GitHub, или в заметках о релизе.
Для получения подробной информации смотрите NEWS или журнал коммитов.
С учетом этих изменений было изменено 3048 файлов, добавлено 218253 строк(+), удалено 131067 строк(-) с момента выхода Ruby 3.1.0!
Счастливого Рождества, веселых праздников и приятного программирования на Ruby 3.2!
Скачать
-
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz
SIZE: 20440715 SHA1: fb4ab2ceba8bf6a5b9bc7bf7cac945cc94f94c2b SHA256: daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272 SHA512: 94203051d20475b95a66660016721a0457d7ea57656a9f16cdd4264d8aa6c4cd8ea2fab659082611bfbd7b00ebbcf0391e883e2ebf384e4fab91869e0a877d35 -
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.xz
SIZE: 15058364 SHA1: bcdae07183d66fd902cb7bf995545a472d2fefea SHA256: d2f4577306e6dd932259693233141e5c3ec13622c95b75996541b8d5b68b28b4 SHA512: 733ecc6709470ee16916deeece9af1c76220ae95d17b2681116aff7f381d99bc3124b1b11b1c2336b2b29e468e91b90f158d5ae5fca810c6cf32a0b6234ae08e -
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.zip
SIZE: 24583271 SHA1: 581ec7b9289c2a85abf4f41c93993ecaa5cf43a5 SHA256: cca9ddbc958431ff77f61948cb67afa569f01f99c9389d2bbedfa92986c9ef09 SHA512: b7d2753825cc0667e8bb391fc7ec59a53c3db5fa314e38eee74b6511890b585ac7515baa2ddac09e2c6b6c42b9221c82e040af5b39c73e980fbd3b1bc622c99d
Что такое Ruby
Ruby был впервые разработан Matz (Yukihiro Matsumoto) в 1993 году и сейчас развивается как open source. Он работает на многих платформах и используется по всему миру, особенно для веб-разработки.
Последние новости
Вышел Ruby 4.0.3
Вышел Ruby 4.0.3.
Опубликовал k0kubun 21-04-2026
Вышел Ruby 3.2.11
Вышел Ruby 3.2.11. В этот релиз вошло обновление гема zlib, устраняющее CVE-2026-27820.
Опубликовал hsbt 27-03-2026
Вышел Ruby 3.3.11
Вышел Ruby 3.3.11. В этот релиз вошло обновление гема zlib, устраняющее CVE-2026-27820, а также некоторые исправления ошибок.
Опубликовал hsbt 26-03-2026
Вышел Ruby 4.0.2
Вышел Ruby 4.0.2.
Опубликовал k0kubun 16-03-2026