Ditulis oleh naruse tanggal 2022-12-25
Diterjemahkan oleh meisyal
Kami dengan senang hati mengumumkan rilis dari Ruby 3.2.0. Ruby 3.2 menambahkan banyak fitur dan memperbaiki kinerja.
Dukungan WebAssembly berbasis WASI
Ini adalah sebuah port awal dari dukungan WebAssembly berbasis WASI. Port ini memperbolehkan sebuah CRuby binary agar tersedia pada web browser, Serverless Edge environment, atau WebAssembly/WASI embedder lainnya. Saat ini, port melewatkan rangkaian tes dasar dan bootstrap dengan tidak menggunakan Thread API.
Latar Belakang
WebAssembly (Wasm) semula diperkenalkan untuk menjalankan program dengan aman dan cepat pada web browser. Sasaran - menjalankan program secara efisien dengan keamanan pada berbagai macam environment - diinginkan sejak lama tidak hanya oleh web, akan tetapi oleh aplikasi umum.
WASI (The WebAssembly System Interface) didesain untuk kasus penggunaan tersebut. Walaupun aplikasi perlu berkomunikasi dengan sistem operasi, WebAssembly berjalan pada sebuah virtual machine yang mana tidak memiliki sebuah system interface. WASI menstandarkannya.
Dukungan WebAssembly/WASI pada Ruby bermaksud untuk memanfaatkan proyek tersebut. Ini memperbolehkan pengembang Ruby untuk memprogram aplikasi yang berjalan pada platform yang menjanjikan.
Kasus penggunaan
Dukungan ini mendorong pengembang untuk memanfaatkan CRuby pada WebAssembly environment. Sebuah contoh kasus penggunaan adalah dukungan CRuby pada TryRuby playground. Sekarang Anda bisa mencoba CRuby pada web browser.
Poin teknis
WASI dan WebAssembly saat ini memiliki beberapa fitur yang tidak didukung, seperti mengimplementasikan Fiber, exception, dan GC karena ini masih terus berkembang dan juga untuk alasan keamanan. Oleh sebab itu, CRuby mengisi gap tersebut dengan menggunakan Asyncify, yang mana adalah sebuah teknik transformasi binary untuk mengendalikan eksekusi pada lingkungan pengguna.
Sebagai tambahan, kami membangun sebuah VFS di atas WASI sehingga kami dapat mengemas aplikasi Ruby ke dalam sebuah berkas .wasm dengan mudah. Ini membuat distribusi aplikasi Ruby sedikit lebih mudah.
Tautan terkait
Production-ready YJIT
- YJIT tidak lagi eksperimental
- Telah dites dengan beban production selama lebih dari satu tahun dan terbukti cukup stabil.
- YJIT sekarang mendukung baik CPU x86-64 maupun arm64/aarch64 pada Linux, MacOS, BSD, dan platform UNIX lainnya.
- Rilis ini membawa dukungan untuk Apple M1/M2, AWS Graviton, Raspberry Pi 4, dan lebih banyak lagi.
- Membangun YJIT sekarang membutuhkan Rust 1.58.0+. [Feature #18481]
- Untuk memastikan CRuby dibangun dengan YJIT, mohon pasang
rustc
>= 1.58.0 sebelum menjalankan skrip./configure
. - Mohon hubungi tim YJIT jika Anda menemui masalah.
- Untuk memastikan CRuby dibangun dengan YJIT, mohon pasang
- YJIT 3.2 lebih cepat dibandingkan 3.1 dan memiliki sekitar 1/3 memory overhead lebih banyak.
- Secara keseluruhan YJIT 41% lebih cepat (geometric mean) daripada Ruby interpreter pada yjit-bench.
- Physical memory untuk kode JIT dialokasikan dengan malas. Tidak seperti Ruby 3.1,
RSS dari sebuah proses Ruby diminimalisasi karena virtual memory page dialokasikan
oleh
--yjit-exec-mem-size
tidak akan dipetakan ke physical memory page hingga sepenuhnya dibutuhkan oleh kode JIT. - Mengenalkan Code GC yang membebaskan semua code page ketika memori yang
dikonsumsi oleh kode JIT mencapai
--yjit-exec-mem-size
. RubyVM::YJIT.runtime_stats
mengembalikan metrik Code GC sebagai tambahaninline_code_size
danoutlined_code_size
keys:code_gc_count
,live_page_count
,freed_page_count
, danfreed_code_size
.
- Statistik yang diproduksi oleh
RubyVM::YJIT.runtime_stats
sekarang tersedia pada release build.- Jalankan ruby dengan
--yjit-stats
untuk menghitung dan menimbun statistik (menimbulkan sedikit run-time overhead).
- Jalankan ruby dengan
- YJIT sekarang dioptimalkan untuk mengambil kelebihan dari object shape. [Feature #18776]
- Mengambil kelebihan dari finer-grained constant invalidation untuk tidak memvalidasi kode yang lebih sedikit ketika mendefinisikan konstanta baru. [Feature #18589]
- Nilai default dari
--yjit-exec-mem-size
diubah menjadi 64 (MiB). - Nilai default dari
--yjit-call-threshold
diubah menjadi 30.
Peningkatan Regexp melawan ReDoS
Diketahui bahwa Regexp matching mungkin membutuhkan waktu yang lama. Jika kode Anda mencoba untuk mencocokkan sebuah Regexp yang tidak efisien dengan sebuah masukan yang tidak terpercaya, seorang penyerang bisa mengeksploitasi ini untuk Denial of Service yang efisien (disebut Regular expression DoS atau ReDoS).
Kami telah memperkenalkan dua peningkatan untuk memitigasi ReDoS secara signifikan.
Peningkatan algoritma Regexp matching
Sejak Ruby 3.2, algoritma Regexp matching telah ditingkatkan dengan menggunakan teknik memoization.
# Regexp matching ini membutuhkan waktu 10 detik pada Ruby 3.1 dan 0.003 detik pada Ruby 3.2
/^a*b?a*$/ =~ "a" * 50000 + "x"
Peningkatan algoritma matching memperbolehkan eksekusi (sekitar 90% dari eksperimen kami) selesai dalam waktu linier.
Peningkatan ini akan mengonsumsi memori sepadan dengan panjang masukan untuk setiap matching. Kami mengharapkan tidak ada masalah yang muncul karena alokasi memori biasanya tertunda dan sebuah Regexp matching biasa mengonsumsi paling banyak 10 kali memori sepanjang masukan. Jika Anda kehabisan memori ketika mengeksekusi pada sebuah aplikasi, mohon laporkan.
Proposal asli di https://bugs.ruby-lang.org/issues/19104
Regexp timeout
Peningkatan di atas tidak dapat diterapkan pada regular expression tertentu, seperti mengandung fitur lanjutan (contoh, back-references atau look-around), atau dengan pengulangan dalam jumlah tetap yang sangat besar. Sebagai penanganan, Sebuah fitur timeout pada Regexp matching juga diperkenalkan.
Regexp.timeout = 1.0
/^a*b?a*()\1$/ =~ "a" * 50000 + "x"
#=> Regexp::TimeoutError akan muncul dalam waktu satu detik
Catat bahwa Regexp.timeout
adalah sebuah pengaturan global. Jika Anda ingin
menggunakan pengaturan yang berbeda untuk Regexp tertentu, Anda bisa
menggunakan kata kunci timeout
pada Regexp.new
.
Regexp.timeout = 1.0
# regexp ini tidak memiliki timeout
long_time_re = Regexp.new('^a*b?a*()\1$', timeout: Float::INFINITY)
long_time_re =~ "a" * 50000 + "x" # tidak pernah diinterupsi
Proposal asli di https://bugs.ruby-lang.org/issues/17837.
Fitur penting lainnya
SyntaxSuggest
-
Fitur
syntax_suggest
(dahuludead_end
) terintegrasi dengan Ruby. Ini membantu Anda untuk menemukan posisi error, seperti kelupaan atau kelebihanend
, dengan cepat, seperti contoh berikut:Ketidakcocokan `end', kata kunci hilang (`do', `def`, `if`, etc.) ? 1 class Dog > 2 defbark > 4 end 5 end
ErrorHighlight
- Saat ini, fitur menunjuk pada argumen yang relevan pada TypeError dan ArgumentError
test.rb:2:in `+': nil can't be coerced into Integer (TypeError)
sum = ary[0] + ary[1]
^^^^^^
Bahasa
-
Argumen dari anonymous rest dan keyword rest sekarang dapat dilewatkan sebagai argumen daripada sekadar digunakan pada parameter method. [Feature #18351]
def foo(*) bar(*) end def baz(**) quux(**) end
-
Sebuah proc yang menerima sebuah positional argument dan keyword tidak akan lagi autosplat. [Bug #18633]
proc{|a, **k| a}.call([1, 2]) # Ruby 3.1 dan sebelumnya # => 1 # Ruby 3.2 dan setelahnya # => [1, 2]
-
Urutan evaluasi dari constant assignment pada objek eksplisit telah dibuat konsisten dengan urutan evaluasi tunggal. Pada kode berikut:
foo::BAR = baz
foo
sekarang dipanggil sebelumbaz
. Demikian pula, untuk multiple assignment pada constant, urutan evaluasi left-to-right digunakan. Pada kode berikut:foo1::BAR1, foo2::BAR2 = baz1, baz2
Urutan evaluasi berikut sekarang digunakan:
foo1
foo2
baz1
baz2
-
Pencarian pattern tidak lagi eksperimental. [Feature #18585]
-
Method mengambil sebuah parameter lain (seperti
*args
) dan mengharapkan untuk mendelegasikan keyword argument melaluifoo(*args)
sekarang harus ditandai denganruby2_keywords
(jika belum terjadi). Dengan kata lain, semua method mengharapkan untuk mendelegasikan keyword argument melalui*args
sekarang harus ditandai denganruby2_keywords
, tanpa kecuali. Ini akan membuat transisi lebih mudah ke bentuk delegasi lain saat sebuah pustaka memerlukan Ruby 3+. Sebelumnya, penandaruby2_keywords
dijaga jika method penerima mengambil*args
, tetapi ini adalah sebuah bug dan ketidakkonsistenan. Sebuah teknik yang bagus untuk menemukan potensi hilang dariruby2_keywords
adalah menjalankan rangkaian tes, dimana pun tes gagal cari method terakhir yang harus menerima keyword argument, menggunakanputs nil, caller, nil
, dan mengecek setiap method/block pada rantai pemanggilan yang harus mendelegasikan keyword ditandai dengan benar sebagairuby2_keywords
. [Bug #18625] [Bug #16466]def target(**kw) end # Secara tidak sengaja, berjalan tanpa ruby2_keywords pada Ruby 2.7-3.1, # ruby2_keywords dibutuhkan pada 3.2+. Sama halnya dengan (*args, **kwargs) # atau (...) yang juga dibutuhkan baik #foo maupun #bar ketika migrasi # dari ruby2_keywords. ruby2_keywords def bar(*args) target(*args) end ruby2_keywords def foo(*args) bar(*args) end foo(k: 1)
Perbaikan kinerja
MJIT
- MJIT compiler diimplementasikan kembali pada Ruby sebagai pustaka standar
ruby_vm/mjit/compiler
. - MJIT compiler dieksekusi dalam sebuah fork dari proses Ruby ketimbang
mengeksekusi dalam sebuah native thread yang dikenal MJIT worker. [Feature #18968]
- Akibatnya, Microsoft Visual Studio (MSWIN) tidak lagi didukung.
- MinGW tidak lagi didukung. [Feature #18824]
- Mengganti nama
--mjit-min-calls
menjadi--mjit-call-threshold
. - Mengubah nilai default
--mjit-max-cache
dari 10000 ke 100.
PubGrub
-
Bundler 2.4 sekarang menggunakan PubGrub resolver ketimbang Molinillo.
- PubGrub adalah algoritma generasi berikutnya yang digunakan oleh
pub
package manager untuk bahasa pemograman Dart. - Anda mungkin mendapatkan hasil yang berbeda setelah perubahan ini. Mohon laporkan masalah tersebut ke RubyGems/Bundler issues
- PubGrub adalah algoritma generasi berikutnya yang digunakan oleh
-
RubyGems masih menggunakan Molinillo resolver pada Ruby 3.2. Kami merencanakan untuk mengganti dengan PubGrub di masa yang akan datang.
Perubahan penting lainnya sejak 3.1
- Data
-
Kelas inti baru untuk merepresentasikan nilai dari objek yang immutable. Kelas ini mirip dengan Struct dan sebagian berbagi sebuah implementasi, tetapi lebih memiliki API yang lean dan strict. [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
sekarang selalu mengembalikan nil jika hash kosong ketimbang mengembalikan nilai default atau memanggil default proc. [Bug #16908]
- MatchData
MatchData#byteoffset
telah ditambahkan. [Feature #13110]
- Module
Module.used_refinements
telah ditambahkan. [Feature #14332]Module#refinements
telah ditambahkan. [Feature #12737]Module#const_added
telah ditambahkan. [Feature #17881]
- Proc
Proc#dup
mengembalikan sebuah instance dari subclass. [Bug #17545]Proc#parameters
sekarang menerima kata kunci lambda. [Feature #15357]
- Refinement
Refinement#refined_class
telah ditambahkan. [Feature #12737]
- RubyVM:AbstractSyntaxTree
- Menambahkan opsi
error_tolerant
padaparse
,parse_file
, danof
. [Feature #19013] Dengan opsi ini- SyntaxError disembunyikan
- AST dikembalikan untuk masukan yang tidak valid
end
disempurnakan ketika sebuah parser menjangkau akhir dari masukan, tetapiend
tidak cukupend
dianggap sebagai kata kunci berdasarkan lekukan baris
# Tanpa opsi error_tolerant root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY) def m a = 10 if end RUBY # => <internal:ast>:33:in `parse': syntax error, unexpected `end' (SyntaxError) # Dengan opsi 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` dianggap sebagai kata kunci berdasarkan lekukan baris 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>]
-
Menambahkan opsi
keep_tokens
padaparse
,parse_file
danof
. [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"
- Menambahkan opsi
- Set
- Set sekarang tersedia sebagai sebuah builtin class tanpa membutuhkan
require "set"
. [Feature #16989] Ini dimuatkan secara otomatis melaluiSet
constant atau sebuah pemanggilanEnumerable#to_set
.
- Set sekarang tersedia sebagai sebuah builtin class tanpa membutuhkan
- String
String#byteindex
danString#byterindex
telah ditambahkan. [Feature #13110]- Memperbarui versi Unicode ke 15.0.0 dan Emoji ke 15.0. [Feature #18639] (juga diaplikasikan pada Regexp)
String#bytesplice
telah ditambahkan. [Feature #18598]
- Struct
-
Sebuah class Struct juga dapat diinisialisasi dengan argumen keyword tanpa
keyword_init: true
padaStruct.new
[Feature #16806]Post = Struct.new(:id, :name) Post.new(1, "hello") #=> #<struct Post id=1, name="hello"> # Mulai Ruby 3.2, kode berikut bekerja tanpa keyword_init: true. Post.new(id: 1, name: "hello") #=> #<struct Post id=1, name="hello">
-
Isu kompatibilitas
Catatan: tidak termasuk perbaikan bug.
Constant terhapus
Berikut ini adalah constant yang telah dihapus.
Fixnum
danBignum
[Feature #12005]Random::DEFAULT
[Feature #17351]Struct::Group
Struct::Passwd
Method terhapus
Berikut ini adalah method yang telah dihapus.
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]
Isu kompatibilitas Stdlib
Tidak lagi membundel sumber pihak ketiga
-
Kami tidak lagi membundel sumber dari pihak ketiga, seperti
libyaml
,libffi
.-
libyaml telah dihapus dari psych. Anda mungkin membutuhkan untuk memasang
libyaml-dev
dengan Ubuntu/Debian platform. Nama package berbeda untuk setiap platform. -
libffi juga telah dihapus dari
fiddle
-
-
Psych dan fiddle mendukung static build dengan versi spesifik dari libyaml dan libffi. Anda dapat membangun psych dengan libyaml-0.2.5 seperti ini:
$ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5
Dan Anda dapat membangun fiddle dengan libffi-3.4.4:
$ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
Pembaruan C API
C API diperbarui
Berikut ini adalah API yang telah diperbarui.
- Pembaruan PRNG
rb_random_interface_t
diperbarui dan diberikan versi. Pustaka extension yang menggunakan interface ini dan untuk versi lama.init_int32
juga perlu didefinisikan.
C API terhapus
Berikut ini adalah API yang telah dihapus.
- Variabel
rb_cData
. - Function “taintedness” dan “trustedness”. [Feature #16131]
Pembaruan pustaka standar
-
Bundler
- Menambahkan dukungan –ext=rust untuk membundel gem dengan ekstensi Rust. [GH-rubygems-6149]
- Membuat salinan git repo lebih cepat [GH-rubygems-4475]
-
RubyGems
- Menambahkan dukungan mswin untuk cargo builder. [GH-rubygems-6167]
-
ERB
ERB::Util.html_escape
dibuat lebih cepat dibandingkanCGI.escapeHTML
.- Ini tidak lagi mengalokasikan sebuah objek String ketika tidak ada karakter yang perlu diloloskan.
- Ini mengabaikan pemanggilan method
#to_s
jika sebuah argumen sudah berupa String. ERB::Escape.html_escape
ditambahkan sebagai sebuah alias untukERB::Util.html_escape
, yang mana belum di-monkey-patch oleh Rails.
- IRB
- Perintah integrasi debug.gem telah ditambahkan:
debug
,break
,catch
,next
,delete
,step
,continue
,finish
,backtrace
,info
- Perintah ini bekerja walaupun Anda tidak memiliki
gem "debug"
pada Gemfile Anda. - Lihat juga: What’s new in Ruby 3.2’s IRB?
- Perintah ini bekerja walaupun Anda tidak memiliki
- Perintah dan fitur Pry-like lainnya telah ditambahkan.
edit
danshow_cmds
(sepertihelp
pada Pry) ditambahkan.ls
mengambil opsi-g
atau-G
untuk menyaring keluaran.show_source
adalah alias dari$
dan menerima masukan tanpa kutipan.whereami
adalah alias dari@
.
- Perintah integrasi debug.gem telah ditambahkan:
-
Berikut ini adalah default gem yang telah diperbarui.
- 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
-
Berikut ini adalah bundled gem yang telah diperbarui.
- 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
Lihat rilis GitHub seperti GitHub Releases of logger atau changelog untuk detail dari default atau bundled gem.
Lihat NEWS atau commit logs untuk lebih detail.
Dengan perubahan tersebut, 3048 berkas berubah, 218253 sisipan(+), 131067 terhapus(-) sejak Ruby 3.1.0!
Selamat natal, selamat berlibur, dan nikmati memprogram dengan Ruby 3.2!
Unduh
-
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
Apa itu Ruby
Ruby pertama kali dikembangkan oleh Matz (Yukihiro Matsumoto) pada 1993 dan sekarang dikembangkan sebagai Open Source. Ruby berjalan pada berbagai platform dan digunakan di seluruh dunia, khususnya pengembangan web.