Вийшов Ruby 3.2.0
Опублікував naruse 25-12-2022
Переклав: Andrii Furmanets
Раді повідомити про вихід 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 playground. Тепер ви можете спробувати оригінальний CRuby у вашому веб-браузері.
Технічні моменти
Сьогоднішні WASI та WebAssembly самі по собі не мають деяких можливостей для реалізації Fiber, винятків та GC, оскільки вони все ще розвиваються, а також з міркувань безпеки. Тому CRuby заповнює прогалину, використовуючи Asyncify, який є технікою бінарного перетворення для контролю виконання в userland.
Крім того, ми побудували 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 і має приблизно в 1/3 менше накладних витрат пам’яті.
- Загалом 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, тепер доступна в release збірках.- Просто запустіть ruby з
--yjit-stats, щоб обчислити та вивести статистику (спричиняє деякі накладні витрати під час виконання).
- Просто запустіть ruby з
- YJIT тепер оптимізовано для використання переваг форм об’єктів. [Feature #18776]
- Використовуйте переваги дрібнозернистої інвалідації констант, щоб інвалідувати менше коду при визначенні нових констант. [Feature #18589]
- Типове значення
--yjit-exec-mem-sizeзмінено на 64 (MiB). - Типове значення
--yjit-call-thresholdзмінено на 30.
Покращення Regexp проти ReDoS
Відомо, що зіставлення Regexp може займати неочікувано довго. Якщо ваш код намагається зіставити можливо неефективний Regexp з ненадійним вводом, зловмисник може використати це для ефективної Denial of Service (так звана Regular expression DoS, або ReDoS).
Ми впровадили два покращення, які значно пом’якшують ReDoS.
Покращений алгоритм зіставлення Regexp
Починаючи з Ruby 3.2, алгоритм зіставлення Regexp значно покращено за допомогою техніки мемоїзації.
# Це зіставлення займає 10 сек. у Ruby 3.1, і 0.003 сек. у Ruby 3.2
/^a*b?a*$/ =~ "a" * 50000 + "x"

Покращений алгоритм зіставлення дозволяє більшості зіставлень Regexp (близько 90% у наших експериментах) завершуватися за лінійний час.
Ця оптимізація може споживати пам’ять, пропорційну довжині вводу для кожного зіставлення. Ми не очікуємо виникнення практичних проблем, оскільки це виділення пам’яті зазвичай відкладене, і нормальне зіставлення Regexp повинно споживати максимум у 10 разів більше пам’яті, ніж довжина вводу. Якщо у вас закінчується пам’ять під час зіставлення Regexps у реальному застосунку, будь ласка, повідомте про це.
Оригінальна пропозиція: https://bugs.ruby-lang.org/issues/19104
Таймаут Regexp
Оптимізацію вище не можна застосувати до деяких видів регулярних виразів, таких як ті, що включають розширені можливості (наприклад, зворотні посилання або look-around), або з великою фіксованою кількістю повторень. Як запасна міра, також впроваджено функцію таймауту для зіставлень Regexp.
Regexp.timeout = 1.0
/^a*b?a*()\1$/ =~ "a" * 50000 + "x"
#=> Regexp::TimeoutError викликається через одну секунду
Зверніть увагу, що Regexp.timeout є глобальною конфігурацією. Якщо ви хочете використовувати різні налаштування таймауту для деяких спеціальних Regexps, ви можете використати ключове слово timeout для Regexp.new.
Regexp.timeout = 1.0
# Цей regexp не має таймауту
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, який приймає один позиційний аргумент та ключові слова, більше не буде автоматично розпаковуватися. [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 worker. [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 все ще використовує резолвер Molinillo в Ruby 3.2. Ми плануємо замінити його на 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, якщо хеш порожній, замість повернення значення за замовчуванням або виклику default 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]
Проблеми сумісності стандартної бібліотеки
Більше не bundle сторонніх джерел
-
Ми більше не bundle сторонні джерела, такі як
libyaml,libffi.-
Джерело libyaml видалено з psych. Вам може знадобитися встановити
libyaml-devна платформі Ubuntu/Debian. Назва пакета відрізняється для кожної платформи. -
Bundled джерело 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 для створення простих gems з розширеннями 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, коли аргумент вже є String. ERB::Escape.html_escapeдодано як псевдонім дляERB::Util.html_escape, який не був monkey-patched Rails.
-
IRB
- Додано команди інтеграції debug.gem:
debug,break,catch,next,delete,step,continue,finish,backtrace,info- Вони працюють навіть якщо у вас немає
gem "debug"у вашому Gemfile. - Див. також: Що нового в IRB Ruby 3.2?
- Вони працюють навіть якщо у вас немає
- Додано більше команд та можливостей, подібних до Pry.
- Додано
editтаshow_cmds(якhelpу Pry). lsприймає опцію-gабо-Gдля фільтрації виводу.show_sourceє псевдонімом від$та приймає нецитовані входи.whereamiє псевдонімом від@.
- Додано
- Додано команди інтеграції debug.gem:
-
Оновлено наступні default gems.
- 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
-
Оновлено наступні bundled gems.
- 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 releases, такі як GitHub Releases of logger, або changelog для деталей default gems або bundled gems.
Див. 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 3.2.10
Вийшов Ruby 3.2.10.
Опублікував hsbt 14-01-2026
Вийшов Ruby 4.0.1
Вийшов Ruby 4.0.1.
Опублікував k0kubun 13-01-2026
Вийшов Ruby 4.0.0
Ми раді повідомити про випуск Ruby 4.0.0. Ruby 4.0 представляє “Ruby Box” та “ZJIT”, а також додає багато покращень.
Опублікував naruse 25-12-2025
Новий вигляд документації Ruby
Слідом за ре-дизайном ruby-lang.org, ми маємо більше новин, щоб відсвяткувати 30-річчя Ruby: docs.ruby-lang.org має повністю новий вигляд завдяки Aliki — новій темі за замовчуванням для...
Опублікував Stan Lo 23-12-2025